aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakob Stoklund Olesen <stoklund@2pi.dk>2012-01-16 19:22:00 +0000
committerJakob Stoklund Olesen <stoklund@2pi.dk>2012-01-16 19:22:00 +0000
commit7739cad69d2590f556afc9fc3048f967b5a3f4f6 (patch)
tree0b94e1e1d7db58d9d497876c3a21d4d9e85188d9
parent1857b51ef57697992afe3955f5f90e79612142d8 (diff)
downloadexternal_llvm-7739cad69d2590f556afc9fc3048f967b5a3f4f6.zip
external_llvm-7739cad69d2590f556afc9fc3048f967b5a3f4f6.tar.gz
external_llvm-7739cad69d2590f556afc9fc3048f967b5a3f4f6.tar.bz2
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
-rw-r--r--docs/CodeGenerator.html15
-rw-r--r--docs/ReleaseNotes.html4
-rw-r--r--include/llvm/CodeGen/MachineInstrBuilder.h5
-rw-r--r--include/llvm/CodeGen/MachineOperand.h38
-rw-r--r--lib/CodeGen/MachineInstr.cpp5
5 files changed, 67 insertions, 0 deletions
diff --git a/docs/CodeGenerator.html b/docs/CodeGenerator.html
index 6b5b204..32a3a97 100644
--- a/docs/CodeGenerator.html
+++ b/docs/CodeGenerator.html
@@ -709,6 +709,21 @@ ret
<!-- _______________________________________________________________________ -->
<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>
</h4>
diff --git a/docs/ReleaseNotes.html b/docs/ReleaseNotes.html
index 011cbbd..b090995 100644
--- a/docs/ReleaseNotes.html
+++ b/docs/ReleaseNotes.html
@@ -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>
diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h
index 8025642..a6f995b 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 2a977de..6a2e38d 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 99081bd..18e9f1a 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() ? "<regmask>" : "<regmask:null>");
+ break;
case MachineOperand::MO_Metadata:
OS << '<';
WriteAsOperand(OS, getMetadata(), /*PrintType=*/false);