MIR: Allow targets to serialize MachineFunctionInfo
authorMatt Arsenault <Matthew.Arsenault@amd.com>
Thu, 14 Mar 2019 22:54:43 +0000 (22:54 +0000)
committerMatt Arsenault <Matthew.Arsenault@amd.com>
Thu, 14 Mar 2019 22:54:43 +0000 (22:54 +0000)
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

31 files changed:
llvm/include/llvm/CodeGen/MIRParser/MIParser.h [moved from llvm/lib/CodeGen/MIRParser/MIParser.h with 98% similarity]
llvm/include/llvm/CodeGen/MIRYamlMapping.h
llvm/include/llvm/CodeGen/MachineModuleInfo.h
llvm/include/llvm/Target/TargetMachine.h
llvm/lib/CodeGen/MIRParser/MIParser.cpp
llvm/lib/CodeGen/MIRParser/MIRParser.cpp
llvm/lib/CodeGen/MIRPrinter.cpp
llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.cpp
llvm/lib/Target/AMDGPU/AMDGPUTargetMachine.h
llvm/lib/Target/AMDGPU/LLVMBuild.txt
llvm/lib/Target/AMDGPU/SIISelLowering.cpp
llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.cpp
llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h
llvm/test/CodeGen/AMDGPU/scalar-store-cache-flush.mir
llvm/test/CodeGen/AMDGPU/sgpr-spill-wrong-stack-id.mir
llvm/test/CodeGen/AMDGPU/spill-before-exec.mir
llvm/test/CodeGen/AMDGPU/spill-empty-live-interval.mir
llvm/test/CodeGen/AMDGPU/stack-slot-color-sgpr-vgpr-spills.mir
llvm/test/CodeGen/AMDGPU/subreg-split-live-in-error.mir
llvm/test/CodeGen/MIR/AMDGPU/machine-function-info-no-ir.mir [new file with mode: 0644]
llvm/test/CodeGen/MIR/AMDGPU/machine-function-info-register-parse-error1.mir [new file with mode: 0644]
llvm/test/CodeGen/MIR/AMDGPU/machine-function-info-register-parse-error2.mir [new file with mode: 0644]
llvm/test/CodeGen/MIR/AMDGPU/machine-function-info.ll [new file with mode: 0644]
llvm/test/CodeGen/MIR/AMDGPU/mfi-frame-offset-reg-class.mir [new file with mode: 0644]
llvm/test/CodeGen/MIR/AMDGPU/mfi-parse-error-frame-offset-reg.mir [new file with mode: 0644]
llvm/test/CodeGen/MIR/AMDGPU/mfi-parse-error-scratch-rsrc-reg.mir [new file with mode: 0644]
llvm/test/CodeGen/MIR/AMDGPU/mfi-parse-error-scratch-wave-offset-reg.mir [new file with mode: 0644]
llvm/test/CodeGen/MIR/AMDGPU/mfi-parse-error-stack-ptr-offset-reg.mir [new file with mode: 0644]
llvm/test/CodeGen/MIR/AMDGPU/mfi-scratch-rsrc-reg-reg-class.mir [new file with mode: 0644]
llvm/test/CodeGen/MIR/AMDGPU/mfi-scratch-wave-offset-reg-class.mir [new file with mode: 0644]
llvm/test/CodeGen/MIR/AMDGPU/mfi-stack-ptr-offset-reg-class.mir [new file with mode: 0644]

similarity index 98%
rename from llvm/lib/CodeGen/MIRParser/MIParser.h
rename to llvm/include/llvm/CodeGen/MIRParser/MIParser.h
index dc858a9..4e32a04 100644 (file)
@@ -164,8 +164,8 @@ struct PerFunctionMIParsingState {
   PerTargetMIParsingState &Target;
 
   DenseMap<unsigned, MachineBasicBlock *> MBBSlots;
-  DenseMap<unsigned, VRegInfo*> VRegInfos;
-  StringMap<VRegInfo*> VRegInfosNamed;
+  DenseMap<unsigned, VRegInfo *> VRegInfos;
+  StringMap<VRegInfo *> VRegInfosNamed;
   DenseMap<unsigned, int> FixedStackObjectSlots;
   DenseMap<unsigned, int> StackObjectSlots;
   DenseMap<unsigned, unsigned> ConstantPoolSlots;
index a0f2b16..13f572f 100644 (file)
@@ -36,6 +36,7 @@ struct StringValue {
 
   StringValue() = default;
   StringValue(std::string Value) : Value(std::move(Value)) {}
+  StringValue(const char Val[]) : Value(Val) {}
 
   bool operator==(const StringValue &Other) const {
     return Value == Other.Value;
@@ -482,6 +483,20 @@ template <> struct MappingTraits<MachineFrameInfo> {
   }
 };
 
+/// Targets should override this in a way that mirrors the implementation of
+/// llvm::MachineFunctionInfo.
+struct MachineFunctionInfo {
+  virtual ~MachineFunctionInfo() {}
+  virtual void mappingImpl(IO &YamlIO) {}
+};
+
+template <> struct MappingTraits<std::unique_ptr<MachineFunctionInfo>> {
+  static void mapping(IO &YamlIO, std::unique_ptr<MachineFunctionInfo> &MFI) {
+    if (MFI)
+      MFI->mappingImpl(YamlIO);
+  }
+};
+
 struct MachineFunction {
   StringRef Name;
   unsigned Alignment = 0;
@@ -503,6 +518,7 @@ struct MachineFunction {
   std::vector<FixedMachineStackObject> FixedStackObjects;
   std::vector<MachineStackObject> StackObjects;
   std::vector<MachineConstantPoolValue> Constants; /// Constant pool.
+  std::unique_ptr<MachineFunctionInfo> MachineFuncInfo;
   MachineJumpTable JumpTableInfo;
   BlockStringValue Body;
 };
@@ -531,6 +547,7 @@ template <> struct MappingTraits<MachineFunction> {
                        std::vector<MachineStackObject>());
     YamlIO.mapOptional("constants", MF.Constants,
                        std::vector<MachineConstantPoolValue>());
+    YamlIO.mapOptional("machineFunctionInfo", MF.MachineFuncInfo);
     if (!YamlIO.outputting() || !MF.JumpTableInfo.Entries.empty())
       YamlIO.mapOptional("jumpTable", MF.JumpTableInfo, MachineJumpTable());
     YamlIO.mapOptional("body", MF.Body, BlockStringValue());
index 9b81dc6..4ff5c7f 100644 (file)
@@ -150,6 +150,8 @@ public:
   bool doInitialization(Module &) override;
   bool doFinalization(Module &) override;
 
+  const LLVMTargetMachine &getTarget() const { return TM; }
+
   const MCContext &getContext() const { return Context; }
   MCContext &getContext() { return Context; }
 
index 7dd9b99..f289c65 100644 (file)
@@ -35,6 +35,9 @@ class MCSubtargetInfo;
 class MCSymbol;
 class raw_pwrite_stream;
 class PassManagerBuilder;
+struct PerFunctionMIParsingState;
+class SMDiagnostic;
+class SMRange;
 class Target;
 class TargetIntrinsicInfo;
 class TargetIRAnalysis;
@@ -49,6 +52,10 @@ class PassManagerBase;
 }
 using legacy::PassManagerBase;
 
+namespace yaml {
+struct MachineFunctionInfo;
+}
+
 //===----------------------------------------------------------------------===//
 ///
 /// Primary interface to the complete machine description for the target
@@ -114,6 +121,27 @@ public:
     return nullptr;
   }
 
+  /// Allocate and return a default initialized instance of the YAML
+  /// representation for the MachineFunctionInfo.
+  virtual yaml::MachineFunctionInfo *createDefaultFuncInfoYAML() const {
+    return nullptr;
+  }
+
+  /// Allocate and initialize an instance of the YAML representation of the
+  /// MachineFunctionInfo.
+  virtual yaml::MachineFunctionInfo *
+  convertFuncInfoToYAML(const MachineFunction &MF) const {
+    return nullptr;
+  }
+
+  /// Parse out the target's MachineFunctionInfo from the YAML reprsentation.
+  virtual bool parseMachineFunctionInfo(const yaml::MachineFunctionInfo &,
+                                        PerFunctionMIParsingState &PFS,
+                                        SMDiagnostic &Error,
+                                        SMRange &SourceRange) const {
+    return false;
+  }
+
   /// This method returns a pointer to the specified type of
   /// TargetSubtargetInfo.  In debug builds, it verifies that the object being
   /// returned is of the correct type.
index 593ec57..971944b 100644 (file)
@@ -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"
index 7a4eb45..3598cbe 100644 (file)
@@ -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 @@ bool MIRParserImpl::parseMachineFunction(Module &M, MachineModuleInfo &MMI) {
   // 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 @@ MIRParserImpl::initializeMachineFunction(const yaml::MachineFunction &YamlMF,
   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);
index 5977ba4..86e3f53 100644 (file)
@@ -215,6 +215,11 @@ void MIRPrinter::print(const MachineFunction &MF) {
     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) {
index dd76390..23ba6ce 100644 (file)
 #include "GCNIterativeScheduler.h"
 #include "GCNSchedStrategy.h"
 #include "R600MachineScheduler.h"
+#include "SIMachineFunctionInfo.h"
 #include "SIMachineScheduler.h"
 #include "llvm/CodeGen/GlobalISel/IRTranslator.h"
 #include "llvm/CodeGen/GlobalISel/InstructionSelect.h"
 #include "llvm/CodeGen/GlobalISel/Legalizer.h"
 #include "llvm/CodeGen/GlobalISel/RegBankSelect.h"
+#include "llvm/CodeGen/MIRParser/MIParser.h"
 #include "llvm/CodeGen/Passes.h"
 #include "llvm/CodeGen/TargetPassConfig.h"
 #include "llvm/IR/Attributes.h"
@@ -930,3 +932,74 @@ void GCNPassConfig::addPreEmitPass() {
 TargetPassConfig *GCNTargetMachine::createPassConfig(PassManagerBase &PM) {
   return new GCNPassConfig(*this, PM);
 }
+
+yaml::MachineFunctionInfo *GCNTargetMachine::createDefaultFuncInfoYAML() const {
+  return new yaml::SIMachineFunctionInfo();
+}
+
+yaml::MachineFunctionInfo *
+GCNTargetMachine::convertFuncInfoToYAML(const MachineFunction &MF) const {
+  const SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
+  return new yaml::SIMachineFunctionInfo(*MFI,
+                                         *MF.getSubtarget().getRegisterInfo());
+}
+
+bool GCNTargetMachine::parseMachineFunctionInfo(
+    const yaml::MachineFunctionInfo &MFI_, PerFunctionMIParsingState &PFS,
+    SMDiagnostic &Error, SMRange &SourceRange) const {
+  const yaml::SIMachineFunctionInfo &YamlMFI =
+      reinterpret_cast<const yaml::SIMachineFunctionInfo &>(MFI_);
+  MachineFunction &MF = PFS.MF;
+  SIMachineFunctionInfo *MFI = MF.getInfo<SIMachineFunctionInfo>();
+
+  MFI->initializeBaseYamlFields(YamlMFI);
+
+  auto parseRegister = [&](const yaml::StringValue &RegName, unsigned &RegVal) {
+    if (parseNamedRegisterReference(PFS, RegVal, RegName.Value, Error)) {
+      SourceRange = RegName.SourceRange;
+      return true;
+    }
+
+    return false;
+  };
+
+  auto diagnoseRegisterClass = [&](const yaml::StringValue &RegName) {
+    // Create a diagnostic for a the register string literal.
+    const MemoryBuffer &Buffer =
+        *PFS.SM->getMemoryBuffer(PFS.SM->getMainFileID());
+    Error = SMDiagnostic(*PFS.SM, SMLoc(), Buffer.getBufferIdentifier(), 1,
+                         RegName.Value.size(), SourceMgr::DK_Error,
+                         "incorrect register class for field", RegName.Value,
+                         None, None);
+    SourceRange = RegName.SourceRange;
+    return true;
+  };
+
+  if (parseRegister(YamlMFI.ScratchRSrcReg, MFI->ScratchRSrcReg) ||
+      parseRegister(YamlMFI.ScratchWaveOffsetReg, MFI->ScratchWaveOffsetReg) ||
+      parseRegister(YamlMFI.FrameOffsetReg, MFI->FrameOffsetReg) ||
+      parseRegister(YamlMFI.StackPtrOffsetReg, MFI->StackPtrOffsetReg))
+    return true;
+
+  if (MFI->ScratchRSrcReg != AMDGPU::PRIVATE_RSRC_REG &&
+      !AMDGPU::SReg_128RegClass.contains(MFI->ScratchRSrcReg)) {
+    return diagnoseRegisterClass(YamlMFI.ScratchRSrcReg);
+  }
+
+  if (MFI->ScratchWaveOffsetReg != AMDGPU::SCRATCH_WAVE_OFFSET_REG &&
+      !AMDGPU::SGPR_32RegClass.contains(MFI->ScratchWaveOffsetReg)) {
+    return diagnoseRegisterClass(YamlMFI.ScratchWaveOffsetReg);
+  }
+
+  if (MFI->FrameOffsetReg != AMDGPU::FP_REG &&
+      !AMDGPU::SGPR_32RegClass.contains(MFI->FrameOffsetReg)) {
+    return diagnoseRegisterClass(YamlMFI.FrameOffsetReg);
+  }
+
+  if (MFI->StackPtrOffsetReg != AMDGPU::SP_REG &&
+      !AMDGPU::SGPR_32RegClass.contains(MFI->StackPtrOffsetReg)) {
+    return diagnoseRegisterClass(YamlMFI.StackPtrOffsetReg);
+  }
+
+  return false;
+}
index b8805f0..70fa396 100644 (file)
@@ -110,6 +110,14 @@ public:
   bool useIPRA() const override {
     return true;
   }
+
+  yaml::MachineFunctionInfo *createDefaultFuncInfoYAML() const override;
+  yaml::MachineFunctionInfo *
+  convertFuncInfoToYAML(const MachineFunction &MF) const override;
+  bool parseMachineFunctionInfo(const yaml::MachineFunctionInfo &,
+                                PerFunctionMIParsingState &PFS,
+                                SMDiagnostic &Error,
+                                SMRange &SourceRange) const override;
 };
 
 } // end namespace llvm
index 2f661af..e18085d 100644 (file)
@@ -29,5 +29,5 @@ has_disassembler = 1
 type = Library
 name = AMDGPUCodeGen
 parent = AMDGPU
-required_libraries = Analysis AsmPrinter CodeGen Core IPO MC AMDGPUAsmPrinter AMDGPUDesc AMDGPUInfo AMDGPUUtils Scalar SelectionDAG Support Target TransformUtils Vectorize GlobalISel BinaryFormat
+required_libraries = Analysis AsmPrinter CodeGen Core IPO MC AMDGPUAsmPrinter AMDGPUDesc AMDGPUInfo AMDGPUUtils Scalar SelectionDAG Support Target TransformUtils Vectorize GlobalISel BinaryFormat MIRParser
 add_to_library_groups = AMDGPU
index 9205c20..f625331 100644 (file)
@@ -9607,13 +9607,22 @@ void SITargetLowering::finalizeLowering(MachineFunction &MF) const {
     assert(Info->getStackPtrOffsetReg() != Info->getFrameOffsetReg());
     assert(!TRI->isSubRegister(Info->getScratchRSrcReg(),
                                Info->getStackPtrOffsetReg()));
-    MRI.replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
+    if (Info->getStackPtrOffsetReg() != AMDGPU::SP_REG)
+      MRI.replaceRegWith(AMDGPU::SP_REG, Info->getStackPtrOffsetReg());
   }
 
-  MRI.replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
-  MRI.replaceRegWith(AMDGPU::FP_REG, Info->getFrameOffsetReg());
-  MRI.replaceRegWith(AMDGPU::SCRATCH_WAVE_OFFSET_REG,
-                     Info->getScratchWaveOffsetReg());
+  // We need to worry about replacing the default register with itself in case
+  // of MIR testcases missing the MFI.
+  if (Info->getScratchRSrcReg() != AMDGPU::PRIVATE_RSRC_REG)
+    MRI.replaceRegWith(AMDGPU::PRIVATE_RSRC_REG, Info->getScratchRSrcReg());
+
+  if (Info->getFrameOffsetReg() != AMDGPU::FP_REG)
+    MRI.replaceRegWith(AMDGPU::FP_REG, Info->getFrameOffsetReg());
+
+  if (Info->getScratchWaveOffsetReg() != AMDGPU::SCRATCH_WAVE_OFFSET_REG) {
+    MRI.replaceRegWith(AMDGPU::SCRATCH_WAVE_OFFSET_REG,
+                       Info->getScratchWaveOffsetReg());
+  }
 
   Info->limitOccupancy(MF);
 
index 78e88ab..834f651 100644 (file)
@@ -319,3 +319,42 @@ MCPhysReg SIMachineFunctionInfo::getNextUserSGPR() const {
 MCPhysReg SIMachineFunctionInfo::getNextSystemSGPR() const {
   return AMDGPU::SGPR0 + NumUserSGPRs + NumSystemSGPRs;
 }
+
+static yaml::StringValue regToString(unsigned Reg,
+                                     const TargetRegisterInfo &TRI) {
+  yaml::StringValue Dest;
+  raw_string_ostream OS(Dest.Value);
+  OS << printReg(Reg, &TRI);
+  return Dest;
+}
+
+yaml::SIMachineFunctionInfo::SIMachineFunctionInfo(
+  const llvm::SIMachineFunctionInfo& MFI,
+  const TargetRegisterInfo &TRI)
+  : ExplicitKernArgSize(MFI.getExplicitKernArgSize()),
+    MaxKernArgAlign(MFI.getMaxKernArgAlign()),
+    LDSSize(MFI.getLDSSize()),
+    IsEntryFunction(MFI.isEntryFunction()),
+    NoSignedZerosFPMath(MFI.hasNoSignedZerosFPMath()),
+    MemoryBound(MFI.isMemoryBound()),
+    WaveLimiter(MFI.needsWaveLimiter()),
+    ScratchRSrcReg(regToString(MFI.getScratchRSrcReg(), TRI)),
+    ScratchWaveOffsetReg(regToString(MFI.getScratchWaveOffsetReg(), TRI)),
+    FrameOffsetReg(regToString(MFI.getFrameOffsetReg(), TRI)),
+    StackPtrOffsetReg(regToString(MFI.getStackPtrOffsetReg(), TRI)) {}
+
+void yaml::SIMachineFunctionInfo::mappingImpl(yaml::IO &YamlIO) {
+  MappingTraits<SIMachineFunctionInfo>::mapping(YamlIO, *this);
+}
+
+bool SIMachineFunctionInfo::initializeBaseYamlFields(
+  const yaml::SIMachineFunctionInfo &YamlMFI) {
+  ExplicitKernArgSize = YamlMFI.ExplicitKernArgSize;
+  MaxKernArgAlign = YamlMFI.MaxKernArgAlign;
+  LDSSize = YamlMFI.LDSSize;
+  IsEntryFunction = YamlMFI.IsEntryFunction;
+  NoSignedZerosFPMath = YamlMFI.NoSignedZerosFPMath;
+  MemoryBound = YamlMFI.MemoryBound;
+  WaveLimiter = YamlMFI.WaveLimiter;
+  return false;
+}
index de84fbb..ce103dc 100644 (file)
 
 #include "AMDGPUArgumentUsageInfo.h"
 #include "AMDGPUMachineFunction.h"
+#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
 #include "SIInstrInfo.h"
 #include "SIRegisterInfo.h"
-#include "MCTargetDesc/AMDGPUMCTargetDesc.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/CodeGen/MIRYamlMapping.h"
 #include "llvm/CodeGen/PseudoSourceValue.h"
 #include "llvm/CodeGen/TargetInstrInfo.h"
 #include "llvm/MC/MCRegisterInfo.h"
@@ -78,9 +79,58 @@ public:
   }
 };
 
+namespace yaml {
+
+struct SIMachineFunctionInfo final : public yaml::MachineFunctionInfo {
+  uint64_t ExplicitKernArgSize = 0;
+  unsigned MaxKernArgAlign = 0;
+  unsigned LDSSize = 0;
+  bool IsEntryFunction = false;
+  bool NoSignedZerosFPMath = false;
+  bool MemoryBound = false;
+  bool WaveLimiter = false;
+
+  StringValue ScratchRSrcReg = "$private_rsrc_reg";
+  StringValue ScratchWaveOffsetReg = "$scratch_wave_offset_reg";
+  StringValue FrameOffsetReg = "$fp_reg";
+  StringValue StackPtrOffsetReg = "$sp_reg";
+
+  SIMachineFunctionInfo() = default;
+  SIMachineFunctionInfo(const llvm::SIMachineFunctionInfo &,
+                        const TargetRegisterInfo &TRI);
+
+  void mappingImpl(yaml::IO &YamlIO) override;
+  ~SIMachineFunctionInfo() = default;
+};
+
+template <> struct MappingTraits<SIMachineFunctionInfo> {
+  static void mapping(IO &YamlIO, SIMachineFunctionInfo &MFI) {
+    YamlIO.mapOptional("explicitKernArgSize", MFI.ExplicitKernArgSize,
+                       UINT64_C(0));
+    YamlIO.mapOptional("maxKernArgAlign", MFI.MaxKernArgAlign, 0u);
+    YamlIO.mapOptional("ldsSize", MFI.LDSSize, 0u);
+    YamlIO.mapOptional("isEntryFunction", MFI.IsEntryFunction, false);
+    YamlIO.mapOptional("noSignedZerosFPMath", MFI.NoSignedZerosFPMath, false);
+    YamlIO.mapOptional("memoryBound", MFI.MemoryBound, false);
+    YamlIO.mapOptional("waveLimiter", MFI.WaveLimiter, false);
+    YamlIO.mapOptional("scratchRSrcReg", MFI.ScratchRSrcReg,
+                       StringValue("$private_rsrc_reg"));
+    YamlIO.mapOptional("scratchWaveOffsetReg", MFI.ScratchWaveOffsetReg,
+                       StringValue("$scratch_wave_offset_reg"));
+    YamlIO.mapOptional("frameOffsetReg", MFI.FrameOffsetReg,
+                       StringValue("$fp_reg"));
+    YamlIO.mapOptional("stackPtrOffsetReg", MFI.StackPtrOffsetReg,
+                       StringValue("$sp_reg"));
+  }
+};
+
+} // end namespace yaml
+
 /// This class keeps track of the SPI_SP_INPUT_ADDR config register, which
 /// tells the hardware which interpolation parameters to load.
 class SIMachineFunctionInfo final : public AMDGPUMachineFunction {
+  friend class GCNTargetMachine;
+
   unsigned TIDReg = AMDGPU::NoRegister;
 
   // Registers that may be reserved for spilling purposes. These may be the same
@@ -219,6 +269,8 @@ private:
 public:
   SIMachineFunctionInfo(const MachineFunction &MF);
 
+  bool initializeBaseYamlFields(const yaml::SIMachineFunctionInfo &YamlMFI);
+
   ArrayRef<SpilledReg> getSGPRToVGPRSpills(int FrameIndex) const {
     auto I = SGPRToVGPRSpills.find(FrameIndex);
     return (I == SGPRToVGPRSpills.end()) ?
index 23974fe..1fea21d 100644 (file)
@@ -53,6 +53,8 @@
 
 name: basic_insert_dcache_wb
 tracksRegLiveness: false
+machineFunctionInfo:
+  isEntryFunction: true
 
 body: |
   bb.0:
@@ -69,6 +71,8 @@ body: |
 
 name: explicit_flush_after
 tracksRegLiveness: false
+machineFunctionInfo:
+  isEntryFunction: true
 
 body: |
   bb.0:
@@ -87,6 +91,8 @@ body: |
 
 name: explicit_flush_before
 tracksRegLiveness: false
+machineFunctionInfo:
+  isEntryFunction: true
 
 body: |
   bb.0:
@@ -100,6 +106,8 @@ body: |
 # CHECK-NEXT: S_ENDPGM 0
 name: no_scalar_store
 tracksRegLiveness: false
+machineFunctionInfo:
+  isEntryFunction: true
 
 body: |
   bb.0:
@@ -119,6 +127,8 @@ body: |
 
 name: multi_block_store
 tracksRegLiveness: false
+machineFunctionInfo:
+  isEntryFunction: true
 
 body: |
   bb.0:
@@ -146,6 +156,8 @@ body: |
 
 name: one_block_store
 tracksRegLiveness: false
+machineFunctionInfo:
+  isEntryFunction: true
 
 body: |
   bb.0:
@@ -165,6 +177,8 @@ body: |
 
 name: si_return
 tracksRegLiveness: false
+machineFunctionInfo:
+  isEntryFunction: true
 
 body: |
   bb.0:
index 9481e98..5943279 100644 (file)
@@ -76,6 +76,11 @@ name:            sgpr_spill_wrong_stack_id
 tracksRegLiveness: true
 frameInfo:
   hasCalls:        true
+machineFunctionInfo:
+  scratchRSrcReg: $sgpr0_sgpr1_sgpr2_sgpr3
+  scratchWaveOffsetReg: $sgpr4
+  frameOffsetReg: $sgpr5
+  stackPtrOffsetReg: $sgpr32
 body:             |
   bb.0:
     %0:sreg_32_xm0 = COPY $sgpr5
index 0726a25..7f0576b 100644 (file)
@@ -8,6 +8,10 @@
 
 name:            foo
 tracksRegLiveness: true
+machineFunctionInfo:
+  scratchRSrcReg: $sgpr0_sgpr1_sgpr2_sgpr3
+  scratchWaveOffsetReg: $sgpr4
+  stackPtrOffsetReg: $sgpr32
 registers:
   - { id: 0, class: sreg_64 }
   - { id: 1100, class: sreg_128 }
index 384042f..c0e63ef 100644 (file)
 
 name: expecting_non_empty_interval
 tracksRegLiveness: true
+machineFunctionInfo:
+  scratchRSrcReg: $sgpr0_sgpr1_sgpr2_sgpr3
+  scratchWaveOffsetReg: $sgpr4
+  frameOffsetReg: $sgpr5
+  stackPtrOffsetReg: $sgpr32
 body:             |
   bb.0:
     successors: %bb.1
@@ -49,6 +54,11 @@ body:             |
 # CHECK-NEXT: S_NOP 0, implicit %2.sub2
 name: rematerialize_empty_interval_has_reference
 tracksRegLiveness: true
+machineFunctionInfo:
+  scratchRSrcReg: $sgpr0_sgpr1_sgpr2_sgpr3
+  scratchWaveOffsetReg: $sgpr4
+  frameOffsetReg: $sgpr5
+  stackPtrOffsetReg: $sgpr32
 body:             |
   bb.0:
     successors: %bb.1
index 559c0d4..9d21d70 100644 (file)
 
 name: no_merge_sgpr_vgpr_spill_slot
 tracksRegLiveness: true
+machineFunctionInfo:
+  scratchRSrcReg: $sgpr0_sgpr1_sgpr2_sgpr3
+  scratchWaveOffsetReg: $sgpr4
+  frameOffsetReg: $sgpr5
+  stackPtrOffsetReg: $sgpr32
 body: |
   bb.0:
-      %0:vgpr_32 = FLAT_LOAD_DWORD undef $vgpr0_vgpr1, 0, 0, 0, implicit $flat_scr, implicit $exec
+    %0:vgpr_32 = FLAT_LOAD_DWORD undef $vgpr0_vgpr1, 0, 0, 0, implicit $flat_scr, implicit $exec
     %2:vgpr_32 = FLAT_LOAD_DWORD undef $vgpr0_vgpr1, 0, 0, 0, implicit $flat_scr, implicit $exec
     S_NOP 0, implicit %0
     %1:sreg_32_xm0_xexec = S_LOAD_DWORD_IMM undef $sgpr0_sgpr1, 0, 0
index 68f6ec7..3bb2737 100644 (file)
 ---
 name:            _amdgpu_ps_main
 tracksRegLiveness: true
+machineFunctionInfo:
+  scratchRSrcReg: $sgpr0_sgpr1_sgpr2_sgpr3
+  scratchWaveOffsetReg: $sgpr4
+  frameOffsetReg: $sgpr5
+  stackPtrOffsetReg: $sgpr32
 liveins:
   - { reg: '$vgpr2', virtual-reg: '%0' }
   - { reg: '$vgpr3', virtual-reg: '%1' }
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/machine-function-info-no-ir.mir b/llvm/test/CodeGen/MIR/AMDGPU/machine-function-info-no-ir.mir
new file mode 100644 (file)
index 0000000..81c4f8f
--- /dev/null
@@ -0,0 +1,151 @@
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -run-pass=none -verify-machineinstrs %s -o - | FileCheck -check-prefixes=FULL,ALL %s
+# RUN: llc -mtriple=amdgcn-amd-amdhsa -run-pass=none -simplify-mir -verify-machineinstrs %s -o - | FileCheck -check-prefixes=SIMPLE,ALL %s
+
+
+---
+# ALL-LABEL: name: kernel0
+# FULL: machineFunctionInfo:
+# FULL-NEXT: explicitKernArgSize: 128
+# FULL-NEXT: maxKernArgAlign: 64
+# FULL-NEXT: ldsSize: 2048
+# FULL-NEXT: isEntryFunction: true
+# FULL-NEXT: noSignedZerosFPMath: false
+# FULL-NEXT: memoryBound:     true
+# FULL-NEXT: waveLimiter:     true
+# FULL-NEXT: scratchRSrcReg:  '$sgpr8_sgpr9_sgpr10_sgpr11'
+# FULL-NEXT: scratchWaveOffsetReg:  '$sgpr12'
+# FULL-NEXT: frameOffsetReg:  '$sgpr12'
+# FULL-NEXT: stackPtrOffsetReg:  '$sgpr13'
+# FULL-NEXT: body:
+
+# SIMPLE: machineFunctionInfo:
+# SIMPLE-NEXT: explicitKernArgSize: 128
+# SIMPLE-NEXT: maxKernArgAlign: 64
+# SIMPLE-NEXT: ldsSize: 2048
+# SIMPLE-NEXT: isEntryFunction: true
+# SIMPLE-NEXT: memoryBound: true
+# SIMPLE-NEXT: waveLimiter: true
+# SIMPLE-NEXT: scratchRSrcReg: '$sgpr8_sgpr9_sgpr10_sgpr11'
+# SIMPLE-NEXT: scratchWaveOffsetReg:  '$sgpr12'
+# SIMPLE-NEXT: frameOffsetReg:  '$sgpr12'
+# SIMPLE-NEXT: stackPtrOffsetReg:  '$sgpr13'
+# SIMPLE-NEXT: body:
+name: kernel0
+machineFunctionInfo:
+  explicitKernArgSize: 128
+  maxKernArgAlign: 64
+  ldsSize: 2048
+  isEntryFunction: true
+  noSignedZerosFPMath: false
+  memoryBound:     true
+  waveLimiter:     true
+  scratchRSrcReg:  '$sgpr8_sgpr9_sgpr10_sgpr11'
+  scratchWaveOffsetReg:  '$sgpr12'
+  frameOffsetReg: '$sgpr12'
+  stackPtrOffsetReg:  '$sgpr13'
+body:             |
+  bb.0:
+    S_ENDPGM 0
+
+...
+
+# FIXME: Should be able to not print section for simple
+---
+# ALL-LABEL: name: no_mfi
+# FULL: machineFunctionInfo:
+# FULL-NEXT: explicitKernArgSize: 0
+# FULL-NEXT: maxKernArgAlign: 0
+# FULL-NEXT: ldsSize: 0
+# FULL-NEXT: isEntryFunction: false
+# FULL-NEXT: noSignedZerosFPMath: false
+# FULL-NEXT: memoryBound:     false
+# FULL-NEXT: waveLimiter:     false
+# FULL-NEXT: scratchRSrcReg:  '$private_rsrc_reg'
+# FULL-NEXT: scratchWaveOffsetReg:  '$scratch_wave_offset_reg'
+# FULL-NEXT: frameOffsetReg:  '$fp_reg'
+# FULL-NEXT: stackPtrOffsetReg:  '$sp_reg'
+
+# SIMPLE: machineFunctionInfo:
+# SIMPLE-NEXT: body:
+
+name: no_mfi
+body:             |
+  bb.0:
+    S_ENDPGM 0
+
+...
+
+---
+# ALL-LABEL: name: empty_mfi
+# FULL: machineFunctionInfo:
+# FULL-NEXT: explicitKernArgSize: 0
+# FULL-NEXT: maxKernArgAlign: 0
+# FULL-NEXT: ldsSize: 0
+# FULL-NEXT: isEntryFunction: false
+# FULL-NEXT: noSignedZerosFPMath: false
+# FULL-NEXT: memoryBound:     false
+# FULL-NEXT: waveLimiter:     false
+# FULL-NEXT: scratchRSrcReg:  '$private_rsrc_reg'
+# FULL-NEXT: scratchWaveOffsetReg:  '$scratch_wave_offset_reg'
+# FULL-NEXT: frameOffsetReg:  '$fp_reg'
+# FULL-NEXT: stackPtrOffsetReg:  '$sp_reg'
+
+# SIMPLE: machineFunctionInfo:
+# SIMPLE-NEXT: body:
+
+name: empty_mfi
+machineFunctionInfo:
+body:             |
+  bb.0:
+    S_ENDPGM 0
+
+...
+
+---
+# ALL-LABEL: name: empty_mfi_entry_func
+# FULL: machineFunctionInfo:
+# FULL-NEXT: explicitKernArgSize: 0
+# FULL-NEXT: maxKernArgAlign: 0
+# FULL-NEXT: ldsSize: 0
+# FULL-NEXT: isEntryFunction: true
+# FULL-NEXT: noSignedZerosFPMath: false
+# FULL-NEXT: memoryBound:     false
+# FULL-NEXT: waveLimiter:     false
+# FULL-NEXT: scratchRSrcReg:  '$private_rsrc_reg'
+# FULL-NEXT: scratchWaveOffsetReg:  '$scratch_wave_offset_reg'
+# FULL-NEXT: frameOffsetReg:  '$fp_reg'
+# FULL-NEXT: stackPtrOffsetReg:  '$sp_reg'
+
+# SIMPLE: machineFunctionInfo:
+# SIMPLE-NEXT: isEntryFunction: true
+# SIMPLE-NEXT: body:
+
+name: empty_mfi_entry_func
+machineFunctionInfo:
+  isEntryFunction: true
+body:             |
+  bb.0:
+    S_ENDPGM 0
+
+...
+
+---
+# ALL-LABEL: name: default_regs_mfi
+
+# FULL: scratchRSrcReg:  '$private_rsrc_reg'
+# FULL-NEXT: scratchWaveOffsetReg:  '$scratch_wave_offset_reg'
+# FULL-NEXT: frameOffsetReg:  '$fp_reg'
+# FULL-NEXT: stackPtrOffsetReg:  '$sp_reg'
+
+# SIMPLE-NOT: scratchRSrcReg
+# SIMPLE-NOT: scratchWaveOffsetReg
+# SIMPLE-NOT:: stackPtrOffsetReg
+name: default_regs_mfi
+machineFunctionInfo:
+  scratchRSrcReg:  '$private_rsrc_reg'
+
+body:             |
+  bb.0:
+    S_ENDPGM 0
+
+...
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/machine-function-info-register-parse-error1.mir b/llvm/test/CodeGen/MIR/AMDGPU/machine-function-info-register-parse-error1.mir
new file mode 100644 (file)
index 0000000..cfa5323
--- /dev/null
@@ -0,0 +1,12 @@
+# RUN: not llc -march=amdgcn -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
+# CHECK: :7:27: incorrect register class for field
+# CHECK: scratchRSrcReg:  '$noreg'
+---
+name: noreg_rsrc_reg
+machineFunctionInfo:
+  scratchRSrcReg:  '$noreg'
+body:             |
+  bb.0:
+
+    S_ENDPGM
+...
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/machine-function-info-register-parse-error2.mir b/llvm/test/CodeGen/MIR/AMDGPU/machine-function-info-register-parse-error2.mir
new file mode 100644 (file)
index 0000000..f3da77e
--- /dev/null
@@ -0,0 +1,12 @@
+# RUN: not llc -march=amdgcn -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
+# CHECK: :7:21: unknown register name 'not_a_register_name'
+# CHECK: scratchRSrcReg:  '$not_a_register_name'
+---
+name: invalid_rsrc_reg
+machineFunctionInfo:
+  scratchRSrcReg:  '$not_a_register_name'
+body:             |
+  bb.0:
+
+    S_ENDPGM
+...
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/machine-function-info.ll b/llvm/test/CodeGen/MIR/AMDGPU/machine-function-info.ll
new file mode 100644 (file)
index 0000000..d04df7d
--- /dev/null
@@ -0,0 +1,83 @@
+; RUN: llc -mtriple=amdgcn-mesa-mesa3d -stop-after expand-isel-pseudos -o %t.mir %s
+; RUN: llc -run-pass=none -verify-machineinstrs %t.mir -o - | FileCheck %s
+
+; Test that SIMachineFunctionInfo can be round trip serialized through
+; MIR.
+
+@lds = addrspace(3) global [512 x float] undef, align 4
+
+; CHECK-LABEL: {{^}}name: kernel
+; CHECK: machineFunctionInfo:
+; CHECK-NEXT: explicitKernArgSize: 128
+; CHECK-NEXT: maxKernArgAlign: 64
+; CHECK-NEXT: ldsSize: 2048
+; CHECK-NEXT: isEntryFunction: true
+; CHECK-NEXT: noSignedZerosFPMath: false
+; CHECK-NEXT: memoryBound: false
+; CHECK-NEXT: waveLimiter: false
+; CHECK-NEXT: scratchRSrcReg:  '$sgpr96_sgpr97_sgpr98_sgpr99'
+; CHECK-NEXT: scratchWaveOffsetReg: '$sgpr101'
+; CHECK-NEXT: frameOffsetReg:  '$sgpr101'
+; CHECK-NEXT: stackPtrOffsetReg: '$sp_reg'
+; CHECK-NEXT: body:
+define amdgpu_kernel void @kernel(i32 %arg0, i64 %arg1, <16 x i32> %arg2) {
+  %gep = getelementptr inbounds [512 x float], [512 x float] addrspace(3)* @lds, i32 0, i32 %arg0
+  store float 0.0, float addrspace(3)* %gep, align 4
+  ret void
+}
+
+; CHECK-LABEL: {{^}}name: ps_shader
+; CHECK: machineFunctionInfo:
+; CHECK-NEXT: explicitKernArgSize: 0
+; CHECK-NEXT: maxKernArgAlign: 0
+; CHECK-NEXT: ldsSize: 0
+; CHECK-NEXT: isEntryFunction: true
+; CHECK-NEXT: noSignedZerosFPMath: false
+; CHECK-NEXT: memoryBound: false
+; CHECK-NEXT: waveLimiter: false
+; CHECK-NEXT: scratchRSrcReg:  '$sgpr96_sgpr97_sgpr98_sgpr99'
+; CHECK-NEXT: scratchWaveOffsetReg: '$sgpr101'
+; CHECK-NEXT: frameOffsetReg:  '$sgpr101'
+; CHECK-NEXT: stackPtrOffsetReg: '$sp_reg'
+; CHECK-NEXT: body:
+define amdgpu_ps void @ps_shader(i32 %arg0, i32 inreg %arg1) {
+  ret void
+}
+
+; CHECK-LABEL: {{^}}name: function
+; CHECK: machineFunctionInfo:
+; CHECK-NEXT: explicitKernArgSize: 0
+; CHECK-NEXT: maxKernArgAlign: 0
+; CHECK-NEXT: ldsSize: 0
+; CHECK-NEXT: isEntryFunction: false
+; CHECK-NEXT: noSignedZerosFPMath: false
+; CHECK-NEXT: memoryBound: false
+; CHECK-NEXT: waveLimiter: false
+; CHECK-NEXT: scratchRSrcReg: '$sgpr0_sgpr1_sgpr2_sgpr3'
+; CHECK-NEXT: scratchWaveOffsetReg: '$sgpr4'
+; CHECK-NEXT: frameOffsetReg: '$sgpr5'
+; CHECK-NEXT: stackPtrOffsetReg: '$sgpr32'
+; CHECK-NEXT: body:
+define void @function() {
+  ret void
+}
+
+; CHECK-LABEL: {{^}}name: function_nsz
+; CHECK: machineFunctionInfo:
+; CHECK-NEXT: explicitKernArgSize: 0
+; CHECK-NEXT: maxKernArgAlign: 0
+; CHECK-NEXT: ldsSize: 0
+; CHECK-NEXT: isEntryFunction: false
+; CHECK-NEXT: noSignedZerosFPMath: true
+; CHECK-NEXT: memoryBound: false
+; CHECK-NEXT: waveLimiter: false
+; CHECK-NEXT: scratchRSrcReg: '$sgpr0_sgpr1_sgpr2_sgpr3'
+; CHECK-NEXT: scratchWaveOffsetReg: '$sgpr4'
+; CHECK-NEXT: frameOffsetReg: '$sgpr5'
+; CHECK-NEXT: stackPtrOffsetReg: '$sgpr32'
+; CHECK-NEXT: body:
+define void @function_nsz() #0 {
+  ret void
+}
+
+attributes #0 = { "no-signed-zeros-fp-math" = "true" }
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/mfi-frame-offset-reg-class.mir b/llvm/test/CodeGen/MIR/AMDGPU/mfi-frame-offset-reg-class.mir
new file mode 100644 (file)
index 0000000..c66f6b6
--- /dev/null
@@ -0,0 +1,13 @@
+# RUN: not llc -march=amdgcn -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
+# CHECK: :8:27: incorrect register class for field
+# CHECK: frameOffsetReg:  '$vgpr0'
+
+---
+name: wrong_reg_class_frame_offset_reg
+machineFunctionInfo:
+  frameOffsetReg:  '$vgpr0'
+body:             |
+  bb.0:
+
+    S_ENDPGM
+...
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/mfi-parse-error-frame-offset-reg.mir b/llvm/test/CodeGen/MIR/AMDGPU/mfi-parse-error-frame-offset-reg.mir
new file mode 100644 (file)
index 0000000..723f542
--- /dev/null
@@ -0,0 +1,12 @@
+# RUN: not llc -march=amdgcn -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
+# CHECK: :7:21: expected a named register
+# CHECK: frameOffsetReg:  ''
+---
+name: empty_frame_offset_reg
+machineFunctionInfo:
+  frameOffsetReg:  ''
+body:             |
+  bb.0:
+
+    S_ENDPGM
+...
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/mfi-parse-error-scratch-rsrc-reg.mir b/llvm/test/CodeGen/MIR/AMDGPU/mfi-parse-error-scratch-rsrc-reg.mir
new file mode 100644 (file)
index 0000000..ee047b9
--- /dev/null
@@ -0,0 +1,12 @@
+# RUN: not llc -march=amdgcn -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
+# CHECK: :7:21: expected a named register
+# CHECK: scratchRSrcReg:  ''
+---
+name: empty_scratch_rsrc_reg
+machineFunctionInfo:
+  scratchRSrcReg:  ''
+body:             |
+  bb.0:
+
+    S_ENDPGM
+...
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/mfi-parse-error-scratch-wave-offset-reg.mir b/llvm/test/CodeGen/MIR/AMDGPU/mfi-parse-error-scratch-wave-offset-reg.mir
new file mode 100644 (file)
index 0000000..bbf5808
--- /dev/null
@@ -0,0 +1,12 @@
+# RUN: not llc -march=amdgcn -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
+# CHECK: :7:27: expected a named register
+# CHECK: scratchWaveOffsetReg:  ''
+---
+name: empty_scratch_wave_offset_reg
+machineFunctionInfo:
+  scratchWaveOffsetReg:  ''
+body:             |
+  bb.0:
+
+    S_ENDPGM
+...
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/mfi-parse-error-stack-ptr-offset-reg.mir b/llvm/test/CodeGen/MIR/AMDGPU/mfi-parse-error-stack-ptr-offset-reg.mir
new file mode 100644 (file)
index 0000000..e8164da
--- /dev/null
@@ -0,0 +1,12 @@
+# RUN: not llc -march=amdgcn -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
+# CHECK: :7:24: expected a named register
+# CHECK: stackPtrOffsetReg:  ''
+---
+name: empty_stack_ptr_offset_reg
+machineFunctionInfo:
+  stackPtrOffsetReg:  ''
+body:             |
+  bb.0:
+
+    S_ENDPGM
+...
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/mfi-scratch-rsrc-reg-reg-class.mir b/llvm/test/CodeGen/MIR/AMDGPU/mfi-scratch-rsrc-reg-reg-class.mir
new file mode 100644 (file)
index 0000000..ac02af9
--- /dev/null
@@ -0,0 +1,13 @@
+# RUN: not llc -march=amdgcn -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
+# CHECK: :8:45: incorrect register class for field
+# CHECK: scratchRSrcReg:  '$vgpr0_vgpr1_vgpr2_vgpr3'
+
+---
+name: wrong_reg_class_scratch_rsrc_reg
+machineFunctionInfo:
+  scratchRSrcReg:  '$vgpr0_vgpr1_vgpr2_vgpr3'
+body:             |
+  bb.0:
+
+    S_ENDPGM
+...
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/mfi-scratch-wave-offset-reg-class.mir b/llvm/test/CodeGen/MIR/AMDGPU/mfi-scratch-wave-offset-reg-class.mir
new file mode 100644 (file)
index 0000000..8e765ba
--- /dev/null
@@ -0,0 +1,13 @@
+# RUN: not llc -march=amdgcn -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
+# CHECK: :8:33: incorrect register class for field
+# CHECK: scratchWaveOffsetReg:  '$vgpr0'
+
+---
+name: wrong_reg_class_scratch_wave_offset_reg
+machineFunctionInfo:
+  scratchWaveOffsetReg:  '$vgpr0'
+body:             |
+  bb.0:
+
+    S_ENDPGM
+...
diff --git a/llvm/test/CodeGen/MIR/AMDGPU/mfi-stack-ptr-offset-reg-class.mir b/llvm/test/CodeGen/MIR/AMDGPU/mfi-stack-ptr-offset-reg-class.mir
new file mode 100644 (file)
index 0000000..c15b0c6
--- /dev/null
@@ -0,0 +1,13 @@
+# RUN: not llc -march=amdgcn -run-pass none -o /dev/null %s 2>&1 | FileCheck %s
+# CHECK: :8:30: incorrect register class for field
+# CHECK: stackPtrOffsetReg:  '$vgpr0'
+
+---
+name: wrong_reg_class_stack_ptr_offset_reg
+machineFunctionInfo:
+  stackPtrOffsetReg:  '$vgpr0'
+body:             |
+  bb.0:
+
+    S_ENDPGM
+...