mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-07 12:28:24 +00:00
Use ArrayRecycler for MachineInstr operand lists.
Instead of an std::vector<MachineOperand>, use MachineOperand arrays from an ArrayRecycler living in MachineFunction. This has several advantages: - MachineInstr now has a trivial destructor, making it possible to delete them in batches when destroying MachineFunction. This will be enabled in a later patch. - Bypassing malloc() and free() can be faster, depending on the system library. - MachineInstr objects and their operands are allocated from the same BumpPtrAllocator, so they will usually be next to each other in memory, providing better locality of reference. - Reduce MachineInstr footprint. A std::vector is 24 bytes, the new operand array representation only uses 8+4+1 bytes in MachineInstr. - Better control over operand array reallocations. In the old representation, the use-def chains would be reordered whenever a std::vector reached its capacity. The new implementation never changes the use-def chain order. Note that some decisions in the code generator depend on the use-def chain orders, so this patch may cause different assembly to be produced in a few cases. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171598 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -21,6 +21,7 @@
|
|||||||
#include "llvm/ADT/ilist.h"
|
#include "llvm/ADT/ilist.h"
|
||||||
#include "llvm/CodeGen/MachineBasicBlock.h"
|
#include "llvm/CodeGen/MachineBasicBlock.h"
|
||||||
#include "llvm/Support/Allocator.h"
|
#include "llvm/Support/Allocator.h"
|
||||||
|
#include "llvm/Support/ArrayRecycler.h"
|
||||||
#include "llvm/Support/DebugLoc.h"
|
#include "llvm/Support/DebugLoc.h"
|
||||||
#include "llvm/Support/Recycler.h"
|
#include "llvm/Support/Recycler.h"
|
||||||
|
|
||||||
@@ -105,6 +106,9 @@ class MachineFunction {
|
|||||||
// Allocation management for instructions in function.
|
// Allocation management for instructions in function.
|
||||||
Recycler<MachineInstr> InstructionRecycler;
|
Recycler<MachineInstr> InstructionRecycler;
|
||||||
|
|
||||||
|
// Allocation management for operand arrays on instructions.
|
||||||
|
ArrayRecycler<MachineOperand> OperandRecycler;
|
||||||
|
|
||||||
// Allocation management for basic blocks in function.
|
// Allocation management for basic blocks in function.
|
||||||
Recycler<MachineBasicBlock> BasicBlockRecycler;
|
Recycler<MachineBasicBlock> BasicBlockRecycler;
|
||||||
|
|
||||||
@@ -394,6 +398,21 @@ public:
|
|||||||
MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO,
|
MachineMemOperand *getMachineMemOperand(const MachineMemOperand *MMO,
|
||||||
int64_t Offset, uint64_t Size);
|
int64_t Offset, uint64_t Size);
|
||||||
|
|
||||||
|
typedef ArrayRecycler<MachineOperand>::Capacity OperandCapacity;
|
||||||
|
|
||||||
|
/// Allocate an array of MachineOperands. This is only intended for use by
|
||||||
|
/// internal MachineInstr functions.
|
||||||
|
MachineOperand *allocateOperandArray(OperandCapacity Cap) {
|
||||||
|
return OperandRecycler.allocate(Cap, Allocator);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Dellocate an array of MachineOperands and recycle the memory. This is
|
||||||
|
/// only intended for use by internal MachineInstr functions.
|
||||||
|
/// Cap must be the same capacity that was used to allocate the array.
|
||||||
|
void deallocateOperandArray(OperandCapacity Cap, MachineOperand *Array) {
|
||||||
|
OperandRecycler.deallocate(Cap, Array);
|
||||||
|
}
|
||||||
|
|
||||||
/// allocateMemRefsArray - Allocate an array to hold MachineMemOperand
|
/// allocateMemRefsArray - Allocate an array to hold MachineMemOperand
|
||||||
/// pointers. This array is owned by the MachineFunction.
|
/// pointers. This array is owned by the MachineFunction.
|
||||||
MachineInstr::mmo_iterator allocateMemRefsArray(unsigned long Num);
|
MachineInstr::mmo_iterator allocateMemRefsArray(unsigned long Num);
|
||||||
|
@@ -25,6 +25,7 @@
|
|||||||
#include "llvm/CodeGen/MachineOperand.h"
|
#include "llvm/CodeGen/MachineOperand.h"
|
||||||
#include "llvm/IR/InlineAsm.h"
|
#include "llvm/IR/InlineAsm.h"
|
||||||
#include "llvm/MC/MCInstrDesc.h"
|
#include "llvm/MC/MCInstrDesc.h"
|
||||||
|
#include "llvm/Support/ArrayRecycler.h"
|
||||||
#include "llvm/Support/DebugLoc.h"
|
#include "llvm/Support/DebugLoc.h"
|
||||||
#include "llvm/Target/TargetOpcodes.h"
|
#include "llvm/Target/TargetOpcodes.h"
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -63,6 +64,13 @@ public:
|
|||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
const MCInstrDesc *MCID; // Instruction descriptor.
|
const MCInstrDesc *MCID; // Instruction descriptor.
|
||||||
|
MachineBasicBlock *Parent; // Pointer to the owning basic block.
|
||||||
|
|
||||||
|
// Operands are allocated by an ArrayRecycler.
|
||||||
|
MachineOperand *Operands; // Pointer to the first operand.
|
||||||
|
unsigned NumOperands; // Number of operands on instruction.
|
||||||
|
typedef ArrayRecycler<MachineOperand>::Capacity OperandCapacity;
|
||||||
|
OperandCapacity CapOperands; // Capacity of the Operands array.
|
||||||
|
|
||||||
uint8_t Flags; // Various bits of additional
|
uint8_t Flags; // Various bits of additional
|
||||||
// information about machine
|
// information about machine
|
||||||
@@ -78,8 +86,6 @@ private:
|
|||||||
uint16_t NumMemRefs; // information on memory references
|
uint16_t NumMemRefs; // information on memory references
|
||||||
mmo_iterator MemRefs;
|
mmo_iterator MemRefs;
|
||||||
|
|
||||||
std::vector<MachineOperand> Operands; // the operands
|
|
||||||
MachineBasicBlock *Parent; // Pointer to the owning basic block.
|
|
||||||
DebugLoc debugLoc; // Source line information.
|
DebugLoc debugLoc; // Source line information.
|
||||||
|
|
||||||
MachineInstr(const MachineInstr&) LLVM_DELETED_FUNCTION;
|
MachineInstr(const MachineInstr&) LLVM_DELETED_FUNCTION;
|
||||||
@@ -252,7 +258,7 @@ public:
|
|||||||
|
|
||||||
/// Access to explicit operands of the instruction.
|
/// Access to explicit operands of the instruction.
|
||||||
///
|
///
|
||||||
unsigned getNumOperands() const { return (unsigned)Operands.size(); }
|
unsigned getNumOperands() const { return NumOperands; }
|
||||||
|
|
||||||
const MachineOperand& getOperand(unsigned i) const {
|
const MachineOperand& getOperand(unsigned i) const {
|
||||||
assert(i < getNumOperands() && "getOperand() out of range!");
|
assert(i < getNumOperands() && "getOperand() out of range!");
|
||||||
@@ -268,14 +274,14 @@ public:
|
|||||||
unsigned getNumExplicitOperands() const;
|
unsigned getNumExplicitOperands() const;
|
||||||
|
|
||||||
/// iterator/begin/end - Iterate over all operands of a machine instruction.
|
/// iterator/begin/end - Iterate over all operands of a machine instruction.
|
||||||
typedef std::vector<MachineOperand>::iterator mop_iterator;
|
typedef MachineOperand *mop_iterator;
|
||||||
typedef std::vector<MachineOperand>::const_iterator const_mop_iterator;
|
typedef const MachineOperand *const_mop_iterator;
|
||||||
|
|
||||||
mop_iterator operands_begin() { return Operands.begin(); }
|
mop_iterator operands_begin() { return Operands; }
|
||||||
mop_iterator operands_end() { return Operands.end(); }
|
mop_iterator operands_end() { return Operands + NumOperands; }
|
||||||
|
|
||||||
const_mop_iterator operands_begin() const { return Operands.begin(); }
|
const_mop_iterator operands_begin() const { return Operands; }
|
||||||
const_mop_iterator operands_end() const { return Operands.end(); }
|
const_mop_iterator operands_end() const { return Operands + NumOperands; }
|
||||||
|
|
||||||
/// Access to memory operands of the instruction
|
/// Access to memory operands of the instruction
|
||||||
mmo_iterator memoperands_begin() const { return MemRefs; }
|
mmo_iterator memoperands_begin() const { return MemRefs; }
|
||||||
|
@@ -35,6 +35,11 @@ class MCSymbol;
|
|||||||
|
|
||||||
/// MachineOperand class - Representation of each machine instruction operand.
|
/// MachineOperand class - Representation of each machine instruction operand.
|
||||||
///
|
///
|
||||||
|
/// This class isn't a POD type because it has a private constructor, but its
|
||||||
|
/// destructor must be trivial. Functions like MachineInstr::addOperand(),
|
||||||
|
/// MachineRegisterInfo::moveOperands(), and MF::DeleteMachineInstr() depend on
|
||||||
|
/// not having to call the MachineOperand destructor.
|
||||||
|
///
|
||||||
class MachineOperand {
|
class MachineOperand {
|
||||||
public:
|
public:
|
||||||
enum MachineOperandType {
|
enum MachineOperandType {
|
||||||
|
@@ -78,6 +78,7 @@ MachineFunction::MachineFunction(const Function *F, const TargetMachine &TM,
|
|||||||
MachineFunction::~MachineFunction() {
|
MachineFunction::~MachineFunction() {
|
||||||
BasicBlocks.clear();
|
BasicBlocks.clear();
|
||||||
InstructionRecycler.clear(Allocator);
|
InstructionRecycler.clear(Allocator);
|
||||||
|
OperandRecycler.clear(Allocator);
|
||||||
BasicBlockRecycler.clear(Allocator);
|
BasicBlockRecycler.clear(Allocator);
|
||||||
if (RegInfo) {
|
if (RegInfo) {
|
||||||
RegInfo->~MachineRegisterInfo();
|
RegInfo->~MachineRegisterInfo();
|
||||||
@@ -177,6 +178,12 @@ MachineFunction::CloneMachineInstr(const MachineInstr *Orig) {
|
|||||||
///
|
///
|
||||||
void
|
void
|
||||||
MachineFunction::DeleteMachineInstr(MachineInstr *MI) {
|
MachineFunction::DeleteMachineInstr(MachineInstr *MI) {
|
||||||
|
// Strip it for parts. The operand array and the MI object itself are
|
||||||
|
// independently recyclable.
|
||||||
|
if (MI->Operands)
|
||||||
|
deallocateOperandArray(MI->CapOperands, MI->Operands);
|
||||||
|
MI->Operands = 0;
|
||||||
|
MI->NumOperands = 0;
|
||||||
MI->~MachineInstr();
|
MI->~MachineInstr();
|
||||||
InstructionRecycler.Deallocate(Allocator, MI);
|
InstructionRecycler.Deallocate(Allocator, MI);
|
||||||
}
|
}
|
||||||
|
@@ -532,12 +532,16 @@ void MachineInstr::addImplicitDefUseOperands(MachineFunction &MF) {
|
|||||||
/// the MCInstrDesc.
|
/// the MCInstrDesc.
|
||||||
MachineInstr::MachineInstr(MachineFunction &MF, const MCInstrDesc &tid,
|
MachineInstr::MachineInstr(MachineFunction &MF, const MCInstrDesc &tid,
|
||||||
const DebugLoc dl, bool NoImp)
|
const DebugLoc dl, bool NoImp)
|
||||||
: MCID(&tid), Flags(0), AsmPrinterFlags(0),
|
: MCID(&tid), Parent(0), Operands(0), NumOperands(0),
|
||||||
NumMemRefs(0), MemRefs(0), Parent(0), debugLoc(dl) {
|
Flags(0), AsmPrinterFlags(0),
|
||||||
unsigned NumImplicitOps = 0;
|
NumMemRefs(0), MemRefs(0), debugLoc(dl) {
|
||||||
if (!NoImp)
|
// Reserve space for the expected number of operands.
|
||||||
NumImplicitOps = MCID->getNumImplicitDefs() + MCID->getNumImplicitUses();
|
if (unsigned NumOps = MCID->getNumOperands() +
|
||||||
Operands.reserve(NumImplicitOps + MCID->getNumOperands());
|
MCID->getNumImplicitDefs() + MCID->getNumImplicitUses()) {
|
||||||
|
CapOperands = OperandCapacity::get(NumOps);
|
||||||
|
Operands = MF.allocateOperandArray(CapOperands);
|
||||||
|
}
|
||||||
|
|
||||||
if (!NoImp)
|
if (!NoImp)
|
||||||
addImplicitDefUseOperands(MF);
|
addImplicitDefUseOperands(MF);
|
||||||
// Make sure that we get added to a machine basicblock
|
// Make sure that we get added to a machine basicblock
|
||||||
@@ -547,10 +551,12 @@ MachineInstr::MachineInstr(MachineFunction &MF, const MCInstrDesc &tid,
|
|||||||
/// MachineInstr ctor - Copies MachineInstr arg exactly
|
/// MachineInstr ctor - Copies MachineInstr arg exactly
|
||||||
///
|
///
|
||||||
MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI)
|
MachineInstr::MachineInstr(MachineFunction &MF, const MachineInstr &MI)
|
||||||
: MCID(&MI.getDesc()), Flags(0), AsmPrinterFlags(0),
|
: MCID(&MI.getDesc()), Parent(0), Operands(0), NumOperands(0),
|
||||||
|
Flags(0), AsmPrinterFlags(0),
|
||||||
NumMemRefs(MI.NumMemRefs), MemRefs(MI.MemRefs),
|
NumMemRefs(MI.NumMemRefs), MemRefs(MI.MemRefs),
|
||||||
Parent(0), debugLoc(MI.getDebugLoc()) {
|
debugLoc(MI.getDebugLoc()) {
|
||||||
Operands.reserve(MI.getNumOperands());
|
CapOperands = OperandCapacity::get(MI.getNumOperands());
|
||||||
|
Operands = MF.allocateOperandArray(CapOperands);
|
||||||
|
|
||||||
// Add operands
|
// Add operands
|
||||||
for (unsigned i = 0; i != MI.getNumOperands(); ++i)
|
for (unsigned i = 0; i != MI.getNumOperands(); ++i)
|
||||||
@@ -611,35 +617,52 @@ void MachineInstr::addOperand(const MachineOperand &Op) {
|
|||||||
addOperand(*MF, Op);
|
addOperand(*MF, Op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Move NumOps MachineOperands from Src to Dst, with support for overlapping
|
||||||
|
/// ranges. If MRI is non-null also update use-def chains.
|
||||||
|
static void moveOperands(MachineOperand *Dst, MachineOperand *Src,
|
||||||
|
unsigned NumOps, MachineRegisterInfo *MRI) {
|
||||||
|
if (MRI)
|
||||||
|
return MRI->moveOperands(Dst, Src, NumOps);
|
||||||
|
|
||||||
|
// Here it would be convenient to call memmove, so that isn't allowed because
|
||||||
|
// MachineOperand has a constructor and so isn't a POD type.
|
||||||
|
if (Dst < Src)
|
||||||
|
for (unsigned i = 0; i != NumOps; ++i)
|
||||||
|
new (Dst + i) MachineOperand(Src[i]);
|
||||||
|
else
|
||||||
|
for (unsigned i = NumOps; i ; --i)
|
||||||
|
new (Dst + i - 1) MachineOperand(Src[i - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
/// addOperand - Add the specified operand to the instruction. If it is an
|
/// addOperand - Add the specified operand to the instruction. If it is an
|
||||||
/// implicit operand, it is added to the end of the operand list. If it is
|
/// implicit operand, it is added to the end of the operand list. If it is
|
||||||
/// 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(MachineFunction &MF, const MachineOperand &Op) {
|
void MachineInstr::addOperand(MachineFunction &MF, const MachineOperand &Op) {
|
||||||
assert(MCID && "Cannot add operands before providing an instr descriptor");
|
assert(MCID && "Cannot add operands before providing an instr descriptor");
|
||||||
bool isImpReg = Op.isReg() && Op.isImplicit();
|
|
||||||
MachineRegisterInfo *RegInfo = getRegInfo();
|
|
||||||
|
|
||||||
// If the Operands backing store is reallocated, all register operands must
|
// Check if we're adding one of our existing operands.
|
||||||
// be removed and re-added to RegInfo. It is storing pointers to operands.
|
if (&Op >= Operands && &Op < Operands + NumOperands) {
|
||||||
bool Reallocate = RegInfo &&
|
// This is unusual: MI->addOperand(MI->getOperand(i)).
|
||||||
!Operands.empty() && getNumOperands() == Operands.capacity();
|
// If adding Op requires reallocating or moving existing operands around,
|
||||||
|
// the Op reference could go stale. Support it by copying Op.
|
||||||
|
MachineOperand CopyOp(Op);
|
||||||
|
return addOperand(MF, CopyOp);
|
||||||
|
}
|
||||||
|
|
||||||
// Find the insert location for the new operand. Implicit registers go at
|
// Find the insert location for the new operand. Implicit registers go at
|
||||||
// the end, everything goes before the implicit regs.
|
// the end, everything else goes before the implicit regs.
|
||||||
unsigned OpNo = getNumOperands();
|
//
|
||||||
|
|
||||||
// Remove all the implicit operands from RegInfo if they need to be shifted.
|
|
||||||
// FIXME: Allow mixed explicit and implicit operands on inline asm.
|
// FIXME: Allow mixed explicit and implicit operands on inline asm.
|
||||||
// InstrEmitter::EmitSpecialNode() is marking inline asm clobbers as
|
// InstrEmitter::EmitSpecialNode() is marking inline asm clobbers as
|
||||||
// implicit-defs, but they must not be moved around. See the FIXME in
|
// implicit-defs, but they must not be moved around. See the FIXME in
|
||||||
// InstrEmitter.cpp.
|
// InstrEmitter.cpp.
|
||||||
|
unsigned OpNo = getNumOperands();
|
||||||
|
bool isImpReg = Op.isReg() && Op.isImplicit();
|
||||||
if (!isImpReg && !isInlineAsm()) {
|
if (!isImpReg && !isInlineAsm()) {
|
||||||
while (OpNo && Operands[OpNo-1].isReg() && Operands[OpNo-1].isImplicit()) {
|
while (OpNo && Operands[OpNo-1].isReg() && Operands[OpNo-1].isImplicit()) {
|
||||||
--OpNo;
|
--OpNo;
|
||||||
assert(!Operands[OpNo].isTied() && "Cannot move tied operands");
|
assert(!Operands[OpNo].isTied() && "Cannot move tied operands");
|
||||||
if (RegInfo)
|
|
||||||
RegInfo->removeRegOperandFromUseList(&Operands[OpNo]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -650,55 +673,56 @@ void MachineInstr::addOperand(MachineFunction &MF, const MachineOperand &Op) {
|
|||||||
OpNo < MCID->getNumOperands()) &&
|
OpNo < MCID->getNumOperands()) &&
|
||||||
"Trying to add an operand to a machine instr that is already done!");
|
"Trying to add an operand to a machine instr that is already done!");
|
||||||
|
|
||||||
// All operands from OpNo have been removed from RegInfo. If the Operands
|
MachineRegisterInfo *MRI = getRegInfo();
|
||||||
// backing store needs to be reallocated, we also need to remove any other
|
|
||||||
// register operands.
|
|
||||||
if (Reallocate)
|
|
||||||
for (unsigned i = 0; i != OpNo; ++i)
|
|
||||||
if (Operands[i].isReg())
|
|
||||||
RegInfo->removeRegOperandFromUseList(&Operands[i]);
|
|
||||||
|
|
||||||
// Insert the new operand at OpNo.
|
// Determine if the Operands array needs to be reallocated.
|
||||||
Operands.insert(Operands.begin() + OpNo, Op);
|
// Save the old capacity and operand array.
|
||||||
Operands[OpNo].ParentMI = this;
|
OperandCapacity OldCap = CapOperands;
|
||||||
|
MachineOperand *OldOperands = Operands;
|
||||||
|
if (!OldOperands || OldCap.getSize() == getNumOperands()) {
|
||||||
|
CapOperands = OldOperands ? OldCap.getNext() : OldCap.get(1);
|
||||||
|
Operands = MF.allocateOperandArray(CapOperands);
|
||||||
|
// Move the operands before the insertion point.
|
||||||
|
if (OpNo)
|
||||||
|
moveOperands(Operands, OldOperands, OpNo, MRI);
|
||||||
|
}
|
||||||
|
|
||||||
// The Operands backing store has now been reallocated, so we can re-add the
|
// Move the operands following the insertion point.
|
||||||
// operands before OpNo.
|
if (OpNo != NumOperands)
|
||||||
if (Reallocate)
|
moveOperands(Operands + OpNo + 1, OldOperands + OpNo, NumOperands - OpNo,
|
||||||
for (unsigned i = 0; i != OpNo; ++i)
|
MRI);
|
||||||
if (Operands[i].isReg())
|
++NumOperands;
|
||||||
RegInfo->addRegOperandToUseList(&Operands[i]);
|
|
||||||
|
|
||||||
// When adding a register operand, tell RegInfo about it.
|
// Deallocate the old operand array.
|
||||||
if (Operands[OpNo].isReg()) {
|
if (OldOperands != Operands && OldOperands)
|
||||||
|
MF.deallocateOperandArray(OldCap, OldOperands);
|
||||||
|
|
||||||
|
// Copy Op into place. It still needs to be inserted into the MRI use lists.
|
||||||
|
MachineOperand *NewMO = new (Operands + OpNo) MachineOperand(Op);
|
||||||
|
NewMO->ParentMI = this;
|
||||||
|
|
||||||
|
// When adding a register operand, tell MRI about it.
|
||||||
|
if (NewMO->isReg()) {
|
||||||
// Ensure isOnRegUseList() returns false, regardless of Op's status.
|
// Ensure isOnRegUseList() returns false, regardless of Op's status.
|
||||||
Operands[OpNo].Contents.Reg.Prev = 0;
|
NewMO->Contents.Reg.Prev = 0;
|
||||||
// Ignore existing ties. This is not a property that can be copied.
|
// Ignore existing ties. This is not a property that can be copied.
|
||||||
Operands[OpNo].TiedTo = 0;
|
NewMO->TiedTo = 0;
|
||||||
// Add the new operand to RegInfo.
|
// Add the new operand to MRI, but only for instructions in an MBB.
|
||||||
if (RegInfo)
|
if (MRI)
|
||||||
RegInfo->addRegOperandToUseList(&Operands[OpNo]);
|
MRI->addRegOperandToUseList(NewMO);
|
||||||
// The MCID operand information isn't accurate until we start adding
|
// The MCID operand information isn't accurate until we start adding
|
||||||
// explicit operands. The implicit operands are added first, then the
|
// explicit operands. The implicit operands are added first, then the
|
||||||
// explicits are inserted before them.
|
// explicits are inserted before them.
|
||||||
if (!isImpReg) {
|
if (!isImpReg) {
|
||||||
// Tie uses to defs as indicated in MCInstrDesc.
|
// Tie uses to defs as indicated in MCInstrDesc.
|
||||||
if (Operands[OpNo].isUse()) {
|
if (NewMO->isUse()) {
|
||||||
int DefIdx = MCID->getOperandConstraint(OpNo, MCOI::TIED_TO);
|
int DefIdx = MCID->getOperandConstraint(OpNo, MCOI::TIED_TO);
|
||||||
if (DefIdx != -1)
|
if (DefIdx != -1)
|
||||||
tieOperands(DefIdx, OpNo);
|
tieOperands(DefIdx, OpNo);
|
||||||
}
|
}
|
||||||
// If the register operand is flagged as early, mark the operand as such.
|
// If the register operand is flagged as early, mark the operand as such.
|
||||||
if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1)
|
if (MCID->getOperandConstraint(OpNo, MCOI::EARLY_CLOBBER) != -1)
|
||||||
Operands[OpNo].setIsEarlyClobber(true);
|
NewMO->setIsEarlyClobber(true);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-add all the implicit ops.
|
|
||||||
if (RegInfo) {
|
|
||||||
for (unsigned i = OpNo + 1, e = getNumOperands(); i != e; ++i) {
|
|
||||||
assert(Operands[i].isReg() && "Should only be an implicit reg!");
|
|
||||||
RegInfo->addRegOperandToUseList(&Operands[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -709,16 +733,6 @@ void MachineInstr::addOperand(MachineFunction &MF, const MachineOperand &Op) {
|
|||||||
void MachineInstr::RemoveOperand(unsigned OpNo) {
|
void MachineInstr::RemoveOperand(unsigned OpNo) {
|
||||||
assert(OpNo < getNumOperands() && "Invalid operand number");
|
assert(OpNo < getNumOperands() && "Invalid operand number");
|
||||||
untieRegOperand(OpNo);
|
untieRegOperand(OpNo);
|
||||||
MachineRegisterInfo *RegInfo = getRegInfo();
|
|
||||||
|
|
||||||
// If we have reginfo to update, remove all operands that will be shifted
|
|
||||||
// down from their reg lists, move everything down, then re-add them.
|
|
||||||
if (RegInfo) {
|
|
||||||
for (unsigned i = OpNo, e = getNumOperands(); i != e; ++i) {
|
|
||||||
if (Operands[i].isReg())
|
|
||||||
RegInfo->removeRegOperandFromUseList(&Operands[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// Moving tied operands would break the ties.
|
// Moving tied operands would break the ties.
|
||||||
@@ -727,14 +741,17 @@ void MachineInstr::RemoveOperand(unsigned OpNo) {
|
|||||||
assert(!Operands[i].isTied() && "Cannot move tied operands");
|
assert(!Operands[i].isTied() && "Cannot move tied operands");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Operands.erase(Operands.begin()+OpNo);
|
MachineRegisterInfo *MRI = getRegInfo();
|
||||||
|
if (MRI && Operands[OpNo].isReg())
|
||||||
|
MRI->removeRegOperandFromUseList(Operands + OpNo);
|
||||||
|
|
||||||
if (RegInfo) {
|
// Don't call the MachineOperand destructor. A lot of this code depends on
|
||||||
for (unsigned i = OpNo, e = getNumOperands(); i != e; ++i) {
|
// MachineOperand having a trivial destructor anyway, and adding a call here
|
||||||
if (Operands[i].isReg())
|
// wouldn't make it 'destructor-correct'.
|
||||||
RegInfo->addRegOperandToUseList(&Operands[i]);
|
|
||||||
}
|
if (unsigned N = NumOperands - 1 - OpNo)
|
||||||
}
|
moveOperands(Operands + OpNo, Operands + OpNo + 1, N, MRI);
|
||||||
|
--NumOperands;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// addMemOperand - Add a MachineMemOperand to the machine instruction.
|
/// addMemOperand - Add a MachineMemOperand to the machine instruction.
|
||||||
|
Reference in New Issue
Block a user