From c48380878548ac69782f53823c4658f160f627d3 Mon Sep 17 00:00:00 2001 From: Alex Lorenz Date: Tue, 11 Aug 2015 00:32:49 +0000 Subject: [PATCH] MIR Serialization: Serialize UsedPhysRegMask from the machine register info. This commit serializes the UsedPhysRegMask register mask from the machine register information class. The mask is serialized as an inverted 'calleeSavedRegisters' mask to keep the output minimal. This commit also allows the MIR parser to infer this mask from the register mask operands if the machine function doesn't specify it. Reviewers: Duncan P. N. Exon Smith llvm-svn: 244548 --- llvm/include/llvm/CodeGen/MIRYamlMapping.h | 2 + .../llvm/CodeGen/MachineRegisterInfo.h | 4 + llvm/lib/CodeGen/MIRParser/MIRParser.cpp | 32 +++++ llvm/lib/CodeGen/MIRPrinter.cpp | 14 +++ .../MIR/X86/used-physical-register-info.mir | 113 ++++++++++++++++++ 5 files changed, 165 insertions(+) create mode 100644 llvm/test/CodeGen/MIR/X86/used-physical-register-info.mir diff --git a/llvm/include/llvm/CodeGen/MIRYamlMapping.h b/llvm/include/llvm/CodeGen/MIRYamlMapping.h index fb78a3e4c3f8..a3844723e8c2 100644 --- a/llvm/include/llvm/CodeGen/MIRYamlMapping.h +++ b/llvm/include/llvm/CodeGen/MIRYamlMapping.h @@ -396,6 +396,7 @@ struct MachineFunction { bool TracksSubRegLiveness = false; std::vector VirtualRegisters; std::vector LiveIns; + Optional> CalleeSavedRegisters; // TODO: Serialize the various register masks. // Frame information MachineFrameInfo FrameInfo; @@ -418,6 +419,7 @@ template <> struct MappingTraits { YamlIO.mapOptional("tracksSubRegLiveness", MF.TracksSubRegLiveness); YamlIO.mapOptional("registers", MF.VirtualRegisters); YamlIO.mapOptional("liveins", MF.LiveIns); + YamlIO.mapOptional("calleeSavedRegisters", MF.CalleeSavedRegisters); YamlIO.mapOptional("frameInfo", MF.FrameInfo); YamlIO.mapOptional("fixedStack", MF.FixedStackObjects); YamlIO.mapOptional("stack", MF.StackObjects); diff --git a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h index 2f823b44801d..56c85475b5d5 100644 --- a/llvm/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/llvm/include/llvm/CodeGen/MachineRegisterInfo.h @@ -653,6 +653,10 @@ public: UsedPhysRegMask.setBitsNotInMask(RegMask); } + const BitVector &getUsedPhysRegsMask() const { return UsedPhysRegMask; } + + void setUsedPhysRegMask(BitVector &Mask) { UsedPhysRegMask = Mask; } + //===--------------------------------------------------------------------===// // Reserved Register Info //===--------------------------------------------------------------------===// diff --git a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp index b5c7d2afefac..9b112e34b038 100644 --- a/llvm/lib/CodeGen/MIRParser/MIRParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIRParser.cpp @@ -107,6 +107,9 @@ public: const yaml::MachineFunction &YamlMF, PerFunctionMIParsingState &PFS); + void inferRegisterInfo(MachineFunction &MF, + const yaml::MachineFunction &YamlMF); + bool initializeFrameInfo(MachineFunction &MF, const yaml::MachineFunction &YamlMF, PerFunctionMIParsingState &PFS); @@ -339,6 +342,7 @@ bool MIRParserImpl::initializeMachineFunction(MachineFunction &MF) { PFS)) return true; } + inferRegisterInfo(MF, YamlMF); // FIXME: This is a temporary workaround until the reserved registers can be // serialized. MF.getRegInfo().freezeReservedRegs(MF); @@ -443,9 +447,37 @@ bool MIRParserImpl::initializeRegisterInfo(MachineFunction &MF, } RegInfo.addLiveIn(Reg, VReg); } + + // Parse the callee saved register mask. + BitVector CalleeSavedRegisterMask(RegInfo.getUsedPhysRegsMask().size()); + if (!YamlMF.CalleeSavedRegisters) + return false; + for (const auto &RegSource : YamlMF.CalleeSavedRegisters.getValue()) { + unsigned Reg = 0; + if (parseNamedRegisterReference(Reg, SM, MF, RegSource.Value, PFS, IRSlots, + Error)) + return error(Error, RegSource.SourceRange); + CalleeSavedRegisterMask[Reg] = true; + } + RegInfo.setUsedPhysRegMask(CalleeSavedRegisterMask.flip()); return false; } +void MIRParserImpl::inferRegisterInfo(MachineFunction &MF, + const yaml::MachineFunction &YamlMF) { + if (YamlMF.CalleeSavedRegisters) + return; + for (const MachineBasicBlock &MBB : MF) { + for (const MachineInstr &MI : MBB) { + for (const MachineOperand &MO : MI.operands()) { + if (!MO.isRegMask()) + continue; + MF.getRegInfo().addPhysRegsUsedFromRegMask(MO.getRegMask()); + } + } + } +} + bool MIRParserImpl::initializeFrameInfo(MachineFunction &MF, const yaml::MachineFunction &YamlMF, PerFunctionMIParsingState &PFS) { diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp index c12b2cfeaccd..8b54a981f8ed 100644 --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -218,6 +218,20 @@ void MIRPrinter::convert(yaml::MachineFunction &MF, printReg(I->second, LiveIn.VirtualRegister, TRI); MF.LiveIns.push_back(LiveIn); } + // The used physical register mask is printed as an inverted callee saved + // register mask. + const BitVector &UsedPhysRegMask = RegInfo.getUsedPhysRegsMask(); + if (UsedPhysRegMask.none()) + return; + std::vector CalleeSavedRegisters; + for (unsigned I = 0, E = UsedPhysRegMask.size(); I != E; ++I) { + if (!UsedPhysRegMask[I]) { + yaml::FlowStringValue Reg; + printReg(I, Reg, TRI); + CalleeSavedRegisters.push_back(Reg); + } + } + MF.CalleeSavedRegisters = CalleeSavedRegisters; } void MIRPrinter::convert(ModuleSlotTracker &MST, diff --git a/llvm/test/CodeGen/MIR/X86/used-physical-register-info.mir b/llvm/test/CodeGen/MIR/X86/used-physical-register-info.mir new file mode 100644 index 000000000000..7858fe29841b --- /dev/null +++ b/llvm/test/CodeGen/MIR/X86/used-physical-register-info.mir @@ -0,0 +1,113 @@ +# RUN: llc -march=x86-64 -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s +# This test ensures that the MIR parser parses the callee saved register mask +# correctly and that the MIR parser can infer it as well. + +--- | + + define i32 @compute(i32 %a) #0 { + body: + %c = mul i32 %a, 11 + ret i32 %c + } + + define i32 @foo(i32 %a) #0 { + entry: + %b = call i32 @compute(i32 %a) + ret i32 %b + } + + define i32 @bar(i32 %a) #0 { + entry: + %b = call i32 @compute(i32 %a) + ret i32 %b + } + + define i32 @empty(i32 %a) #0 { + entry: + %b = call i32 @compute(i32 %a) + ret i32 %b + } + + attributes #0 = { "no-frame-pointer-elim"="false" } + +... +--- +# CHECK: name: compute +# CHECK: liveins: +# CHECK-NEXT: - { reg: '%edi' } +# CHECK-NEXT: frameInfo: +name: compute +liveins: + - { reg: '%edi' } +frameInfo: + stackSize: 8 +body: + - id: 0 + name: body + liveins: [ '%edi' ] + instructions: + - '%eax = IMUL32rri8 %edi, 11, implicit-def %eflags' + - 'RETQ %eax' +... +--- +name: foo +liveins: + - { reg: '%edi' } +# CHECK: name: foo +# CHECK: calleeSavedRegisters: [ '%bh', '%bl', '%bp', '%bpl', '%bx', '%ebp', '%ebx', +# CHECK-NEXT: '%rbp', '%rbx', '%r12', '%r13', '%r14', '%r15', +# CHECK-NEXT: '%r12b', '%r13b', '%r14b', '%r15b', '%r12d', '%r13d', +# CHECK-NEXT: '%r14d', '%r15d', '%r12w', '%r13w', '%r14w', '%r15w' ] +calleeSavedRegisters: [ '%bh', '%bl', '%bp', '%bpl', '%bx', '%ebp', '%ebx', + '%rbp', '%rbx', '%r12', '%r13', '%r14', '%r15', + '%r12b', '%r13b', '%r14b', '%r15b', '%r12d', '%r13d', + '%r14d', '%r15d', '%r12w', '%r13w', '%r14w', '%r15w' ] +body: + - id: 0 + name: entry + liveins: [ '%edi' ] + instructions: + - 'PUSH64r %rax, implicit-def %rsp, implicit %rsp' + - 'CALL64pcrel32 @compute, csr_64, implicit %rsp, implicit %edi, implicit-def %rsp, implicit-def %eax' + - '%rdx = POP64r implicit-def %rsp, implicit %rsp' + - 'RETQ %eax' +... +--- +name: bar +liveins: + - { reg: '%edi' } +# Verify that the callee saved register can be inferred from register mask +# machine operands: +# CHECK: name: bar +# CHECK: calleeSavedRegisters: [ '%bh', '%bl', '%bp', '%bpl', '%bx', '%ebp', '%ebx', +# CHECK-NEXT: '%rbp', '%rbx', '%r12', '%r13', '%r14', '%r15', +# CHECK-NEXT: '%r12b', '%r13b', '%r14b', '%r15b', '%r12d', '%r13d', +# CHECK-NEXT: '%r14d', '%r15d', '%r12w', '%r13w', '%r14w', '%r15w' ] +body: + - id: 0 + name: entry + liveins: [ '%edi' ] + instructions: + - 'PUSH64r %rax, implicit-def %rsp, implicit %rsp' + - 'CALL64pcrel32 @compute, csr_64, implicit %rsp, implicit %edi, implicit-def %rsp, implicit-def %eax' + - '%rdx = POP64r implicit-def %rsp, implicit %rsp' + - 'RETQ %eax' +... +--- +name: empty +liveins: + - { reg: '%edi' } +# Verify that the callee saved register can be empty. +# CHECK: name: empty +# CHECK: calleeSavedRegisters: [ ] +calleeSavedRegisters: [ ] +body: + - id: 0 + name: entry + liveins: [ '%edi' ] + instructions: + - 'PUSH64r %rax, implicit-def %rsp, implicit %rsp' + - 'CALL64pcrel32 @compute, csr_64, implicit %rsp, implicit %edi, implicit-def %rsp, implicit-def %eax' + - '%rdx = POP64r implicit-def %rsp, implicit %rsp' + - 'RETQ %eax' +...