MIR Serialization: Serialize the simple virtual register allocation hints.
authorAlex Lorenz <arphaman@gmail.com>
Fri, 24 Jul 2015 20:35:40 +0000 (20:35 +0000)
committerAlex Lorenz <arphaman@gmail.com>
Fri, 24 Jul 2015 20:35:40 +0000 (20:35 +0000)
This commit serializes the virtual register allocations hints of type 0.
These hints specify the preferred physical registers for allocations.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@243156 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/CodeGen/MIRYamlMapping.h
include/llvm/CodeGen/MachineRegisterInfo.h
lib/CodeGen/MIRParser/MIRParser.cpp
lib/CodeGen/MIRPrinter.cpp
test/CodeGen/MIR/X86/expected-named-register-in-allocation-hint.mir [new file with mode: 0644]
test/CodeGen/MIR/X86/simple-register-allocation-hints.mir [new file with mode: 0644]

index 678cec9838accb4bde596a321f06ddabefb06b5b..c99dc40458d1359ba5d0a8d0ebebdcfdadd00995 100644 (file)
@@ -101,13 +101,16 @@ namespace yaml {
 struct VirtualRegisterDefinition {
   unsigned ID;
   StringValue Class;
-  // TODO: Serialize the virtual register hints.
+  StringValue PreferredRegister;
+  // TODO: Serialize the target specific register hints.
 };
 
 template <> struct MappingTraits<VirtualRegisterDefinition> {
   static void mapping(IO &YamlIO, VirtualRegisterDefinition &Reg) {
     YamlIO.mapRequired("id", Reg.ID);
     YamlIO.mapRequired("class", Reg.Class);
+    YamlIO.mapOptional("preferred-register", Reg.PreferredRegister,
+                       StringValue()); // Don't print out when it's empty.
   }
 
   static const bool flow = true;
index 67583be616c38da175de144888f459a6c8881b77..2f823b44801de1eba51ef3525e8374b0b06f3b66 100644 (file)
@@ -614,6 +614,12 @@ public:
     RegAllocHints[VReg].second = PrefReg;
   }
 
+  /// Specify the preferred register allocation hint for the specified virtual
+  /// register.
+  void setSimpleHint(unsigned VReg, unsigned PrefReg) {
+    setRegAllocationHint(VReg, /*Type=*/0, PrefReg);
+  }
+
   /// getRegAllocationHint - Return the register allocation hint for the
   /// specified virtual register.
   std::pair<unsigned, unsigned>
index 383fde1101a9724e6d7e55353122d1660df57046..67c939cc562a025ee48c7aa3193f6d0c24d2c40f 100644 (file)
@@ -103,11 +103,9 @@ public:
                                    const yaml::MachineBasicBlock &YamlMBB,
                                    const PerFunctionMIParsingState &PFS);
 
-  bool
-  initializeRegisterInfo(const MachineFunction &MF,
-                         MachineRegisterInfo &RegInfo,
-                         const yaml::MachineFunction &YamlMF,
-                         DenseMap<unsigned, unsigned> &VirtualRegisterSlots);
+  bool initializeRegisterInfo(MachineFunction &MF, MachineRegisterInfo &RegInfo,
+                              const yaml::MachineFunction &YamlMF,
+                              PerFunctionMIParsingState &PFS);
 
   bool initializeFrameInfo(const Function &F, MachineFrameInfo &MFI,
                            const yaml::MachineFunction &YamlMF,
@@ -273,8 +271,7 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) {
   MF.setExposesReturnsTwice(YamlMF.ExposesReturnsTwice);
   MF.setHasInlineAsm(YamlMF.HasInlineAsm);
   PerFunctionMIParsingState PFS;
-  if (initializeRegisterInfo(MF, MF.getRegInfo(), YamlMF,
-                             PFS.VirtualRegisterSlots))
+  if (initializeRegisterInfo(MF, MF.getRegInfo(), YamlMF, PFS))
     return true;
   if (initializeFrameInfo(*MF.getFunction(), *MF.getFrameInfo(), YamlMF,
                           PFS.StackObjectSlots, PFS.FixedStackObjectSlots))
@@ -368,10 +365,10 @@ bool MIRParserImpl::initializeMachineBasicBlock(
   return false;
 }
 
-bool MIRParserImpl::initializeRegisterInfo(
-    const MachineFunction &MF, MachineRegisterInfo &RegInfo,
-    const yaml::MachineFunction &YamlMF,
-    DenseMap<unsigned, unsigned> &VirtualRegisterSlots) {
+bool MIRParserImpl::initializeRegisterInfo(MachineFunction &MF,
+                                           MachineRegisterInfo &RegInfo,
+                                           const yaml::MachineFunction &YamlMF,
+                                           PerFunctionMIParsingState &PFS) {
   assert(RegInfo.isSSA());
   if (!YamlMF.IsSSA)
     RegInfo.leaveSSA();
@@ -380,6 +377,7 @@ bool MIRParserImpl::initializeRegisterInfo(
     RegInfo.invalidateLiveness();
   RegInfo.enableSubRegLiveness(YamlMF.TracksSubRegLiveness);
 
+  SMDiagnostic Error;
   // Parse the virtual register information.
   for (const auto &VReg : YamlMF.VirtualRegisters) {
     const auto *RC = getRegClass(MF, VReg.Class.Value);
@@ -390,7 +388,15 @@ bool MIRParserImpl::initializeRegisterInfo(
     unsigned Reg = RegInfo.createVirtualRegister(RC);
     // TODO: Report an error when the same virtual register with the same ID is
     // redefined.
-    VirtualRegisterSlots.insert(std::make_pair(VReg.ID, Reg));
+    PFS.VirtualRegisterSlots.insert(std::make_pair(VReg.ID, Reg));
+    if (!VReg.PreferredRegister.Value.empty()) {
+      unsigned PreferredReg = 0;
+      if (parseNamedRegisterReference(PreferredReg, SM, MF,
+                                      VReg.PreferredRegister.Value, PFS,
+                                      IRSlots, Error))
+        return error(Error, VReg.PreferredRegister.SourceRange);
+      RegInfo.setSimpleHint(Reg, PreferredReg);
+    }
   }
   return false;
 }
index 2ae5466392fd39d8c28af944958b96af2867fb14..574a0ddee1bb86f6ac750734d0231024878625b0 100644 (file)
@@ -140,6 +140,12 @@ static void printReg(unsigned Reg, raw_ostream &OS,
     llvm_unreachable("Can't print this kind of register yet");
 }
 
+static void printReg(unsigned Reg, yaml::StringValue &Dest,
+                     const TargetRegisterInfo *TRI) {
+  raw_string_ostream OS(Dest.Value);
+  printReg(Reg, OS, TRI);
+}
+
 void MIRPrinter::print(const MachineFunction &MF) {
   initRegisterMaskIds(MF);
 
@@ -188,6 +194,9 @@ void MIRPrinter::convert(yaml::MachineFunction &MF,
     VReg.ID = I;
     VReg.Class =
         StringRef(TRI->getRegClassName(RegInfo.getRegClass(Reg))).lower();
+    unsigned PreferredReg = RegInfo.getSimpleHint(Reg);
+    if (PreferredReg)
+      printReg(PreferredReg, VReg.PreferredRegister, TRI);
     MF.VirtualRegisters.push_back(VReg);
   }
 }
diff --git a/test/CodeGen/MIR/X86/expected-named-register-in-allocation-hint.mir b/test/CodeGen/MIR/X86/expected-named-register-in-allocation-hint.mir
new file mode 100644 (file)
index 0000000..3dca9ab
--- /dev/null
@@ -0,0 +1,30 @@
+# RUN: not llc -march=x86-64 -start-after machine-scheduler -stop-after machine-scheduler -o /dev/null %s 2>&1 | FileCheck %s
+
+--- |
+
+  define i32 @test(i32 %a, i32 %b) {
+  body:
+    %c = mul i32 %a, %b
+    ret i32 %c
+  }
+
+...
+---
+name:            test
+tracksRegLiveness: true
+registers:
+  - { id: 0, class: gr32 }
+  # CHECK: [[@LINE+1]]:48: expected a named register
+  - { id: 1, class: gr32, preferred-register: '%0' }
+  - { id: 2, class: gr32, preferred-register: '%edi' }
+body:
+  - id:              0
+    name:            body
+    liveins:         [ '%edi', '%esi' ]
+    instructions:
+      - '%1 = COPY %esi'
+      - '%2 = COPY %edi'
+      - '%2 = IMUL32rr %2, %1, implicit-def dead %eflags'
+      - '%eax = COPY %2'
+      - 'RETQ killed %eax'
+...
diff --git a/test/CodeGen/MIR/X86/simple-register-allocation-hints.mir b/test/CodeGen/MIR/X86/simple-register-allocation-hints.mir
new file mode 100644 (file)
index 0000000..42ed70e
--- /dev/null
@@ -0,0 +1,35 @@
+# RUN: llc -march=x86-64 -start-after machine-scheduler -stop-after machine-scheduler -o /dev/null %s | FileCheck %s
+# This test ensures that the MIR parser parses simple register allocation hints
+# correctly.
+
+--- |
+
+  define i32 @test(i32 %a, i32 %b) {
+  body:
+    %c = mul i32 %a, %b
+    ret i32 %c
+  }
+
+...
+---
+name:            test
+tracksRegLiveness: true
+# CHECK: registers:
+# CHECK-NEXT:  - { id: 0, class: gr32 }
+# CHECK-NEXT:  - { id: 1, class: gr32, preferred-register: '%esi' }
+# CHECK-NEXT:  - { id: 2, class: gr32, preferred-register: '%edi' }
+registers:
+  - { id: 0, class: gr32 }
+  - { id: 1, class: gr32, preferred-register: '%esi' }
+  - { id: 2, class: gr32, preferred-register: '%edi' }
+body:
+  - id:              0
+    name:            body
+    liveins:         [ '%edi', '%esi' ]
+    instructions:
+      - '%1 = COPY %esi'
+      - '%2 = COPY %edi'
+      - '%2 = IMUL32rr %2, %1, implicit-def dead %eflags'
+      - '%eax = COPY %2'
+      - 'RETQ killed %eax'
+...