summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/CodeGen/MIRYamlMapping.h5
-rw-r--r--llvm/include/llvm/CodeGen/MachineRegisterInfo.h6
-rw-r--r--llvm/lib/CodeGen/MIRParser/MIRParser.cpp30
-rw-r--r--llvm/lib/CodeGen/MIRPrinter.cpp9
-rw-r--r--llvm/test/CodeGen/MIR/X86/expected-named-register-in-allocation-hint.mir30
-rw-r--r--llvm/test/CodeGen/MIR/X86/simple-register-allocation-hints.mir35
6 files changed, 102 insertions, 13 deletions
diff --git a/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
index 678cec9838a..c99dc40458d 100644
--- a/llvm/include/llvm/CodeGen/MIRYamlMapping.h
+++ b/llvm/include/llvm/CodeGen/MIRYamlMapping.h
@@ -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;
diff --git a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
index 67583be616c..2f823b44801 100644
--- a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h
@@ -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>
diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
index 383fde1101a..67c939cc562 100644
--- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
+++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp
@@ -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;
}
diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp
index 2ae5466392f..574a0ddee1b 100644
--- a/llvm/lib/CodeGen/MIRPrinter.cpp
+++ b/llvm/lib/CodeGen/MIRPrinter.cpp
@@ -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/llvm/test/CodeGen/MIR/X86/expected-named-register-in-allocation-hint.mir b/llvm/test/CodeGen/MIR/X86/expected-named-register-in-allocation-hint.mir
new file mode 100644
index 00000000000..3dca9ab726b
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/X86/expected-named-register-in-allocation-hint.mir
@@ -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/llvm/test/CodeGen/MIR/X86/simple-register-allocation-hints.mir b/llvm/test/CodeGen/MIR/X86/simple-register-allocation-hints.mir
new file mode 100644
index 00000000000..42ed70ee372
--- /dev/null
+++ b/llvm/test/CodeGen/MIR/X86/simple-register-allocation-hints.mir
@@ -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'
+...
OpenPOWER on IntegriCloud