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
This commit is contained in:
Jakob Stoklund Olesen 2012-01-16 19:22:00 +00:00
parent 1857b51ef5
commit 7739cad69d
5 changed files with 67 additions and 0 deletions

View 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>

View 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>

View 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;

View 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;

View 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);