mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-01 12:24:24 +00:00
Implement automatically updated def/use lists for all MachineInstr register
operands. The lists are currently kept in MachineRegisterInfo, but it does not yet provide an iterator interface to them. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45477 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -45,6 +45,7 @@ class MachineInstr {
|
||||
|
||||
// Intrusive list support
|
||||
friend struct ilist_traits<MachineInstr>;
|
||||
friend struct ilist_traits<MachineBasicBlock>;
|
||||
void setParent(MachineBasicBlock *P) { Parent = P; }
|
||||
public:
|
||||
/// MachineInstr ctor - This constructor creates a dummy MachineInstr with
|
||||
@ -154,27 +155,14 @@ public:
|
||||
void dump() const;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Accessors to add operands when building up machine instructions.
|
||||
//
|
||||
void addOperand(const MachineOperand &Op) {
|
||||
bool isImpReg = Op.isRegister() && Op.isImplicit();
|
||||
assert((isImpReg || !OperandsComplete()) &&
|
||||
"Trying to add an operand to a machine instr that is already done!");
|
||||
if (isImpReg || NumImplicitOps == 0) {// This is true most of the time.
|
||||
Operands.push_back(Op);
|
||||
Operands.back().ParentMI = this;
|
||||
} else {
|
||||
// Insert a real operand before any implicit ones.
|
||||
unsigned OpNo = Operands.size()-NumImplicitOps;
|
||||
Operands.insert(Operands.begin()+OpNo, Op);
|
||||
Operands[OpNo].ParentMI = this;
|
||||
}
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Accessors used to modify instructions in place.
|
||||
//
|
||||
// Accessors used to build up machine instructions.
|
||||
|
||||
/// 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
|
||||
/// an explicit operand it is added at the end of the explicit operand list
|
||||
/// (before the first implicit operand).
|
||||
void addOperand(const MachineOperand &Op);
|
||||
|
||||
/// setInstrDescriptor - Replace the instruction descriptor (thus opcode) of
|
||||
/// the current instruction with a new one.
|
||||
///
|
||||
@ -183,14 +171,27 @@ public:
|
||||
/// RemoveOperand - Erase an operand from an instruction, leaving it with one
|
||||
/// fewer operand than it started with.
|
||||
///
|
||||
void RemoveOperand(unsigned i) {
|
||||
Operands.erase(Operands.begin()+i);
|
||||
}
|
||||
void RemoveOperand(unsigned i);
|
||||
|
||||
private:
|
||||
/// getRegInfo - If this instruction is embedded into a MachineFunction,
|
||||
/// return the MachineRegisterInfo object for the current function, otherwise
|
||||
/// return null.
|
||||
MachineRegisterInfo *getRegInfo();
|
||||
|
||||
/// addImplicitDefUseOperands - Add all implicit def and use operands to
|
||||
/// this instruction.
|
||||
void addImplicitDefUseOperands();
|
||||
|
||||
/// RemoveRegOperandsFromUseLists - Unlink all of the register operands in
|
||||
/// this instruction from their respective use lists. This requires that the
|
||||
/// operands already be on their use lists.
|
||||
void RemoveRegOperandsFromUseLists();
|
||||
|
||||
/// AddRegOperandsToUseLists - Add all of the register operands in
|
||||
/// this instruction from their respective use lists. This requires that the
|
||||
/// operands not be on their use lists yet.
|
||||
void AddRegOperandsToUseLists(MachineRegisterInfo &RegInfo);
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -25,6 +25,7 @@ class MachineBasicBlock;
|
||||
class GlobalValue;
|
||||
class MachineInstr;
|
||||
class TargetMachine;
|
||||
class MachineRegisterInfo;
|
||||
|
||||
/// MachineOperand class - Representation of each machine instruction operand.
|
||||
///
|
||||
@ -76,8 +77,13 @@ private:
|
||||
/// Contents union - This contains the payload for the various operand types.
|
||||
union {
|
||||
MachineBasicBlock *MBB; // For MO_MachineBasicBlock.
|
||||
unsigned RegNo; // For MO_Register.
|
||||
int64_t ImmVal; // For MO_Immediate.
|
||||
|
||||
struct { // For MO_Register.
|
||||
unsigned RegNo;
|
||||
MachineOperand **Prev; // Access list for register.
|
||||
MachineOperand *Next;
|
||||
} Reg;
|
||||
|
||||
/// OffsetedInfo - This struct contains the offset and an object identifier.
|
||||
/// this represent the object as with an optional offset from it.
|
||||
@ -92,7 +98,6 @@ private:
|
||||
} Contents;
|
||||
|
||||
MachineOperand(MachineOperandType K) : OpKind(K), ParentMI(0) {}
|
||||
|
||||
public:
|
||||
MachineOperand(const MachineOperand &M) {
|
||||
*this = M;
|
||||
@ -138,7 +143,7 @@ public:
|
||||
/// getReg - Returns the register number.
|
||||
unsigned getReg() const {
|
||||
assert(isRegister() && "This is not a register operand!");
|
||||
return Contents.RegNo;
|
||||
return Contents.Reg.RegNo;
|
||||
}
|
||||
|
||||
unsigned getSubReg() const {
|
||||
@ -175,11 +180,10 @@ public:
|
||||
// Mutators for Register Operands
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
void setReg(unsigned Reg) {
|
||||
assert(isRegister() && "This is not a register operand!");
|
||||
Contents.RegNo = Reg;
|
||||
}
|
||||
|
||||
/// Change the register this operand corresponds to.
|
||||
///
|
||||
void setReg(unsigned Reg);
|
||||
|
||||
void setSubReg(unsigned subReg) {
|
||||
assert(isRegister() && "Wrong MachineOperand accessor");
|
||||
SubReg = (unsigned char)subReg;
|
||||
@ -284,24 +288,13 @@ public:
|
||||
/// ChangeToImmediate - Replace this operand with a new immediate operand of
|
||||
/// the specified value. If an operand is known to be an immediate already,
|
||||
/// the setImm method should be used.
|
||||
void ChangeToImmediate(int64_t ImmVal) {
|
||||
OpKind = MO_Immediate;
|
||||
Contents.ImmVal = ImmVal;
|
||||
}
|
||||
|
||||
void ChangeToImmediate(int64_t ImmVal);
|
||||
|
||||
/// ChangeToRegister - Replace this operand with a new register operand of
|
||||
/// the specified value. If an operand is known to be an register already,
|
||||
/// the setReg method should be used.
|
||||
void ChangeToRegister(unsigned Reg, bool isDef, bool isImp = false,
|
||||
bool isKill = false, bool isDead = false) {
|
||||
OpKind = MO_Register;
|
||||
Contents.RegNo = Reg;
|
||||
IsDef = isDef;
|
||||
IsImp = isImp;
|
||||
IsKill = isKill;
|
||||
IsDead = isDead;
|
||||
SubReg = 0;
|
||||
}
|
||||
bool isKill = false, bool isDead = false);
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Construction methods.
|
||||
@ -321,7 +314,9 @@ public:
|
||||
Op.IsImp = isImp;
|
||||
Op.IsKill = isKill;
|
||||
Op.IsDead = isDead;
|
||||
Op.Contents.RegNo = Reg;
|
||||
Op.Contents.Reg.RegNo = Reg;
|
||||
Op.Contents.Reg.Prev = 0;
|
||||
Op.Contents.Reg.Next = 0;
|
||||
Op.SubReg = SubReg;
|
||||
return Op;
|
||||
}
|
||||
@ -371,6 +366,37 @@ public:
|
||||
}
|
||||
|
||||
friend class MachineInstr;
|
||||
friend class MachineRegisterInfo;
|
||||
private:
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Methods for handling register use/def lists.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
||||
/// isOnRegUseList - Return true if this operand is on a register use/def list
|
||||
/// or false if not. This can only be called for register operands that are
|
||||
/// part of a machine instruction.
|
||||
bool isOnRegUseList() const {
|
||||
assert(isReg() && "Can only add reg operand to use lists");
|
||||
return Contents.Reg.Prev != 0;
|
||||
}
|
||||
|
||||
/// AddRegOperandToRegInfo - Add this register operand to the specified
|
||||
/// MachineRegisterInfo. If it is null, then the next/prev fields should be
|
||||
/// explicitly nulled out.
|
||||
void AddRegOperandToRegInfo(MachineRegisterInfo *RegInfo);
|
||||
|
||||
void RemoveRegOperandFromRegInfo() {
|
||||
assert(isOnRegUseList() && "Can only add reg operand to use lists");
|
||||
// Unlink this from the doubly linked list of operands.
|
||||
MachineOperand *NextOp = Contents.Reg.Next;
|
||||
*Contents.Reg.Prev = NextOp;
|
||||
if (NextOp) {
|
||||
assert(NextOp->getReg() == getReg() && "Corrupt reg use/def chain!");
|
||||
NextOp->Contents.Reg.Prev = Contents.Reg.Prev;
|
||||
}
|
||||
Contents.Reg.Prev = 0;
|
||||
Contents.Reg.Next = 0;
|
||||
}
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &OS, const MachineOperand &MO) {
|
||||
|
@ -26,7 +26,14 @@ class MachineRegisterInfo {
|
||||
/// VRegInfo - Information we keep for each virtual register. The entries in
|
||||
/// this vector are actually converted to vreg numbers by adding the
|
||||
/// MRegisterInfo::FirstVirtualRegister delta to their index.
|
||||
std::vector<const TargetRegisterClass*> VRegInfo;
|
||||
///
|
||||
/// Each element in this list contains the register class of the vreg and the
|
||||
/// start of the use/def list for the register.
|
||||
std::vector<std::pair<const TargetRegisterClass*, MachineOperand*> > VRegInfo;
|
||||
|
||||
/// PhysRegUseDefLists - This is an array of the head of the use/def list for
|
||||
/// physical registers.
|
||||
MachineOperand **PhysRegUseDefLists;
|
||||
|
||||
/// UsedPhysRegs - This is a bit vector that is computed and set by the
|
||||
/// register allocator, and must be kept up to date by passes that run after
|
||||
@ -42,8 +49,21 @@ class MachineRegisterInfo {
|
||||
/// stored in the second element.
|
||||
std::vector<std::pair<unsigned, unsigned> > LiveIns;
|
||||
std::vector<unsigned> LiveOuts;
|
||||
|
||||
MachineRegisterInfo(const MachineRegisterInfo&); // DO NOT IMPLEMENT
|
||||
void operator=(const MachineRegisterInfo&); // DO NOT IMPLEMENT
|
||||
public:
|
||||
MachineRegisterInfo(const MRegisterInfo &MRI);
|
||||
~MachineRegisterInfo();
|
||||
|
||||
/// getRegUseDefListHead - Return the head pointer for the register use/def
|
||||
/// list for the specified virtual or physical register.
|
||||
MachineOperand *&getRegUseDefListHead(unsigned RegNo) {
|
||||
if (RegNo < MRegisterInfo::FirstVirtualRegister)
|
||||
return PhysRegUseDefLists[RegNo];
|
||||
RegNo -= MRegisterInfo::FirstVirtualRegister;
|
||||
return VRegInfo[RegNo].second;
|
||||
}
|
||||
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -54,15 +74,23 @@ public:
|
||||
const TargetRegisterClass *getRegClass(unsigned Reg) {
|
||||
Reg -= MRegisterInfo::FirstVirtualRegister;
|
||||
assert(Reg < VRegInfo.size() && "Invalid vreg!");
|
||||
return VRegInfo[Reg];
|
||||
return VRegInfo[Reg].first;
|
||||
}
|
||||
|
||||
|
||||
/// createVirtualRegister - Create and return a new virtual register in the
|
||||
/// function with the specified register class.
|
||||
///
|
||||
unsigned createVirtualRegister(const TargetRegisterClass *RegClass) {
|
||||
assert(RegClass && "Cannot create register without RegClass!");
|
||||
VRegInfo.push_back(RegClass);
|
||||
// Add a reg, but keep track of whether the vector reallocated or not.
|
||||
void *ArrayBase = &VRegInfo[0];
|
||||
VRegInfo.push_back(std::make_pair(RegClass, (MachineOperand*)0));
|
||||
|
||||
if (&VRegInfo[0] == ArrayBase)
|
||||
return getLastVirtReg();
|
||||
|
||||
// Otherwise, the vector reallocated, handle this now.
|
||||
HandleVRegListReallocation();
|
||||
return getLastVirtReg();
|
||||
}
|
||||
|
||||
@ -111,6 +139,8 @@ public:
|
||||
liveout_iterator liveout_begin() const { return LiveOuts.begin(); }
|
||||
liveout_iterator liveout_end() const { return LiveOuts.end(); }
|
||||
bool liveout_empty() const { return LiveOuts.empty(); }
|
||||
private:
|
||||
void HandleVRegListReallocation();
|
||||
};
|
||||
|
||||
} // End llvm namespace
|
||||
|
Reference in New Issue
Block a user