mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-09 11:25:55 +00:00
Rewrite MachineInstr::addOperand() to avoid NumImplicitOps.
The function needs to scan the implicit operands anyway, so no performance is won by caching the number of implicit operands added to an instruction. This also fixes a bug when adding operands after an implicit operand has been added manually. The NumImplicitOps count wasn't kept up to date. MachineInstr::addOperand() will now consistently place all explicit operands before all the implicit operands, regardless of the order they are added. It is possible to change an MI opcode and add additional explicit operands. They will be inserted before any existing implicit operands. The only exception is inline asm instructions where operands are never reordered. This is because of a hack that marks explicit clobber regs on inline asm as <implicit-def> to please the fast register allocator. This hack can go away when InstrEmitter and FastIsel can add exact <dead> flags to physreg defs. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@140744 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -607,100 +607,72 @@ void MachineInstr::AddRegOperandsToUseLists(MachineRegisterInfo &RegInfo) {
|
|||||||
/// an explicit operand it is added at the end of the explicit operand list
|
/// an explicit operand it is added at the end of the explicit operand list
|
||||||
/// (before the first implicit operand).
|
/// (before the first implicit operand).
|
||||||
void MachineInstr::addOperand(const MachineOperand &Op) {
|
void MachineInstr::addOperand(const MachineOperand &Op) {
|
||||||
|
assert(MCID && "Cannot add operands before providing an instr descriptor");
|
||||||
bool isImpReg = Op.isReg() && Op.isImplicit();
|
bool isImpReg = Op.isReg() && Op.isImplicit();
|
||||||
assert((isImpReg || !OperandsComplete()) &&
|
|
||||||
"Trying to add an operand to a machine instr that is already done!");
|
|
||||||
|
|
||||||
MachineRegisterInfo *RegInfo = getRegInfo();
|
MachineRegisterInfo *RegInfo = getRegInfo();
|
||||||
|
|
||||||
// If we are adding the operand to the end of the list, our job is simpler.
|
// If the Operands backing store is reallocated, all register operands must
|
||||||
// This is true most of the time, so this is a reasonable optimization.
|
// be removed and re-added to RegInfo. It is storing pointers to operands.
|
||||||
if (isImpReg || NumImplicitOps == 0) {
|
bool Reallocate = RegInfo &&
|
||||||
// We can only do this optimization if we know that the operand list won't
|
!Operands.empty() && Operands.size() == Operands.capacity();
|
||||||
// reallocate.
|
|
||||||
if (Operands.empty() || Operands.size()+1 <= Operands.capacity()) {
|
|
||||||
Operands.push_back(Op);
|
|
||||||
|
|
||||||
// Set the parent of the operand.
|
// Find the insert location for the new operand. Implicit registers go at
|
||||||
Operands.back().ParentMI = this;
|
// the end, everything goes before the implicit regs.
|
||||||
|
unsigned OpNo = Operands.size();
|
||||||
|
|
||||||
// If the operand is a register, update the operand's use list.
|
// Remove all the implicit operands from RegInfo if they need to be shifted.
|
||||||
if (Op.isReg()) {
|
// FIXME: Allow mixed explicit and implicit operands on inline asm.
|
||||||
Operands.back().AddRegOperandToRegInfo(RegInfo);
|
// InstrEmitter::EmitSpecialNode() is marking inline asm clobbers as
|
||||||
// If the register operand is flagged as early, mark the operand as such
|
// implicit-defs, but they must not be moved around. See the FIXME in
|
||||||
unsigned OpNo = Operands.size() - 1;
|
// InstrEmitter.cpp.
|
||||||
if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1)
|
if (!isImpReg && !isInlineAsm()) {
|
||||||
Operands[OpNo].setIsEarlyClobber(true);
|
while (OpNo && Operands[OpNo-1].isReg() && Operands[OpNo-1].isImplicit()) {
|
||||||
}
|
--OpNo;
|
||||||
return;
|
if (RegInfo)
|
||||||
|
Operands[OpNo].RemoveRegOperandFromRegInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, we have to insert a real operand before any implicit ones.
|
// OpNo now points as the desired insertion point. Unless this is a variadic
|
||||||
unsigned OpNo = Operands.size()-NumImplicitOps;
|
// instruction, only implicit regs are allowed beyond MCID->getNumOperands().
|
||||||
|
assert((isImpReg || MCID->isVariadic() || OpNo < MCID->getNumOperands()) &&
|
||||||
|
"Trying to add an operand to a machine instr that is already done!");
|
||||||
|
|
||||||
// If this instruction isn't embedded into a function, then we don't need to
|
// All operands from OpNo have been removed from RegInfo. If the Operands
|
||||||
// update any operand lists.
|
// backing store needs to be reallocated, we also need to remove any other
|
||||||
if (RegInfo == 0) {
|
// register operands.
|
||||||
// Simple insertion, no reginfo update needed for other register operands.
|
if (Reallocate)
|
||||||
Operands.insert(Operands.begin()+OpNo, Op);
|
for (unsigned i = 0; i != OpNo; ++i)
|
||||||
Operands[OpNo].ParentMI = this;
|
if (Operands[i].isReg())
|
||||||
|
Operands[i].RemoveRegOperandFromRegInfo();
|
||||||
|
|
||||||
// Do explicitly set the reginfo for this operand though, to ensure the
|
// Insert the new operand at OpNo.
|
||||||
// next/prev fields are properly nulled out.
|
Operands.insert(Operands.begin() + OpNo, Op);
|
||||||
if (Operands[OpNo].isReg()) {
|
Operands[OpNo].ParentMI = this;
|
||||||
Operands[OpNo].AddRegOperandToRegInfo(0);
|
|
||||||
// If the register operand is flagged as early, mark the operand as such
|
|
||||||
if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1)
|
|
||||||
Operands[OpNo].setIsEarlyClobber(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (Operands.size()+1 <= Operands.capacity()) {
|
// The Operands backing store has now been reallocated, so we can re-add the
|
||||||
// Otherwise, we have to remove register operands from their register use
|
// operands before OpNo.
|
||||||
// list, add the operand, then add the register operands back to their use
|
if (Reallocate)
|
||||||
// list. This also must handle the case when the operand list reallocates
|
for (unsigned i = 0; i != OpNo; ++i)
|
||||||
// to somewhere else.
|
if (Operands[i].isReg())
|
||||||
|
Operands[i].AddRegOperandToRegInfo(RegInfo);
|
||||||
|
|
||||||
// If insertion of this operand won't cause reallocation of the operand
|
// When adding a register operand, tell RegInfo about it.
|
||||||
// list, just remove the implicit operands, add the operand, then re-add all
|
if (Operands[OpNo].isReg()) {
|
||||||
// the rest of the operands.
|
// Add the new operand to RegInfo, even when RegInfo is NULL.
|
||||||
for (unsigned i = OpNo, e = Operands.size(); i != e; ++i) {
|
// This will initialize the linked list pointers.
|
||||||
assert(Operands[i].isReg() && "Should only be an implicit reg!");
|
Operands[OpNo].AddRegOperandToRegInfo(RegInfo);
|
||||||
Operands[i].RemoveRegOperandFromRegInfo();
|
// If the register operand is flagged as early, mark the operand as such.
|
||||||
}
|
if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1)
|
||||||
|
Operands[OpNo].setIsEarlyClobber(true);
|
||||||
|
}
|
||||||
|
|
||||||
// Add the operand. If it is a register, add it to the reg list.
|
// Re-add all the implicit ops.
|
||||||
Operands.insert(Operands.begin()+OpNo, Op);
|
if (RegInfo) {
|
||||||
Operands[OpNo].ParentMI = this;
|
for (unsigned i = OpNo + 1, e = Operands.size(); i != e; ++i) {
|
||||||
|
|
||||||
if (Operands[OpNo].isReg()) {
|
|
||||||
Operands[OpNo].AddRegOperandToRegInfo(RegInfo);
|
|
||||||
// If the register operand is flagged as early, mark the operand as such
|
|
||||||
if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1)
|
|
||||||
Operands[OpNo].setIsEarlyClobber(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-add all the implicit ops.
|
|
||||||
for (unsigned i = OpNo+1, e = Operands.size(); i != e; ++i) {
|
|
||||||
assert(Operands[i].isReg() && "Should only be an implicit reg!");
|
assert(Operands[i].isReg() && "Should only be an implicit reg!");
|
||||||
Operands[i].AddRegOperandToRegInfo(RegInfo);
|
Operands[i].AddRegOperandToRegInfo(RegInfo);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// Otherwise, we will be reallocating the operand list. Remove all reg
|
|
||||||
// operands from their list, then readd them after the operand list is
|
|
||||||
// reallocated.
|
|
||||||
RemoveRegOperandsFromUseLists();
|
|
||||||
|
|
||||||
Operands.insert(Operands.begin()+OpNo, Op);
|
|
||||||
Operands[OpNo].ParentMI = this;
|
|
||||||
|
|
||||||
// Re-add all the operands.
|
|
||||||
AddRegOperandsToUseLists(*RegInfo);
|
|
||||||
|
|
||||||
// If the register operand is flagged as early, mark the operand as such
|
|
||||||
if (Operands[OpNo].isReg()
|
|
||||||
&& MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1)
|
|
||||||
Operands[OpNo].setIsEarlyClobber(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1385,7 +1357,7 @@ void MachineInstr::print(raw_ostream &OS, const TargetMachine *TM) const {
|
|||||||
unsigned AsmDescOp = ~0u;
|
unsigned AsmDescOp = ~0u;
|
||||||
unsigned AsmOpCount = 0;
|
unsigned AsmOpCount = 0;
|
||||||
|
|
||||||
if (isInlineAsm()) {
|
if (isInlineAsm() && e >= InlineAsm::MIOp_FirstOperand) {
|
||||||
// Print asm string.
|
// Print asm string.
|
||||||
OS << " ";
|
OS << " ";
|
||||||
getOperand(InlineAsm::MIOp_AsmString).print(OS, TM);
|
getOperand(InlineAsm::MIOp_AsmString).print(OS, TM);
|
||||||
|
Reference in New Issue
Block a user