From 76604af7748badc535017534f5f4c627516fdd7a Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Thu, 13 Mar 2014 06:02:25 +0000 Subject: [PATCH] Phase 1 of refactoring the MachineRegisterInfo iterators to make them suitable for use with C++11 range-based for-loops. The gist of phase 1 is to remove the skipInstruction() and skipBundle() methods from these iterators, instead splitting each iterator into a version that walks operands, a version that walks instructions, and a version that walks bundles. This has the result of making some "clever" loops in lib/CodeGen more verbose, but also makes their iterator invalidation characteristics much more obvious to the casual reader. (Making them concise again in the future is a good motivating case for a pre-incrementing range adapter!) Phase 2 of this undertaking with consist of removing the getOperand() method, and changing operator*() of the operand-walker to return a MachineOperand&. At that point, it should be possible to add range views for them that work as one might expect. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@203757 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/MachineRegisterInfo.h | 192 ++++++++++++++---- lib/CodeGen/CalcSpillWeights.cpp | 6 +- lib/CodeGen/InlineSpiller.cpp | 38 ++-- lib/CodeGen/LiveIntervalAnalysis.cpp | 14 +- lib/CodeGen/RegAllocBase.cpp | 13 +- lib/CodeGen/RegisterCoalescer.cpp | 7 +- lib/CodeGen/RegisterPressure.cpp | 6 +- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp | 7 +- 8 files changed, 207 insertions(+), 76 deletions(-) diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 58ca907316a..ecaaf0a0689 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -200,32 +200,78 @@ public: /// reg_begin/reg_end - Provide iteration support to walk over all definitions /// and uses of a register within the MachineFunction that corresponds to this /// MachineRegisterInfo object. - template + template class defusechain_iterator; // Make it a friend so it can access getNextOperandForReg(). - template friend class defusechain_iterator; + template + friend class defusechain_iterator; /// reg_iterator/reg_begin/reg_end - Walk all defs and uses of the specified /// register. - typedef defusechain_iterator reg_iterator; + typedef defusechain_iterator + reg_iterator; reg_iterator reg_begin(unsigned RegNo) const { return reg_iterator(getRegUseDefListHead(RegNo)); } static reg_iterator reg_end() { return reg_iterator(0); } + /// reg_instr_iterator/reg_instr_begin/reg_instr_end - Walk all defs and uses + /// of the specified register, stepping by MachineInstr. + typedef defusechain_iterator + reg_instr_iterator; + reg_instr_iterator reg_instr_begin(unsigned RegNo) const { + return reg_instr_iterator(getRegUseDefListHead(RegNo)); + } + static reg_instr_iterator reg_instr_end() { return reg_instr_iterator(0); } + + /// reg_bundle_iterator/reg_bundle_begin/reg_bundle_end - Walk all defs and uses + /// of the specified register, stepping by bundle. + typedef defusechain_iterator + reg_bundle_iterator; + reg_bundle_iterator reg_bundle_begin(unsigned RegNo) const { + return reg_bundle_iterator(getRegUseDefListHead(RegNo)); + } + static reg_bundle_iterator reg_bundle_end() { return reg_bundle_iterator(0); } + /// reg_empty - Return true if there are no instructions using or defining the /// specified register (it may be live-in). bool reg_empty(unsigned RegNo) const { return reg_begin(RegNo) == reg_end(); } /// reg_nodbg_iterator/reg_nodbg_begin/reg_nodbg_end - Walk all defs and uses /// of the specified register, skipping those marked as Debug. - typedef defusechain_iterator reg_nodbg_iterator; + typedef defusechain_iterator + reg_nodbg_iterator; reg_nodbg_iterator reg_nodbg_begin(unsigned RegNo) const { return reg_nodbg_iterator(getRegUseDefListHead(RegNo)); } static reg_nodbg_iterator reg_nodbg_end() { return reg_nodbg_iterator(0); } + /// reg_instr_nodbg_iterator/reg_instr_nodbg_begin/reg_instr_nodbg_end - Walk + /// all defs and uses of the specified register, stepping by MachineInstr, + /// skipping those marked as Debug. + typedef defusechain_iterator + reg_instr_nodbg_iterator; + reg_instr_nodbg_iterator reg_instr_nodbg_begin(unsigned RegNo) const { + return reg_instr_nodbg_iterator(getRegUseDefListHead(RegNo)); + } + static reg_instr_nodbg_iterator reg_instr_nodbg_end() { + return reg_instr_nodbg_iterator(0); + } + + /// reg_bundle_nodbg_iterator/reg_bundle_nodbg_begin/reg_bundle_nodbg_end - Walk + /// all defs and uses of the specified register, stepping by bundle, + /// skipping those marked as Debug. + typedef defusechain_iterator + reg_bundle_nodbg_iterator; + reg_bundle_nodbg_iterator reg_bundle_nodbg_begin(unsigned RegNo) const { + return reg_bundle_nodbg_iterator(getRegUseDefListHead(RegNo)); + } + static reg_bundle_nodbg_iterator reg_bundle_nodbg_end() { + return reg_bundle_nodbg_iterator(0); + } + /// reg_nodbg_empty - Return true if the only instructions using or defining /// Reg are Debug instructions. bool reg_nodbg_empty(unsigned RegNo) const { @@ -233,12 +279,31 @@ public: } /// def_iterator/def_begin/def_end - Walk all defs of the specified register. - typedef defusechain_iterator def_iterator; + typedef defusechain_iterator + def_iterator; def_iterator def_begin(unsigned RegNo) const { return def_iterator(getRegUseDefListHead(RegNo)); } static def_iterator def_end() { return def_iterator(0); } + /// def_instr_iterator/def_instr_begin/def_instr_end - Walk all defs of the + /// specified register, stepping by MachineInst. + typedef defusechain_iterator + def_instr_iterator; + def_instr_iterator def_instr_begin(unsigned RegNo) const { + return def_instr_iterator(getRegUseDefListHead(RegNo)); + } + static def_instr_iterator def_instr_end() { return def_instr_iterator(0); } + + /// def_bundle_iterator/def_bundle_begin/def_bundle_end - Walk all defs of the + /// specified register, stepping by bundle. + typedef defusechain_iterator + def_bundle_iterator; + def_bundle_iterator def_bundle_begin(unsigned RegNo) const { + return def_bundle_iterator(getRegUseDefListHead(RegNo)); + } + static def_bundle_iterator def_bundle_end() { return def_bundle_iterator(0); } + /// def_empty - Return true if there are no instructions defining the /// specified register (it may be live-in). bool def_empty(unsigned RegNo) const { return def_begin(RegNo) == def_end(); } @@ -253,12 +318,31 @@ public: } /// use_iterator/use_begin/use_end - Walk all uses of the specified register. - typedef defusechain_iterator use_iterator; + typedef defusechain_iterator + use_iterator; use_iterator use_begin(unsigned RegNo) const { return use_iterator(getRegUseDefListHead(RegNo)); } static use_iterator use_end() { return use_iterator(0); } + /// use_instr_iterator/use_instr_begin/use_instr_end - Walk all uses of the + /// specified register, stepping by MachineInstr. + typedef defusechain_iterator + use_instr_iterator; + use_instr_iterator use_instr_begin(unsigned RegNo) const { + return use_instr_iterator(getRegUseDefListHead(RegNo)); + } + static use_instr_iterator use_instr_end() { return use_instr_iterator(0); } + + /// use_bundle_iterator/use_bundle_begin/use_bundle_end - Walk all uses of the + /// specified register, stepping by bundle. + typedef defusechain_iterator + use_bundle_iterator; + use_bundle_iterator use_bundle_begin(unsigned RegNo) const { + return use_bundle_iterator(getRegUseDefListHead(RegNo)); + } + static use_bundle_iterator use_bundle_end() { return use_bundle_iterator(0); } + /// use_empty - Return true if there are no instructions using the specified /// register. bool use_empty(unsigned RegNo) const { return use_begin(RegNo) == use_end(); } @@ -274,12 +358,37 @@ public: /// use_nodbg_iterator/use_nodbg_begin/use_nodbg_end - Walk all uses of the /// specified register, skipping those marked as Debug. - typedef defusechain_iterator use_nodbg_iterator; + typedef defusechain_iterator + use_nodbg_iterator; use_nodbg_iterator use_nodbg_begin(unsigned RegNo) const { return use_nodbg_iterator(getRegUseDefListHead(RegNo)); } static use_nodbg_iterator use_nodbg_end() { return use_nodbg_iterator(0); } + /// use_instr_nodbg_iterator/use_instr_nodbg_begin/use_instr_nodbg_end - Walk + /// all uses of the specified register, stepping by MachineInstr, skipping + /// those marked as Debug. + typedef defusechain_iterator + use_instr_nodbg_iterator; + use_instr_nodbg_iterator use_instr_nodbg_begin(unsigned RegNo) const { + return use_instr_nodbg_iterator(getRegUseDefListHead(RegNo)); + } + static use_instr_nodbg_iterator use_instr_nodbg_end() { + return use_instr_nodbg_iterator(0); + } + + /// use_bundle_nodbg_iterator/use_bundle_nodbg_begin/use_bundle_nodbg_end - Walk + /// all uses of the specified register, stepping by bundle, skipping + /// those marked as Debug. + typedef defusechain_iterator + use_bundle_nodbg_iterator; + use_bundle_nodbg_iterator use_bundle_nodbg_begin(unsigned RegNo) const { + return use_bundle_nodbg_iterator(getRegUseDefListHead(RegNo)); + } + static use_bundle_nodbg_iterator use_bundle_nodbg_end() { + return use_bundle_nodbg_iterator(0); + } + /// use_nodbg_empty - Return true if there are no non-Debug instructions /// using the specified register. bool use_nodbg_empty(unsigned RegNo) const { @@ -552,7 +661,8 @@ public: /// returns defs. If neither are true then you are silly and it always /// returns end(). If SkipDebug is true it skips uses marked Debug /// when incrementing. - template + template class defusechain_iterator : public std::iterator { MachineOperand *Op; @@ -567,6 +677,26 @@ public: } } friend class MachineRegisterInfo; + + void advance() { + assert(Op && "Cannot increment end iterator!"); + Op = getNextOperandForReg(Op); + + // All defs come before the uses, so stop def_iterator early. + if (!ReturnUses) { + if (Op) { + if (Op->isUse()) + Op = 0; + else + assert(!Op->isDebug() && "Can't have debug defs"); + } + } else { + // If this is an operand we don't care about, skip it. + while (Op && ((!ReturnDefs && Op->isDef()) || + (SkipDebug && Op->isDebug()))) + Op = getNextOperandForReg(Op); + } + } public: typedef std::iterator::reference reference; @@ -589,21 +719,18 @@ public: // Iterator traversal: forward iteration only defusechain_iterator &operator++() { // Preincrement assert(Op && "Cannot increment end iterator!"); - Op = getNextOperandForReg(Op); - - // All defs come before the uses, so stop def_iterator early. - if (!ReturnUses) { - if (Op) { - if (Op->isUse()) - Op = 0; - else - assert(!Op->isDebug() && "Can't have debug defs"); - } - } else { - // If this is an operand we don't care about, skip it. - while (Op && ((!ReturnDefs && Op->isDef()) || - (SkipDebug && Op->isDebug()))) - Op = getNextOperandForReg(Op); + if (ByOperand) + advance(); + else if (ByInstr) { + MachineInstr *P = Op->getParent(); + do { + advance(); + } while (Op && Op->getParent() == P); + } else if (ByBundle) { + MachineInstr *P = getBundleStart(Op->getParent()); + do { + advance(); + } while (Op && getBundleStart(Op->getParent()) == P); } return *this; @@ -612,25 +739,6 @@ public: defusechain_iterator tmp = *this; ++*this; return tmp; } - /// skipInstruction - move forward until reaching a different instruction. - /// Return the skipped instruction that is no longer pointed to, or NULL if - /// already pointing to end(). - MachineInstr *skipInstruction() { - if (!Op) return 0; - MachineInstr *MI = Op->getParent(); - do ++*this; - while (Op && Op->getParent() == MI); - return MI; - } - - MachineInstr *skipBundle() { - if (!Op) return 0; - MachineInstr *MI = getBundleStart(Op->getParent()); - do ++*this; - while (Op && getBundleStart(Op->getParent()) == MI); - return MI; - } - MachineOperand &getOperand() const { assert(Op && "Cannot dereference end iterator!"); return *Op; diff --git a/lib/CodeGen/CalcSpillWeights.cpp b/lib/CodeGen/CalcSpillWeights.cpp index d9fccd03729..4833731fc17 100644 --- a/lib/CodeGen/CalcSpillWeights.cpp +++ b/lib/CodeGen/CalcSpillWeights.cpp @@ -112,8 +112,10 @@ VirtRegAuxInfo::calculateSpillWeightAndHint(LiveInterval &li) { // Don't recompute spill weight for an unspillable register. bool Spillable = li.isSpillable(); - for (MachineRegisterInfo::reg_iterator I = mri.reg_begin(li.reg); - MachineInstr *mi = I.skipInstruction();) { + for (MachineRegisterInfo::reg_instr_iterator + I = mri.reg_instr_begin(li.reg), E = mri.reg_instr_end(); + I != E; ) { + MachineInstr *mi = &*(I++); if (mi->isIdentityCopy() || mi->isImplicitDef() || mi->isDebugValue()) continue; if (!visited.insert(mi)) diff --git a/lib/CodeGen/InlineSpiller.cpp b/lib/CodeGen/InlineSpiller.cpp index bf716d877eb..64211c8d31b 100644 --- a/lib/CodeGen/InlineSpiller.cpp +++ b/lib/CodeGen/InlineSpiller.cpp @@ -238,9 +238,10 @@ bool InlineSpiller::isSnippet(const LiveInterval &SnipLI) { MachineInstr *UseMI = 0; // Check that all uses satisfy our criteria. - for (MachineRegisterInfo::reg_nodbg_iterator - RI = MRI.reg_nodbg_begin(SnipLI.reg); - MachineInstr *MI = RI.skipInstruction();) { + for (MachineRegisterInfo::reg_instr_nodbg_iterator + RI = MRI.reg_instr_nodbg_begin(SnipLI.reg), + E = MRI.reg_instr_nodbg_end(); RI != E; ) { + MachineInstr *MI = &*(RI++); // Allow copies to/from Reg. if (isFullCopyOf(MI, Reg)) @@ -277,8 +278,9 @@ void InlineSpiller::collectRegsToSpill() { if (Original == Reg) return; - for (MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(Reg); - MachineInstr *MI = RI.skipInstruction();) { + for (MachineRegisterInfo::reg_instr_iterator + RI = MRI.reg_instr_begin(Reg), E = MRI.reg_instr_end(); RI != E; ) { + MachineInstr *MI = &*(RI++); unsigned SnipReg = isFullCopyOf(MI, Reg); if (!isSibling(SnipReg)) continue; @@ -759,8 +761,10 @@ void InlineSpiller::eliminateRedundantSpills(LiveInterval &SLI, VNInfo *VNI) { DEBUG(dbgs() << "Merged to stack int: " << *StackInt << '\n'); // Find all spills and copies of VNI. - for (MachineRegisterInfo::use_nodbg_iterator UI = MRI.use_nodbg_begin(Reg); - MachineInstr *MI = UI.skipInstruction();) { + for (MachineRegisterInfo::use_instr_nodbg_iterator + UI = MRI.use_instr_nodbg_begin(Reg), E = MRI.use_instr_nodbg_end(); + UI != E; ) { + MachineInstr *MI = &*(UI++); if (!MI->isCopy() && !MI->mayStore()) continue; SlotIndex Idx = LIS.getInstructionIndex(MI); @@ -920,10 +924,12 @@ void InlineSpiller::reMaterializeAll() { for (unsigned i = 0, e = RegsToSpill.size(); i != e; ++i) { unsigned Reg = RegsToSpill[i]; LiveInterval &LI = LIS.getInterval(Reg); - for (MachineRegisterInfo::use_nodbg_iterator - RI = MRI.use_nodbg_begin(Reg); - MachineInstr *MI = RI.skipBundle();) + for (MachineRegisterInfo::use_bundle_nodbg_iterator + RI = MRI.use_bundle_nodbg_begin(Reg), E = MRI.use_bundle_nodbg_end(); + RI != E; ) { + MachineInstr *MI = &*(RI++); anyRemat |= reMaterializeFor(LI, MI); + } } if (!anyRemat) return; @@ -1187,8 +1193,10 @@ void InlineSpiller::spillAroundUses(unsigned Reg) { LiveInterval &OldLI = LIS.getInterval(Reg); // Iterate over instructions using Reg. - for (MachineRegisterInfo::reg_iterator RegI = MRI.reg_begin(Reg); - MachineInstr *MI = RegI.skipBundle();) { + for (MachineRegisterInfo::reg_bundle_iterator + RegI = MRI.reg_bundle_begin(Reg), E = MRI.reg_bundle_end(); + RegI != E; ) { + MachineInstr *MI = &*(RegI++); // Debug values are not allowed to affect codegen. if (MI->isDebugValue()) { @@ -1313,8 +1321,10 @@ void InlineSpiller::spillAll() { // Finally delete the SnippetCopies. for (unsigned i = 0, e = RegsToSpill.size(); i != e; ++i) { - for (MachineRegisterInfo::reg_iterator RI = MRI.reg_begin(RegsToSpill[i]); - MachineInstr *MI = RI.skipInstruction();) { + for (MachineRegisterInfo::reg_instr_iterator + RI = MRI.reg_instr_begin(RegsToSpill[i]), E = MRI.reg_instr_end(); + RI != E; ) { + MachineInstr *MI = &*(RI++); assert(SnippetCopies.count(MI) && "Remaining use wasn't a snippet copy"); // FIXME: Do this with a LiveRangeEdit callback. LIS.RemoveMachineInstrFromMaps(MI); diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index a5cadf4916b..fdc673f71e1 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -326,8 +326,10 @@ bool LiveIntervals::shrinkToUses(LiveInterval *li, SmallPtrSet LiveOut; // Visit all instructions reading li->reg. - for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(li->reg); - MachineInstr *UseMI = I.skipInstruction();) { + for (MachineRegisterInfo::reg_instr_iterator + I = MRI->reg_instr_begin(li->reg), E = MRI->reg_instr_end(); + I != E; ) { + MachineInstr *UseMI = &*(I++); if (UseMI->isDebugValue() || !UseMI->readsVirtualRegister(li->reg)) continue; SlotIndex Idx = getInstructionIndex(UseMI).getRegSlot(); @@ -980,10 +982,10 @@ private: if (TargetRegisterInfo::isVirtualRegister(Reg)) { SlotIndex LastUse = NewIdx; - for (MachineRegisterInfo::use_nodbg_iterator - UI = MRI.use_nodbg_begin(Reg), - UE = MRI.use_nodbg_end(); - UI != UE; UI.skipInstruction()) { + for (MachineRegisterInfo::use_instr_nodbg_iterator + UI = MRI.use_instr_nodbg_begin(Reg), + UE = MRI.use_instr_nodbg_end(); + UI != UE; ++UI) { const MachineInstr* MI = &*UI; SlotIndex InstSlot = LIS.getSlotIndexes()->getInstructionIndex(MI); if (InstSlot > LastUse && InstSlot < OldIdx) diff --git a/lib/CodeGen/RegAllocBase.cpp b/lib/CodeGen/RegAllocBase.cpp index 48aadc2a5f3..33584f86806 100644 --- a/lib/CodeGen/RegAllocBase.cpp +++ b/lib/CodeGen/RegAllocBase.cpp @@ -110,11 +110,16 @@ void RegAllocBase::allocatePhysRegs() { if (AvailablePhysReg == ~0u) { // selectOrSplit failed to find a register! // Probably caused by an inline asm. - MachineInstr *MI; - for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(VirtReg->reg); - (MI = I.skipInstruction());) - if (MI->isInlineAsm()) + MachineInstr *MI = 0; + for (MachineRegisterInfo::reg_instr_iterator + I = MRI->reg_instr_begin(VirtReg->reg), E = MRI->reg_instr_end(); + I != E; ) { + MachineInstr *TmpMI = &*(I++); + if (TmpMI->isInlineAsm()) { + MI = TmpMI; break; + } + } if (MI) MI->emitError("inline assembly requires more registers than available"); else diff --git a/lib/CodeGen/RegisterCoalescer.cpp b/lib/CodeGen/RegisterCoalescer.cpp index 64e6da51e49..13ea1a58e04 100644 --- a/lib/CodeGen/RegisterCoalescer.cpp +++ b/lib/CodeGen/RegisterCoalescer.cpp @@ -939,8 +939,11 @@ void RegisterCoalescer::updateRegDefsUses(unsigned SrcReg, LiveInterval *DstInt = DstIsPhys ? 0 : &LIS->getInterval(DstReg); SmallPtrSet Visited; - for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(SrcReg); - MachineInstr *UseMI = I.skipInstruction();) { + for (MachineRegisterInfo::reg_instr_iterator + I = MRI->reg_instr_begin(SrcReg), E = MRI->reg_instr_end(); + I != E; ) { + MachineInstr *UseMI = &*(I++); + // Each instruction can only be rewritten once because sub-register // composition is not always idempotent. When SrcReg != DstReg, rewriting // the UseMI operands removes them from the SrcReg use-def chain, but when diff --git a/lib/CodeGen/RegisterPressure.cpp b/lib/CodeGen/RegisterPressure.cpp index cfeafbf4030..97817daac52 100644 --- a/lib/CodeGen/RegisterPressure.cpp +++ b/lib/CodeGen/RegisterPressure.cpp @@ -882,9 +882,9 @@ static bool findUseBetween(unsigned Reg, SlotIndex PriorUseIdx, SlotIndex NextUseIdx, const MachineRegisterInfo *MRI, const LiveIntervals *LIS) { - for (MachineRegisterInfo::use_nodbg_iterator - UI = MRI->use_nodbg_begin(Reg), UE = MRI->use_nodbg_end(); - UI != UE; UI.skipInstruction()) { + for (MachineRegisterInfo::use_instr_nodbg_iterator + UI = MRI->use_instr_nodbg_begin(Reg), + UE = MRI->use_instr_nodbg_end(); UI != UE; ++UI) { const MachineInstr* MI = &*UI; if (MI->isDebugValue()) continue; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index cda0b57a159..5d0e2b937df 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -483,9 +483,10 @@ bool SelectionDAGISel::runOnMachineFunction(MachineFunction &mf) { // that COPY instructions also need DBG_VALUE, if it is the only // user of LDI->second. MachineInstr *CopyUseMI = NULL; - for (MachineRegisterInfo::use_iterator - UI = RegInfo->use_begin(LDI->second); - MachineInstr *UseMI = UI.skipInstruction();) { + for (MachineRegisterInfo::use_instr_iterator + UI = RegInfo->use_instr_begin(LDI->second), + E = RegInfo->use_instr_end(); UI != E; ) { + MachineInstr *UseMI = &*(UI++); if (UseMI->isDebugValue()) continue; if (UseMI->isCopy() && !CopyUseMI && UseMI->getParent() == EntryMBB) { CopyUseMI = UseMI; continue;