Add a new kind of MachineOperand: MO_RegisterMask.
authorJakob Stoklund Olesen <stoklund@2pi.dk>
Mon, 16 Jan 2012 19:22:00 +0000 (19:22 +0000)
committerJakob Stoklund Olesen <stoklund@2pi.dk>
Mon, 16 Jan 2012 19:22:00 +0000 (19:22 +0000)
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
docs/ReleaseNotes.html
include/llvm/CodeGen/MachineInstrBuilder.h
include/llvm/CodeGen/MachineOperand.h
lib/CodeGen/MachineInstr.cpp

index 6b5b204dc58e18c3fb159c02ed060e7348feff90..32a3a971a32e088cc89c883362b6b01ba701f236 100644 (file)
@@ -707,6 +707,21 @@ ret
 
 </div>
 
+<!-- _______________________________________________________________________ -->
+<h4>
+  <a name="callclobber">Call-clobbered registers</a>
+</h4>
+
+<div>
+
+<p>Some machine instructions, like calls, clobber a large number of physical
+   registers.  Rather than adding <code>&lt;def,dead&gt;</code> operands for
+   all of them, it is possible to use an <code>MO_RegisterMask</code> operand
+   instead.  The register mask operand holds a bit mask of preserved registers,
+   and everything else is considered to be clobbered by the instruction.  </p>
+
+</div>
+
 <!-- _______________________________________________________________________ -->
 <h4>
   <a name="ssa">Machine code in SSA form</a>
index 011cbbd344c434e6d1e746e0b4e0a87f39b56c15..b090995da10d5d14e310cfd102eb122897fb942f 100644 (file)
@@ -355,6 +355,10 @@ Release Notes</a>.</h1>
   frozen when register allocation starts.  Target hooks should use the
   <code>MRI->canReserveReg(FramePtr)</code> method to avoid accidentally
   disabling frame pointer elimination during register allocation.</li>
+  <li>A new kind of <code>MachineOperand</code> 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.</li>
 </ul>
 </div>
 
index 80256428b278e5fdb01a0ad5c9bd3882208f8529..a6f995bc365a1530a169e7d40afeee035791665a 100644 (file)
@@ -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;
index 2a977de0e3511f3a71ca221b9defaf609dd49b46..6a2e38dd84ee3b65b5943f751ffc1718bf09bdf0 100644 (file)
@@ -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;
index 99081bdbae1cb9dfbbd9001fb85f0af5bb331d61..18e9f1a855eea40550d3dba8dfe422ccdde5906a 100644 (file)
@@ -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() ? "<regmask>" : "<regmask:null>");
+    break;
   case MachineOperand::MO_Metadata:
     OS << '<';
     WriteAsOperand(OS, getMetadata(), /*PrintType=*/false);