From 7739cad69d2590f556afc9fc3048f967b5a3f4f6 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Mon, 16 Jan 2012 19:22:00 +0000 Subject: [PATCH] Add a new kind of MachineOperand: MO_RegisterMask. Register masks will be used as a compact representation of large clobber lists. Currently, an x86 call instruction has some 40 operands representing call-clobbered registers. That's more than 1kB of useless operands per call site. A register mask operand references a bit mask of call-preserved registers, everything else is clobbered. The bit mask will typically come from TargetRegisterInfo::getCallPreservedMask(). By abandoning ImplicitDefs for call-clobbered registers, it also becomes possible to share call instruction descriptions between calling conventions, and we can get rid of the WINCALL* instructions. This patch introduces the new operand kind. Future patches will add RegMask support to target-independent passes before finally the fixed clobber lists can be removed from call instruction descriptions. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148250 91177308-0d34-0410-b5e6-96231b3b80d8 --- docs/CodeGenerator.html | 15 +++++++++ docs/ReleaseNotes.html | 4 +++ include/llvm/CodeGen/MachineInstrBuilder.h | 5 +++ include/llvm/CodeGen/MachineOperand.h | 38 ++++++++++++++++++++++ lib/CodeGen/MachineInstr.cpp | 5 +++ 5 files changed, 67 insertions(+) diff --git a/docs/CodeGenerator.html b/docs/CodeGenerator.html index 6b5b204dc58..32a3a971a32 100644 --- a/docs/CodeGenerator.html +++ b/docs/CodeGenerator.html @@ -707,6 +707,21 @@ ret + +

+ Call-clobbered registers +

+ +
+ +

Some machine instructions, like calls, clobber a large number of physical + registers. Rather than adding <def,dead> operands for + all of them, it is possible to use an MO_RegisterMask operand + instead. The register mask operand holds a bit mask of preserved registers, + and everything else is considered to be clobbered by the instruction.

+ +
+

Machine code in SSA form diff --git a/docs/ReleaseNotes.html b/docs/ReleaseNotes.html index 011cbbd344c..b090995da10 100644 --- a/docs/ReleaseNotes.html +++ b/docs/ReleaseNotes.html @@ -355,6 +355,10 @@ Release Notes.

frozen when register allocation starts. Target hooks should use the MRI->canReserveReg(FramePtr) method to avoid accidentally disabling frame pointer elimination during register allocation. +
  • A new kind of MachineOperand provides a compact + representation of large clobber lists on call instructions. The register + mask operand references a bit mask of preserved registers. Everything else is + clobbered.
  • diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index 80256428b27..a6f995bc365 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -124,6 +124,11 @@ public: return *this; } + const MachineInstrBuilder &addRegMask(const uint32_t *Mask) const { + MI->addOperand(MachineOperand::CreateRegMask(Mask)); + return *this; + } + const MachineInstrBuilder &addMemOperand(MachineMemOperand *MMO) const { MI->addMemOperand(*MI->getParent()->getParent(), MMO); return *this; diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 2a977de0e35..6a2e38dd84e 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -48,6 +48,7 @@ public: MO_ExternalSymbol, ///< Name of external global symbol MO_GlobalAddress, ///< Address of a global value MO_BlockAddress, ///< Address of a basic block + MO_RegisterMask, ///< Mask of preserved registers. MO_Metadata, ///< Metadata reference (for debug info) MO_MCSymbol ///< MCSymbol reference (for debug/eh info) }; @@ -141,6 +142,7 @@ private: const ConstantFP *CFP; // For MO_FPImmediate. const ConstantInt *CI; // For MO_CImmediate. Integers > 64bit. int64_t ImmVal; // For MO_Immediate. + const uint32_t *RegMask; // For MO_RegisterMask. const MDNode *MD; // For MO_Metadata. MCSymbol *Sym; // For MO_MCSymbol @@ -220,10 +222,13 @@ public: bool isSymbol() const { return OpKind == MO_ExternalSymbol; } /// isBlockAddress - Tests if this is a MO_BlockAddress operand. bool isBlockAddress() const { return OpKind == MO_BlockAddress; } + /// isRegMask - Tests if this is a MO_RegisterMask operand. + bool isRegMask() const { return OpKind == MO_RegisterMask; } /// isMetadata - Tests if this is a MO_Metadata operand. bool isMetadata() const { return OpKind == MO_Metadata; } bool isMCSymbol() const { return OpKind == MO_MCSymbol; } + //===--------------------------------------------------------------------===// // Accessors for Register Operands //===--------------------------------------------------------------------===// @@ -436,6 +441,22 @@ public: return Contents.OffsetedInfo.Val.SymbolName; } + /// clobbersPhysReg - Returns true if this RegMask operand clobbers PhysReg. + bool clobbersPhysReg(unsigned PhysReg) const { + assert(isRegMask() && "Wrong MachineOperand accessor"); + // See TargetRegisterInfo.h. + assert(PhysReg < (1u << 30) && "Not a physical register"); + return !Contents.RegMask || + !(Contents.RegMask[PhysReg / 32] & (1u << PhysReg % 32)); + } + + /// getRegMask - Returns a bit mask of registers preserved by this RegMask + /// operand. A NULL pointer means that all registers are clobbered. + const uint32_t *getRegMask() const { + assert(isRegMask() && "Wrong MachineOperand accessor"); + return Contents.RegMask; + } + const MDNode *getMetadata() const { assert(isMetadata() && "Wrong MachineOperand accessor"); return Contents.MD; @@ -582,6 +603,23 @@ public: Op.setTargetFlags(TargetFlags); return Op; } + /// CreateRegMask - Creates a register mask operand referencing Mask. The + /// operand does not take ownership of the memory referenced by Mask, it must + /// remain valid for the lifetime of the operand. + /// + /// A RegMask operand represents a set of non-clobbered physical registers on + /// an instruction that clobbers many registers, typically a call. The bit + /// mask has a bit set for each physreg that is preserved by this + /// instruction, as described in the documentation for + /// TargetRegisterInfo::getCallPreservedMask(). + /// + /// Any physreg with a 0 bit in the mask is clobbered by the instruction. + /// + static MachineOperand CreateRegMask(const uint32_t *Mask) { + MachineOperand Op(MachineOperand::MO_RegisterMask); + Op.Contents.RegMask = Mask; + return Op; + } static MachineOperand CreateMetadata(const MDNode *Meta) { MachineOperand Op(MachineOperand::MO_Metadata); Op.Contents.MD = Meta; diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 99081bdbae1..18e9f1a855e 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -216,6 +216,8 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const { getOffset() == Other.getOffset(); case MachineOperand::MO_BlockAddress: return getBlockAddress() == Other.getBlockAddress(); + case MO_RegisterMask: + return getRegMask() == Other.getRegMask(); case MachineOperand::MO_MCSymbol: return getMCSymbol() == Other.getMCSymbol(); case MachineOperand::MO_Metadata: @@ -324,6 +326,9 @@ void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const { WriteAsOperand(OS, getBlockAddress(), /*PrintType=*/false); OS << '>'; break; + case MachineOperand::MO_RegisterMask: + OS << (getRegMask() ? "" : ""); + break; case MachineOperand::MO_Metadata: OS << '<'; WriteAsOperand(OS, getMetadata(), /*PrintType=*/false);