diff options
author | Chris Lattner <sabre@nondot.org> | 2008-01-01 01:12:31 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2008-01-01 01:12:31 +0000 |
commit | 62ed6b9ade63bf01717ce5274fa11e93e873d245 (patch) | |
tree | 9068503f260d6d167ced6218ee4d53599e1ff70a /lib/CodeGen | |
parent | 264e6fec9f3962cb269031d6d84cee9f896e0286 (diff) |
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
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/MachineBasicBlock.cpp | 59 | ||||
-rw-r--r-- | lib/CodeGen/MachineInstr.cpp | 252 | ||||
-rw-r--r-- | lib/CodeGen/MachineRegisterInfo.cpp | 28 |
3 files changed, 331 insertions, 8 deletions
diff --git a/lib/CodeGen/MachineBasicBlock.cpp b/lib/CodeGen/MachineBasicBlock.cpp index 3b84d688b8..7f93185375 100644 --- a/lib/CodeGen/MachineBasicBlock.cpp +++ b/lib/CodeGen/MachineBasicBlock.cpp @@ -31,13 +31,23 @@ std::ostream& llvm::operator<<(std::ostream &OS, const MachineBasicBlock &MBB) { return OS; } -// MBBs start out as #-1. When a MBB is added to a MachineFunction, it -// gets the next available unique MBB number. If it is removed from a -// MachineFunction, it goes back to being #-1. +/// addNodeToList (MBB) - When an MBB is added to an MF, we need to update the +/// parent pointer of the MBB, the MBB numbering, and any instructions in the +/// MBB to be on the right operand list for registers. +/// +/// MBBs start out as #-1. When a MBB is added to a MachineFunction, it +/// gets the next available unique MBB number. If it is removed from a +/// MachineFunction, it goes back to being #-1. void ilist_traits<MachineBasicBlock>::addNodeToList(MachineBasicBlock* N) { assert(N->getParent() == 0 && "machine instruction already in a basic block"); N->setParent(Parent); N->Number = Parent->addToMBBNumbering(N); + + // Make sure the instructions have their operands in the reginfo lists. + MachineRegisterInfo &RegInfo = Parent->getRegInfo(); + for (MachineBasicBlock::iterator I = N->begin(), E = N->end(); I != E; ++I) + I->AddRegOperandsToUseLists(RegInfo); + LeakDetector::removeGarbageObject(N); } @@ -46,6 +56,12 @@ void ilist_traits<MachineBasicBlock>::removeNodeFromList(MachineBasicBlock* N) { N->getParent()->removeFromMBBNumbering(N->Number); N->Number = -1; N->setParent(0); + + // Make sure the instructions have their operands removed from the reginfo + // lists. + for (MachineBasicBlock::iterator I = N->begin(), E = N->end(); I != E; ++I) + I->RemoveRegOperandsFromUseLists(); + LeakDetector::addGarbageObject(N); } @@ -56,27 +72,62 @@ MachineInstr* ilist_traits<MachineInstr>::createSentinel() { return dummy; } +/// addNodeToList (MI) - When we add an instruction to a basic block +/// list, we update its parent pointer and add its operands from reg use/def +/// lists if appropriate. void ilist_traits<MachineInstr>::addNodeToList(MachineInstr* N) { assert(N->getParent() == 0 && "machine instruction already in a basic block"); N->setParent(parent); LeakDetector::removeGarbageObject(N); + + // If the block is in a function, add the instruction's register operands to + // their corresponding use/def lists. + if (MachineFunction *MF = parent->getParent()) + N->AddRegOperandsToUseLists(MF->getRegInfo()); } +/// removeNodeFromList (MI) - When we remove an instruction from a basic block +/// list, we update its parent pointer and remove its operands from reg use/def +/// lists if appropriate. void ilist_traits<MachineInstr>::removeNodeFromList(MachineInstr* N) { assert(N->getParent() != 0 && "machine instruction not in a basic block"); + // If this block is in a function, remove from the use/def lists. + if (parent->getParent() != 0) + N->RemoveRegOperandsFromUseLists(); + N->setParent(0); LeakDetector::addGarbageObject(N); } +/// transferNodesFromList (MI) - When moving a range of instructions from one +/// MBB list to another, we need to update the parent pointers and the use/def +/// lists. void ilist_traits<MachineInstr>::transferNodesFromList( iplist<MachineInstr, ilist_traits<MachineInstr> >& fromList, ilist_iterator<MachineInstr> first, ilist_iterator<MachineInstr> last) { // Splice within the same MBB -> no change. if (parent == fromList.parent) return; + + // If splicing between two blocks within the same function, just update the + // parent pointers. + if (parent->getParent() == fromList.parent->getParent()) { + for (; first != last; ++first) + first->setParent(parent); + return; + } - for (; first != last; ++first) + // Otherwise, we have to update the parent and the use/def lists. The common + // case when this occurs is if we're splicing from a block in a MF to a block + // that is not in an MF. + bool HasOldMF = fromList.parent->getParent() != 0; + MachineFunction *NewMF = parent->getParent(); + + for (; first != last; ++first) { + if (HasOldMF) first->RemoveRegOperandsFromUseLists(); first->setParent(parent); + if (NewMF) first->AddRegOperandsToUseLists(NewMF->getRegInfo()); + } } MachineBasicBlock::iterator MachineBasicBlock::getFirstTerminator() { diff --git a/lib/CodeGen/MachineInstr.cpp b/lib/CodeGen/MachineInstr.cpp index 4d0a98a114..43cc66d237 100644 --- a/lib/CodeGen/MachineInstr.cpp +++ b/lib/CodeGen/MachineInstr.cpp @@ -14,6 +14,7 @@ #include "llvm/CodeGen/MachineInstr.h" #include "llvm/Value.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/MRegisterInfo.h" @@ -26,6 +27,96 @@ using namespace llvm; // MachineOperand Implementation //===----------------------------------------------------------------------===// +/// AddRegOperandToRegInfo - Add this register operand to the specified +/// MachineRegisterInfo. If it is null, then the next/prev fields should be +/// explicitly nulled out. +void MachineOperand::AddRegOperandToRegInfo(MachineRegisterInfo *RegInfo) { + assert(isReg() && "Can only add reg operand to use lists"); + + // If the reginfo pointer is null, just explicitly null out or next/prev + // pointers, to ensure they are not garbage. + if (RegInfo == 0) { + Contents.Reg.Prev = 0; + Contents.Reg.Next = 0; + return; + } + + // Otherwise, add this operand to the head of the registers use/def list. + MachineOperand *&Head = RegInfo->getRegUseDefListHead(getReg()); + + Contents.Reg.Next = Head; + if (Contents.Reg.Next) { + assert(getReg() == Contents.Reg.Next->getReg() && + "Different regs on the same list!"); + Contents.Reg.Next->Contents.Reg.Prev = &Contents.Reg.Next; + } + + Contents.Reg.Prev = &Head; + Head = this; +} + +void MachineOperand::setReg(unsigned Reg) { + if (getReg() == Reg) return; // No change. + + // Otherwise, we have to change the register. If this operand is embedded + // into a machine function, we need to update the old and new register's + // use/def lists. + if (MachineInstr *MI = getParent()) + if (MachineBasicBlock *MBB = MI->getParent()) + if (MachineFunction *MF = MBB->getParent()) { + RemoveRegOperandFromRegInfo(); + Contents.Reg.RegNo = Reg; + AddRegOperandToRegInfo(&MF->getRegInfo()); + return; + } + + // Otherwise, just change the register, no problem. :) + Contents.Reg.RegNo = Reg; +} + +/// 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 MachineOperand::ChangeToImmediate(int64_t ImmVal) { + // If this operand is currently a register operand, and if this is in a + // function, deregister the operand from the register's use/def list. + if (isReg() && getParent() && getParent()->getParent() && + getParent()->getParent()->getParent()) + RemoveRegOperandFromRegInfo(); + + OpKind = MO_Immediate; + Contents.ImmVal = 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 MachineOperand::ChangeToRegister(unsigned Reg, bool isDef, bool isImp, + bool isKill, bool isDead) { + // If this operand is already a register operand, use setReg to update the + // register's use/def lists. + if (isReg()) { + setReg(Reg); + } else { + // Otherwise, change this to a register and set the reg#. + OpKind = MO_Register; + Contents.Reg.RegNo = Reg; + + // If this operand is embedded in a function, add the operand to the + // register's use/def list. + if (MachineInstr *MI = getParent()) + if (MachineBasicBlock *MBB = MI->getParent()) + if (MachineFunction *MF = MBB->getParent()) + AddRegOperandToRegInfo(&MF->getRegInfo()); + } + + IsDef = isDef; + IsImp = isImp; + IsKill = isKill; + IsDead = isDead; + SubReg = 0; +} + /// isIdenticalTo - Return true if this operand is identical to the specified /// operand. bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const { @@ -63,8 +154,7 @@ void MachineOperand::print(std::ostream &OS, const TargetMachine *TM) const { OS << "%reg" << getReg(); } else { // If the instruction is embedded into a basic block, we can find the - // target - // info for the instruction. + // target info for the instruction. if (TM == 0) if (const MachineInstr *MI = getParent()) if (const MachineBasicBlock *MBB = MI->getParent()) @@ -212,8 +302,11 @@ MachineInstr::MachineInstr(const MachineInstr &MI) { MachineInstr::~MachineInstr() { LeakDetector::removeGarbageObject(this); #ifndef NDEBUG - for (unsigned i = 0, e = Operands.size(); i != e; ++i) + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { assert(Operands[i].ParentMI == this && "ParentMI mismatch!"); + assert((!Operands[i].isReg() || !Operands[i].isOnRegUseList()) && + "Reg operand def/use list corrupted"); + } #endif } @@ -223,6 +316,159 @@ int MachineInstr::getOpcode() const { return TID->Opcode; } +/// getRegInfo - If this instruction is embedded into a MachineFunction, +/// return the MachineRegisterInfo object for the current function, otherwise +/// return null. +MachineRegisterInfo *MachineInstr::getRegInfo() { + if (MachineBasicBlock *MBB = getParent()) + if (MachineFunction *MF = MBB->getParent()) + return &MF->getRegInfo(); + return 0; +} + +/// 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 MachineInstr::RemoveRegOperandsFromUseLists() { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + if (Operands[i].isReg()) + Operands[i].RemoveRegOperandFromRegInfo(); + } +} + +/// 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 MachineInstr::AddRegOperandsToUseLists(MachineRegisterInfo &RegInfo) { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) { + if (Operands[i].isReg()) + Operands[i].AddRegOperandToRegInfo(&RegInfo); + } +} + + +/// 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 MachineInstr::addOperand(const MachineOperand &Op) { + bool isImpReg = Op.isReg() && Op.isImplicit(); + assert((isImpReg || !OperandsComplete()) && + "Trying to add an operand to a machine instr that is already done!"); + + // If we are adding the operand to the end of the list, our job is simpler. + // This is true most of the time, so this is a reasonable optimization. + if (isImpReg || NumImplicitOps == 0) { + // We can only do this optimization if we know that the operand list won't + // reallocate. + if (Operands.empty() || Operands.size()+1 <= Operands.capacity()) { + Operands.push_back(Op); + + // Set the parent of the operand. + Operands.back().ParentMI = this; + + // If the operand is a register, update the operand's use list. + if (Op.isReg()) + Operands.back().AddRegOperandToRegInfo(getRegInfo()); + return; + } + } + + // Otherwise, we have to insert a real operand before any implicit ones. + unsigned OpNo = Operands.size()-NumImplicitOps; + + MachineRegisterInfo *RegInfo = getRegInfo(); + + // If this instruction isn't embedded into a function, then we don't need to + // update any operand lists. + if (RegInfo == 0) { + // Simple insertion, no reginfo update needed for other register operands. + Operands.insert(Operands.begin()+OpNo, Op); + Operands[OpNo].ParentMI = this; + + // Do explicitly set the reginfo for this operand though, to ensure the + // next/prev fields are properly nulled out. + if (Operands[OpNo].isReg()) + Operands[OpNo].AddRegOperandToRegInfo(0); + + } else if (Operands.size()+1 <= Operands.capacity()) { + // Otherwise, we have to remove register operands from their register use + // list, add the operand, then add the register operands back to their use + // list. This also must handle the case when the operand list reallocates + // to somewhere else. + + // If insertion of this operand won't cause reallocation of the operand + // list, just remove the implicit operands, add the operand, then re-add all + // the rest of the operands. + for (unsigned i = OpNo, e = Operands.size(); i != e; ++i) { + assert(Operands[i].isReg() && "Should only be an implicit reg!"); + Operands[i].RemoveRegOperandFromRegInfo(); + } + + // Add the operand. If it is a register, add it to the reg list. + Operands.insert(Operands.begin()+OpNo, Op); + Operands[OpNo].ParentMI = this; + + if (Operands[OpNo].isReg()) + Operands[OpNo].AddRegOperandToRegInfo(RegInfo); + + // 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!"); + 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); + } +} + +/// RemoveOperand - Erase an operand from an instruction, leaving it with one +/// fewer operand than it started with. +/// +void MachineInstr::RemoveOperand(unsigned OpNo) { + assert(OpNo < Operands.size() && "Invalid operand number"); + + // Special case removing the last one. + if (OpNo == Operands.size()-1) { + // If needed, remove from the reg def/use list. + if (Operands.back().isReg() && Operands.back().isOnRegUseList()) + Operands.back().RemoveRegOperandFromRegInfo(); + + Operands.pop_back(); + return; + } + + // Otherwise, we are removing an interior operand. 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. + MachineRegisterInfo *RegInfo = getRegInfo(); + if (RegInfo) { + for (unsigned i = OpNo, e = Operands.size(); i != e; ++i) { + if (Operands[i].isReg()) + Operands[i].RemoveRegOperandFromRegInfo(); + } + } + + Operands.erase(Operands.begin()+OpNo); + + if (RegInfo) { + for (unsigned i = OpNo, e = Operands.size(); i != e; ++i) { + if (Operands[i].isReg()) + Operands[i].AddRegOperandToRegInfo(RegInfo); + } + } +} + + /// removeFromParent - This method unlinks 'this' from the containing basic /// block, and returns it, but does not delete it. MachineInstr *MachineInstr::removeFromParent() { diff --git a/lib/CodeGen/MachineRegisterInfo.cpp b/lib/CodeGen/MachineRegisterInfo.cpp index 19c09eee51..f217c042be 100644 --- a/lib/CodeGen/MachineRegisterInfo.cpp +++ b/lib/CodeGen/MachineRegisterInfo.cpp @@ -1,4 +1,4 @@ -//===-- MachineRegisterInfo.cpp -------------------------------------------===// +//===-- lib/Codegen/MachineRegisterInfo.cpp -------------------------------===// // // The LLVM Compiler Infrastructure // @@ -17,4 +17,30 @@ using namespace llvm; MachineRegisterInfo::MachineRegisterInfo(const MRegisterInfo &MRI) { VRegInfo.reserve(256); UsedPhysRegs.resize(MRI.getNumRegs()); + + // Create the physreg use/def lists. + PhysRegUseDefLists = new MachineOperand*[MRI.getNumRegs()]; + memset(PhysRegUseDefLists, 0, sizeof(MachineOperand*)*MRI.getNumRegs()); +} + +MachineRegisterInfo::~MachineRegisterInfo() { +#ifndef NDEBUG + for (unsigned i = 0, e = VRegInfo.size(); i != e; ++i) + assert(VRegInfo[i].second == 0 && "Vreg use list non-empty still?"); +#endif + delete [] PhysRegUseDefLists; +} + +/// HandleVRegListReallocation - We just added a virtual register to the +/// VRegInfo info list and it reallocated. Update the use/def lists info +/// pointers. +void MachineRegisterInfo::HandleVRegListReallocation() { + // The back pointers for the vreg lists point into the previous vector. + // Update them to point to their correct slots. + for (unsigned i = 0, e = VRegInfo.size(); i != e; ++i) { + MachineOperand *List = VRegInfo[i].second; + if (!List) continue; + // Update the back-pointer to be accurate once more. + List->Contents.Reg.Prev = &VRegInfo[i].second; + } } |