mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-07-21 18:29:45 +00: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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@148250 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1857b51ef5
commit
7739cad69d
@ -707,6 +707,21 @@ ret
|
|||||||
|
|
||||||
</div>
|
</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>
|
<h4>
|
||||||
<a name="ssa">Machine code in SSA form</a>
|
<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
|
frozen when register allocation starts. Target hooks should use the
|
||||||
<code>MRI->canReserveReg(FramePtr)</code> method to avoid accidentally
|
<code>MRI->canReserveReg(FramePtr)</code> method to avoid accidentally
|
||||||
disabling frame pointer elimination during register allocation.</li>
|
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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -124,6 +124,11 @@ public:
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MachineInstrBuilder &addRegMask(const uint32_t *Mask) const {
|
||||||
|
MI->addOperand(MachineOperand::CreateRegMask(Mask));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
const MachineInstrBuilder &addMemOperand(MachineMemOperand *MMO) const {
|
const MachineInstrBuilder &addMemOperand(MachineMemOperand *MMO) const {
|
||||||
MI->addMemOperand(*MI->getParent()->getParent(), MMO);
|
MI->addMemOperand(*MI->getParent()->getParent(), MMO);
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -48,6 +48,7 @@ public:
|
|||||||
MO_ExternalSymbol, ///< Name of external global symbol
|
MO_ExternalSymbol, ///< Name of external global symbol
|
||||||
MO_GlobalAddress, ///< Address of a global value
|
MO_GlobalAddress, ///< Address of a global value
|
||||||
MO_BlockAddress, ///< Address of a basic block
|
MO_BlockAddress, ///< Address of a basic block
|
||||||
|
MO_RegisterMask, ///< Mask of preserved registers.
|
||||||
MO_Metadata, ///< Metadata reference (for debug info)
|
MO_Metadata, ///< Metadata reference (for debug info)
|
||||||
MO_MCSymbol ///< MCSymbol reference (for debug/eh info)
|
MO_MCSymbol ///< MCSymbol reference (for debug/eh info)
|
||||||
};
|
};
|
||||||
@ -141,6 +142,7 @@ private:
|
|||||||
const ConstantFP *CFP; // For MO_FPImmediate.
|
const ConstantFP *CFP; // For MO_FPImmediate.
|
||||||
const ConstantInt *CI; // For MO_CImmediate. Integers > 64bit.
|
const ConstantInt *CI; // For MO_CImmediate. Integers > 64bit.
|
||||||
int64_t ImmVal; // For MO_Immediate.
|
int64_t ImmVal; // For MO_Immediate.
|
||||||
|
const uint32_t *RegMask; // For MO_RegisterMask.
|
||||||
const MDNode *MD; // For MO_Metadata.
|
const MDNode *MD; // For MO_Metadata.
|
||||||
MCSymbol *Sym; // For MO_MCSymbol
|
MCSymbol *Sym; // For MO_MCSymbol
|
||||||
|
|
||||||
@ -220,10 +222,13 @@ public:
|
|||||||
bool isSymbol() const { return OpKind == MO_ExternalSymbol; }
|
bool isSymbol() const { return OpKind == MO_ExternalSymbol; }
|
||||||
/// isBlockAddress - Tests if this is a MO_BlockAddress operand.
|
/// isBlockAddress - Tests if this is a MO_BlockAddress operand.
|
||||||
bool isBlockAddress() const { return OpKind == MO_BlockAddress; }
|
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.
|
/// isMetadata - Tests if this is a MO_Metadata operand.
|
||||||
bool isMetadata() const { return OpKind == MO_Metadata; }
|
bool isMetadata() const { return OpKind == MO_Metadata; }
|
||||||
bool isMCSymbol() const { return OpKind == MO_MCSymbol; }
|
bool isMCSymbol() const { return OpKind == MO_MCSymbol; }
|
||||||
|
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
// Accessors for Register Operands
|
// Accessors for Register Operands
|
||||||
//===--------------------------------------------------------------------===//
|
//===--------------------------------------------------------------------===//
|
||||||
@ -436,6 +441,22 @@ public:
|
|||||||
return Contents.OffsetedInfo.Val.SymbolName;
|
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 {
|
const MDNode *getMetadata() const {
|
||||||
assert(isMetadata() && "Wrong MachineOperand accessor");
|
assert(isMetadata() && "Wrong MachineOperand accessor");
|
||||||
return Contents.MD;
|
return Contents.MD;
|
||||||
@ -582,6 +603,23 @@ public:
|
|||||||
Op.setTargetFlags(TargetFlags);
|
Op.setTargetFlags(TargetFlags);
|
||||||
return Op;
|
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) {
|
static MachineOperand CreateMetadata(const MDNode *Meta) {
|
||||||
MachineOperand Op(MachineOperand::MO_Metadata);
|
MachineOperand Op(MachineOperand::MO_Metadata);
|
||||||
Op.Contents.MD = Meta;
|
Op.Contents.MD = Meta;
|
||||||
|
@ -216,6 +216,8 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const {
|
|||||||
getOffset() == Other.getOffset();
|
getOffset() == Other.getOffset();
|
||||||
case MachineOperand::MO_BlockAddress:
|
case MachineOperand::MO_BlockAddress:
|
||||||
return getBlockAddress() == Other.getBlockAddress();
|
return getBlockAddress() == Other.getBlockAddress();
|
||||||
|
case MO_RegisterMask:
|
||||||
|
return getRegMask() == Other.getRegMask();
|
||||||
case MachineOperand::MO_MCSymbol:
|
case MachineOperand::MO_MCSymbol:
|
||||||
return getMCSymbol() == Other.getMCSymbol();
|
return getMCSymbol() == Other.getMCSymbol();
|
||||||
case MachineOperand::MO_Metadata:
|
case MachineOperand::MO_Metadata:
|
||||||
@ -324,6 +326,9 @@ void MachineOperand::print(raw_ostream &OS, const TargetMachine *TM) const {
|
|||||||
WriteAsOperand(OS, getBlockAddress(), /*PrintType=*/false);
|
WriteAsOperand(OS, getBlockAddress(), /*PrintType=*/false);
|
||||||
OS << '>';
|
OS << '>';
|
||||||
break;
|
break;
|
||||||
|
case MachineOperand::MO_RegisterMask:
|
||||||
|
OS << (getRegMask() ? "<regmask>" : "<regmask:null>");
|
||||||
|
break;
|
||||||
case MachineOperand::MO_Metadata:
|
case MachineOperand::MO_Metadata:
|
||||||
OS << '<';
|
OS << '<';
|
||||||
WriteAsOperand(OS, getMetadata(), /*PrintType=*/false);
|
WriteAsOperand(OS, getMetadata(), /*PrintType=*/false);
|
||||||
|
Loading…
Reference in New Issue
Block a user