forked from OSchip/llvm-project
MIR Serialization: Serialize the simple virtual register allocation hints.
This commit serializes the virtual register allocations hints of type 0. These hints specify the preferred physical registers for allocations. llvm-svn: 243156
This commit is contained in:
parent
bd210e638a
commit
ab4cbcfda7
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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'
|
||||
...
|
|
@ -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'
|
||||
...
|
Loading…
Reference in New Issue