MIR: Allow targets to serialize MachineFunctionInfo
This has been a very painful missing feature that has made producing
reduced testcases difficult. In particular the various registers
determined for stack access during function lowering were necessary to
avoid undefined register errors in a large percentage of
cases. Implement a subset of the important fields that need to be
preserved for AMDGPU.
Most of the changes are to support targets parsing register fields and
properly reporting errors. The biggest sort-of bug remaining is for
fields that can be initialized from the IR section will be overwritten
by a default initialized machineFunctionInfo section. Another
remaining bug is the machineFunctionInfo section is still printed even
if empty.
llvm-svn: 356215
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
index 593ec57..971944b 100644
--- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp
@@ -10,7 +10,7 @@
//
//===----------------------------------------------------------------------===//
-#include "MIParser.h"
+#include "llvm/CodeGen/MIRParser/MIParser.h"
#include "MILexer.h"
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/APSInt.h"
diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.h b/llvm/lib/CodeGen/MIRParser/MIParser.h
deleted file mode 100644
index dc858a9..0000000
--- a/llvm/lib/CodeGen/MIRParser/MIParser.h
+++ /dev/null
@@ -1,233 +0,0 @@
-//===- MIParser.h - Machine Instructions Parser -----------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file declares the function that parses the machine instructions.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_LIB_CODEGEN_MIRPARSER_MIPARSER_H
-#define LLVM_LIB_CODEGEN_MIRPARSER_MIPARSER_H
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/CodeGen/MachineMemOperand.h"
-#include "llvm/Support/Allocator.h"
-
-namespace llvm {
-
-class MachineBasicBlock;
-class MachineFunction;
-class MDNode;
-class RegisterBank;
-struct SlotMapping;
-class SMDiagnostic;
-class SourceMgr;
-class StringRef;
-class TargetRegisterClass;
-class TargetSubtargetInfo;
-
-struct VRegInfo {
- enum uint8_t {
- UNKNOWN, NORMAL, GENERIC, REGBANK
- } Kind = UNKNOWN;
- bool Explicit = false; ///< VReg was explicitly specified in the .mir file.
- union {
- const TargetRegisterClass *RC;
- const RegisterBank *RegBank;
- } D;
- unsigned VReg;
- unsigned PreferredReg = 0;
-};
-
-using Name2RegClassMap = StringMap<const TargetRegisterClass *>;
-using Name2RegBankMap = StringMap<const RegisterBank *>;
-
-struct PerTargetMIParsingState {
-private:
- const TargetSubtargetInfo &Subtarget;
-
- /// Maps from instruction names to op codes.
- StringMap<unsigned> Names2InstrOpCodes;
-
- /// Maps from register names to registers.
- StringMap<unsigned> Names2Regs;
-
- /// Maps from register mask names to register masks.
- StringMap<const uint32_t *> Names2RegMasks;
-
- /// Maps from subregister names to subregister indices.
- StringMap<unsigned> Names2SubRegIndices;
-
- /// Maps from target index names to target indices.
- StringMap<int> Names2TargetIndices;
-
- /// Maps from direct target flag names to the direct target flag values.
- StringMap<unsigned> Names2DirectTargetFlags;
-
- /// Maps from direct target flag names to the bitmask target flag values.
- StringMap<unsigned> Names2BitmaskTargetFlags;
-
- /// Maps from MMO target flag names to MMO target flag values.
- StringMap<MachineMemOperand::Flags> Names2MMOTargetFlags;
-
- /// Maps from register class names to register classes.
- Name2RegClassMap Names2RegClasses;
-
- /// Maps from register bank names to register banks.
- Name2RegBankMap Names2RegBanks;
-
- void initNames2InstrOpCodes();
- void initNames2Regs();
- void initNames2RegMasks();
- void initNames2SubRegIndices();
- void initNames2TargetIndices();
- void initNames2DirectTargetFlags();
- void initNames2BitmaskTargetFlags();
- void initNames2MMOTargetFlags();
-
- void initNames2RegClasses();
- void initNames2RegBanks();
-
-public:
- /// Try to convert an instruction name to an opcode. Return true if the
- /// instruction name is invalid.
- bool parseInstrName(StringRef InstrName, unsigned &OpCode);
-
- /// Try to convert a register name to a register number. Return true if the
- /// register name is invalid.
- bool getRegisterByName(StringRef RegName, unsigned &Reg);
-
- /// Check if the given identifier is a name of a register mask.
- ///
- /// Return null if the identifier isn't a register mask.
- const uint32_t *getRegMask(StringRef Identifier);
-
- /// Check if the given identifier is a name of a subregister index.
- ///
- /// Return 0 if the name isn't a subregister index class.
- unsigned getSubRegIndex(StringRef Name);
-
- /// Try to convert a name of target index to the corresponding target index.
- ///
- /// Return true if the name isn't a name of a target index.
- bool getTargetIndex(StringRef Name, int &Index);
-
- /// Try to convert a name of a direct target flag to the corresponding
- /// target flag.
- ///
- /// Return true if the name isn't a name of a direct flag.
- bool getDirectTargetFlag(StringRef Name, unsigned &Flag);
-
- /// Try to convert a name of a bitmask target flag to the corresponding
- /// target flag.
- ///
- /// Return true if the name isn't a name of a bitmask target flag.
- bool getBitmaskTargetFlag(StringRef Name, unsigned &Flag);
-
- /// Try to convert a name of a MachineMemOperand target flag to the
- /// corresponding target flag.
- ///
- /// Return true if the name isn't a name of a target MMO flag.
- bool getMMOTargetFlag(StringRef Name, MachineMemOperand::Flags &Flag);
-
- /// Check if the given identifier is a name of a register class.
- ///
- /// Return null if the name isn't a register class.
- const TargetRegisterClass *getRegClass(StringRef Name);
-
- /// Check if the given identifier is a name of a register bank.
- ///
- /// Return null if the name isn't a register bank.
- const RegisterBank *getRegBank(StringRef Name);
-
- PerTargetMIParsingState(const TargetSubtargetInfo &STI)
- : Subtarget(STI) {
- initNames2RegClasses();
- initNames2RegBanks();
- }
-
- ~PerTargetMIParsingState() = default;
-
- void setTarget(const TargetSubtargetInfo &NewSubtarget);
-};
-
-struct PerFunctionMIParsingState {
- BumpPtrAllocator Allocator;
- MachineFunction &MF;
- SourceMgr *SM;
- const SlotMapping &IRSlots;
- PerTargetMIParsingState &Target;
-
- DenseMap<unsigned, MachineBasicBlock *> MBBSlots;
- DenseMap<unsigned, VRegInfo*> VRegInfos;
- StringMap<VRegInfo*> VRegInfosNamed;
- DenseMap<unsigned, int> FixedStackObjectSlots;
- DenseMap<unsigned, int> StackObjectSlots;
- DenseMap<unsigned, unsigned> ConstantPoolSlots;
- DenseMap<unsigned, unsigned> JumpTableSlots;
-
- PerFunctionMIParsingState(MachineFunction &MF, SourceMgr &SM,
- const SlotMapping &IRSlots,
- PerTargetMIParsingState &Target);
-
- VRegInfo &getVRegInfo(unsigned Num);
- VRegInfo &getVRegInfoNamed(StringRef RegName);
-};
-
-/// Parse the machine basic block definitions, and skip the machine
-/// instructions.
-///
-/// This function runs the first parsing pass on the machine function's body.
-/// It parses only the machine basic block definitions and creates the machine
-/// basic blocks in the given machine function.
-///
-/// The machine instructions aren't parsed during the first pass because all
-/// the machine basic blocks aren't defined yet - this makes it impossible to
-/// resolve the machine basic block references.
-///
-/// Return true if an error occurred.
-bool parseMachineBasicBlockDefinitions(PerFunctionMIParsingState &PFS,
- StringRef Src, SMDiagnostic &Error);
-
-/// Parse the machine instructions.
-///
-/// This function runs the second parsing pass on the machine function's body.
-/// It skips the machine basic block definitions and parses only the machine
-/// instructions and basic block attributes like liveins and successors.
-///
-/// The second parsing pass assumes that the first parsing pass already ran
-/// on the given source string.
-///
-/// Return true if an error occurred.
-bool parseMachineInstructions(PerFunctionMIParsingState &PFS, StringRef Src,
- SMDiagnostic &Error);
-
-bool parseMBBReference(PerFunctionMIParsingState &PFS,
- MachineBasicBlock *&MBB, StringRef Src,
- SMDiagnostic &Error);
-
-bool parseRegisterReference(PerFunctionMIParsingState &PFS,
- unsigned &Reg, StringRef Src,
- SMDiagnostic &Error);
-
-bool parseNamedRegisterReference(PerFunctionMIParsingState &PFS, unsigned &Reg,
- StringRef Src, SMDiagnostic &Error);
-
-bool parseVirtualRegisterReference(PerFunctionMIParsingState &PFS,
- VRegInfo *&Info, StringRef Src,
- SMDiagnostic &Error);
-
-bool parseStackObjectReference(PerFunctionMIParsingState &PFS, int &FI,
- StringRef Src, SMDiagnostic &Error);
-
-bool parseMDNode(PerFunctionMIParsingState &PFS, MDNode *&Node, StringRef Src,
- SMDiagnostic &Error);
-
-} // end namespace llvm
-
-#endif // LLVM_LIB_CODEGEN_MIRPARSER_MIPARSER_H
diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
index 7a4eb45f..3598cbe 100644
--- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "llvm/CodeGen/MIRParser/MIRParser.h"
-#include "MIParser.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringMap.h"
@@ -21,6 +20,7 @@
#include "llvm/AsmParser/SlotMapping.h"
#include "llvm/CodeGen/GlobalISel/RegisterBank.h"
#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h"
+#include "llvm/CodeGen/MIRParser/MIParser.h"
#include "llvm/CodeGen/MIRYamlMapping.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
@@ -39,6 +39,7 @@
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Target/TargetMachine.h"
#include <memory>
using namespace llvm;
@@ -266,6 +267,11 @@
// Parse the yaml.
yaml::MachineFunction YamlMF;
yaml::EmptyContext Ctx;
+
+ const LLVMTargetMachine &TM = MMI.getTarget();
+ YamlMF.MachineFuncInfo = std::unique_ptr<yaml::MachineFunctionInfo>(
+ TM.createDefaultFuncInfoYAML());
+
yaml::yamlize(In, YamlMF, false, Ctx);
if (In.error())
return true;
@@ -407,6 +413,19 @@
if (setupRegisterInfo(PFS, YamlMF))
return true;
+ if (YamlMF.MachineFuncInfo) {
+ const LLVMTargetMachine &TM = MF.getTarget();
+ // Note this is called after the initial constructor of the
+ // MachineFunctionInfo based on the MachineFunction, which may depend on the
+ // IR.
+
+ SMRange SrcRange;
+ if (TM.parseMachineFunctionInfo(*YamlMF.MachineFuncInfo, PFS, Error,
+ SrcRange)) {
+ return error(Error, SrcRange);
+ }
+ }
+
computeFunctionProperties(MF);
MF.getSubtarget().mirFileLoaded(MF);
diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index 5977ba4..86e3f53 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -215,6 +215,11 @@
convert(YamlMF, *ConstantPool);
if (const auto *JumpTableInfo = MF.getJumpTableInfo())
convert(MST, YamlMF.JumpTableInfo, *JumpTableInfo);
+
+ const TargetMachine &TM = MF.getTarget();
+ YamlMF.MachineFuncInfo =
+ std::unique_ptr<yaml::MachineFunctionInfo>(TM.convertFuncInfoToYAML(MF));
+
raw_string_ostream StrOS(YamlMF.Body.Value.Value);
bool IsNewlineNeeded = false;
for (const auto &MBB : MF) {