mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
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. llvm-svn: 148250
This commit is contained in:
parent
a343d87eac
commit
77ce60119b
@ -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><def,dead></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>
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user