From f41538d1b54f55e8900394929b50f7ce3e61125f Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Tue, 2 Jun 2009 16:53:25 +0000 Subject: [PATCH] Update to in-place spilling framework. Includes live interval scaling and trivial rewriter. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@72729 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/LiveInterval.h | 24 +++ include/llvm/CodeGen/LiveIntervalAnalysis.h | 23 ++- include/llvm/CodeGen/LiveStackAnalysis.h | 2 + lib/CodeGen/LiveInterval.cpp | 23 +++ lib/CodeGen/LiveIntervalAnalysis.cpp | 44 +++++ lib/CodeGen/LiveStackAnalysis.cpp | 9 + lib/CodeGen/RegAllocLinearScan.cpp | 141 +++++++++++++- lib/CodeGen/SimpleRegisterCoalescing.cpp | 2 +- lib/CodeGen/SimpleRegisterCoalescing.h | 2 +- lib/CodeGen/Spiller.cpp | 197 +++++++++++--------- lib/CodeGen/Spiller.h | 5 +- lib/CodeGen/StrongPHIElimination.cpp | 2 +- lib/CodeGen/VirtRegRewriter.cpp | 45 ++++- 13 files changed, 405 insertions(+), 114 deletions(-) diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index d6f5c8484e4..f1ae587ac19 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -113,6 +113,26 @@ namespace llvm { VNInfoList valnos; // value#'s public: + + struct InstrSlots { + enum { + LOAD = 0, + USE = 1, + DEF = 2, + STORE = 3, + NUM = 4 + }; + + static unsigned scale(unsigned slot, unsigned factor) { + unsigned index = slot / NUM, + offset = slot % NUM; + assert(index <= ~0U / (factor * NUM) && + "Rescaled interval would overflow"); + return index * NUM * factor + offset; + } + + }; + LiveInterval(unsigned Reg, float Weight, bool IsSS = false) : reg(Reg), weight(Weight), preference(0) { if (IsSS) @@ -414,6 +434,10 @@ namespace llvm { /// Also remove the value# from value# list. void removeValNo(VNInfo *ValNo); + /// scaleNumbering - Renumber VNI and ranges to provide gaps for new + /// instructions. + void scaleNumbering(unsigned factor); + /// getSize - Returns the sum of sizes of all the LiveRange's. /// unsigned getSize() const; diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 01ea6092e8c..7c44cc7dbf2 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -92,20 +92,12 @@ namespace llvm { std::vector ClonedMIs; + typedef LiveInterval::InstrSlots InstrSlots; + public: static char ID; // Pass identification, replacement for typeid LiveIntervals() : MachineFunctionPass(&ID) {} - struct InstrSlots { - enum { - LOAD = 0, - USE = 1, - DEF = 2, - STORE = 3, - NUM = 4 - }; - }; - static unsigned getBaseIndex(unsigned index) { return index - (index % InstrSlots::NUM); } @@ -226,6 +218,13 @@ namespace llvm { return getInstructionFromIndex(Index) == 0; } + /// hasGapAfterInstr - Return true if the successive instruction slot, + /// i.e. Index + InstrSlots::Num, is not occupied. + bool hasGapAfterInstr(unsigned Index) { + Index = getBaseIndex(Index + InstrSlots::NUM); + return getInstructionFromIndex(Index) == 0; + } + /// findGapBeforeInstr - Find an empty instruction slot before the /// specified index. If "Furthest" is true, find one that's furthest /// away from the index (but before any index that's occupied). @@ -394,6 +393,10 @@ namespace llvm { /// computeNumbering - Compute the index numbering. void computeNumbering(); + /// scaleNumbering - Rescale interval numbers to introduce gaps for new + /// instructions + void scaleNumbering(int factor); + /// intervalIsInOneMBB - Returns true if the specified interval is entirely /// within a single basic block. bool intervalIsInOneMBB(const LiveInterval &li) const; diff --git a/include/llvm/CodeGen/LiveStackAnalysis.h b/include/llvm/CodeGen/LiveStackAnalysis.h index a2a2f93df3f..27ae1be7f91 100644 --- a/include/llvm/CodeGen/LiveStackAnalysis.h +++ b/include/llvm/CodeGen/LiveStackAnalysis.h @@ -48,6 +48,8 @@ namespace llvm { iterator begin() { return S2IMap.begin(); } iterator end() { return S2IMap.end(); } + void scaleNumbering(int factor); + unsigned getNumIntervals() const { return (unsigned)S2IMap.size(); } LiveInterval &getOrCreateInterval(int Slot, const TargetRegisterClass *RC) { diff --git a/lib/CodeGen/LiveInterval.cpp b/lib/CodeGen/LiveInterval.cpp index 9dee892c75e..67120b87988 100644 --- a/lib/CodeGen/LiveInterval.cpp +++ b/lib/CodeGen/LiveInterval.cpp @@ -359,6 +359,29 @@ void LiveInterval::removeValNo(VNInfo *ValNo) { } } +/// scaleNumbering - Renumber VNI and ranges to provide gaps for new +/// instructions. +void LiveInterval::scaleNumbering(unsigned factor) { + // Scale ranges. + for (iterator RI = begin(), RE = end(); RI != RE; ++RI) { + RI->start = InstrSlots::scale(RI->start, factor); + RI->end = InstrSlots::scale(RI->end, factor); + } + + // Scale VNI info. + for (vni_iterator VNI = vni_begin(), VNIE = vni_end(); VNI != VNIE; ++VNI) { + VNInfo *vni = *VNI; + if (vni->def != ~0U && vni->def != ~1U) { + vni->def = InstrSlots::scale(vni->def, factor); + } + + for (unsigned i = 0; i < vni->kills.size(); ++i) { + if (vni->kills[i] != 0) + vni->kills[i] = InstrSlots::scale(vni->kills[i], factor); + } + } +} + /// getLiveRangeContaining - Return the live range that contains the /// specified index, or null if there is none. LiveInterval::const_iterator diff --git a/lib/CodeGen/LiveIntervalAnalysis.cpp b/lib/CodeGen/LiveIntervalAnalysis.cpp index bf18015e96c..cf0a648b629 100644 --- a/lib/CodeGen/LiveIntervalAnalysis.cpp +++ b/lib/CodeGen/LiveIntervalAnalysis.cpp @@ -36,6 +36,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" #include +#include #include using namespace llvm; @@ -243,6 +244,49 @@ void LiveIntervals::computeNumbering() { } } +void LiveIntervals::scaleNumbering(int factor) { + // Need to + // * scale MBB begin and end points + // * scale all ranges. + // * Update VNI structures. + // * Scale instruction numberings + + // Scale the MBB indices. + Idx2MBBMap.clear(); + for (MachineFunction::iterator MBB = mf_->begin(), MBBE = mf_->end(); + MBB != MBBE; ++MBB) { + std::pair &mbbIndices = MBB2IdxMap[MBB->getNumber()]; + mbbIndices.first = InstrSlots::scale(mbbIndices.first, factor); + mbbIndices.second = InstrSlots::scale(mbbIndices.second, factor); + Idx2MBBMap.push_back(std::make_pair(mbbIndices.first, MBB)); + } + std::sort(Idx2MBBMap.begin(), Idx2MBBMap.end(), Idx2MBBCompare()); + + // Scale the intervals. + for (iterator LI = begin(), LE = end(); LI != LE; ++LI) { + LI->second->scaleNumbering(factor); + } + + // Scale MachineInstrs. + Mi2IndexMap oldmi2iMap = mi2iMap_; + unsigned highestSlot = 0; + for (Mi2IndexMap::iterator MI = oldmi2iMap.begin(), ME = oldmi2iMap.end(); + MI != ME; ++MI) { + unsigned newSlot = InstrSlots::scale(MI->second, factor); + mi2iMap_[MI->first] = newSlot; + highestSlot = std::max(highestSlot, newSlot); + } + + i2miMap_.clear(); + i2miMap_.resize(highestSlot + 1); + for (Mi2IndexMap::iterator MI = mi2iMap_.begin(), ME = mi2iMap_.end(); + MI != ME; ++MI) { + i2miMap_[MI->second] = MI->first; + } + +} + + /// runOnMachineFunction - Register allocate the whole function /// bool LiveIntervals::runOnMachineFunction(MachineFunction &fn) { diff --git a/lib/CodeGen/LiveStackAnalysis.cpp b/lib/CodeGen/LiveStackAnalysis.cpp index c68a2d9a809..86f7ea20c9b 100644 --- a/lib/CodeGen/LiveStackAnalysis.cpp +++ b/lib/CodeGen/LiveStackAnalysis.cpp @@ -15,15 +15,24 @@ #define DEBUG_TYPE "livestacks" #include "llvm/CodeGen/LiveStackAnalysis.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" #include "llvm/CodeGen/Passes.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/Debug.h" #include "llvm/ADT/Statistic.h" +#include using namespace llvm; char LiveStacks::ID = 0; static RegisterPass X("livestacks", "Live Stack Slot Analysis"); +void LiveStacks::scaleNumbering(int factor) { + // Scale the intervals. + for (iterator LI = begin(), LE = end(); LI != LE; ++LI) { + LI->second.scaleNumbering(factor); + } +} + void LiveStacks::getAnalysisUsage(AnalysisUsage &AU) const { AU.setPreservesAll(); MachineFunctionPass::getAnalysisUsage(AU); diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index ac6ab323416..ee118de4f49 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/lib/CodeGen/RegAllocLinearScan.cpp @@ -40,6 +40,8 @@ #include #include #include +#include + using namespace llvm; STATISTIC(NumIters , "Number of iterations performed"); @@ -310,6 +312,93 @@ namespace { static RegisterPass X("linearscan-regalloc", "Linear Scan Register Allocator"); +bool validateRegAlloc(MachineFunction *mf, LiveIntervals *lis, + VirtRegMap *vrm) { + + MachineRegisterInfo *mri = &mf->getRegInfo(); + const TargetRegisterInfo *tri = mf->getTarget().getRegisterInfo(); + bool allocationValid = true; + + + for (LiveIntervals::iterator itr = lis->begin(), end = lis->end(); + itr != end; ++itr) { + + LiveInterval *li = itr->second; + + if (TargetRegisterInfo::isPhysicalRegister(li->reg)) { + continue; + } + + if (vrm->hasPhys(li->reg)) { + const TargetRegisterClass *trc = mri->getRegClass(li->reg); + + if (lis->hasInterval(vrm->getPhys(li->reg))) { + if (li->overlaps(lis->getInterval(vrm->getPhys(li->reg)))) { + std::cerr << "vreg " << li->reg << " overlaps its assigned preg " + << vrm->getPhys(li->reg) << "(" << tri->getName(vrm->getPhys(li->reg)) << ")\n"; + } + } + + TargetRegisterClass::iterator fReg = + std::find(trc->allocation_order_begin(*mf), trc->allocation_order_end(*mf), + vrm->getPhys(li->reg)); + + if (fReg == trc->allocation_order_end(*mf)) { + std::cerr << "preg " << vrm->getPhys(li->reg) + << "(" << tri->getName(vrm->getPhys(li->reg)) << ") is not in the allocation set for vreg " + << li->reg << "\n"; + allocationValid &= false; + } + } + else { + std::cerr << "No preg for vreg " << li->reg << "\n"; + // What about conflicting loads/stores? + continue; + } + + for (LiveIntervals::iterator itr2 = next(itr); itr2 != end; ++itr2) { + + LiveInterval *li2 = itr2->second; + + if (li2->empty()) + continue; + + if (TargetRegisterInfo::isPhysicalRegister(li2->reg)) { + if (li->overlaps(*li2)) { + if (vrm->getPhys(li->reg) == li2->reg || + tri->areAliases(vrm->getPhys(li->reg), li2->reg)) { + std::cerr << "vreg " << li->reg << " overlaps preg " + << li2->reg << "(" << tri->getName(li2->reg) << ") which aliases " + << vrm->getPhys(li->reg) << "(" << tri->getName(vrm->getPhys(li->reg)) << ")\n"; + allocationValid &= false; + } + } + } + else { + + if (!vrm->hasPhys(li2->reg)) { + continue; + } + + if (li->overlaps(*li2)) { + if (vrm->getPhys(li->reg) == vrm->getPhys(li2->reg) || + tri->areAliases(vrm->getPhys(li->reg), vrm->getPhys(li2->reg))) { + std::cerr << "vreg " << li->reg << " (preg " << vrm->getPhys(li->reg) + << ") overlaps vreg " << li2->reg << " (preg " << vrm->getPhys(li2->reg) + << ") and " << vrm->getPhys(li->reg) << " aliases " << vrm->getPhys(li2->reg) << "\n"; + allocationValid &= false; + } + } + } + } + + } + + return allocationValid; + +} + + void RALinScan::ComputeRelatedRegClasses() { // First pass, add all reg classes to the union, and determine at least one // reg class that each register is in. @@ -430,16 +519,17 @@ bool RALinScan::runOnMachineFunction(MachineFunction &fn) { if (!rewriter_.get()) rewriter_.reset(createVirtRegRewriter()); if (NewSpillFramework) { - spiller_.reset(createSpiller(mf_, li_, vrm_)); + spiller_.reset(createSpiller(mf_, li_, ls_, vrm_)); } - else { - spiller_.reset(0); - } - + initIntervalSets(); linearScan(); + if (NewSpillFramework) { + bool allocValid = validateRegAlloc(mf_, li_, vrm_); + } + // Rewrite spill code and update the PhysRegsUsed set. rewriter_->runOnMachineFunction(*mf_, *vrm_, li_); @@ -454,6 +544,7 @@ bool RALinScan::runOnMachineFunction(MachineFunction &fn) { NextReloadMap.clear(); DowngradedRegs.clear(); DowngradeMap.clear(); + spiller_.reset(0); return true; } @@ -1127,8 +1218,7 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) if (!NewSpillFramework) { added = li_->addIntervalsForSpills(*cur, spillIs, loopInfo, *vrm_); - } - else { + } else { added = spiller_->spill(cur); } @@ -1192,7 +1282,9 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) // The earliest start of a Spilled interval indicates up to where // in handled we need to roll back + unsigned earliestStart = cur->beginNumber(); + LiveInterval *earliestStartInterval = cur; // Spill live intervals of virtual regs mapped to the physical register we // want to clear (and its aliases). We only spill those that overlap with the @@ -1201,17 +1293,48 @@ void RALinScan::assignRegOrStackSlotAtInterval(LiveInterval* cur) // mark our rollback point. std::vector added; while (!spillIs.empty()) { + bool epicFail = false; LiveInterval *sli = spillIs.back(); spillIs.pop_back(); DOUT << "\t\t\tspilling(a): " << *sli << '\n'; earliestStart = std::min(earliestStart, sli->beginNumber()); - std::vector newIs = - li_->addIntervalsForSpills(*sli, spillIs, loopInfo, *vrm_); + earliestStartInterval = + (earliestStartInterval->beginNumber() < sli->beginNumber()) ? + earliestStartInterval : sli; + + if (earliestStartInterval->beginNumber()!=earliestStart) { + epicFail |= true; + std::cerr << "What the 1 - " + << "earliestStart = " << earliestStart + << "earliestStartInterval = " << earliestStartInterval->beginNumber() + << "\n"; + } + + std::vector newIs; + if (!NewSpillFramework) { + newIs = li_->addIntervalsForSpills(*sli, spillIs, loopInfo, *vrm_); + } else { + newIs = spiller_->spill(sli); + } addStackInterval(sli, ls_, li_, mri_, *vrm_); std::copy(newIs.begin(), newIs.end(), std::back_inserter(added)); spilled.insert(sli->reg); + + if (earliestStartInterval->beginNumber()!=earliestStart) { + epicFail |= true; + std::cerr << "What the 2 - " + << "earliestStart = " << earliestStart + << "earliestStartInterval = " << earliestStartInterval->beginNumber() + << "\n"; + } + + if (epicFail) { + //abort(); + } } + earliestStart = earliestStartInterval->beginNumber(); + DOUT << "\t\trolling back to: " << earliestStart << '\n'; // Scan handled in reverse order up to the earliest start of a diff --git a/lib/CodeGen/SimpleRegisterCoalescing.cpp b/lib/CodeGen/SimpleRegisterCoalescing.cpp index a7807f130e4..2bc234f7d09 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.cpp +++ b/lib/CodeGen/SimpleRegisterCoalescing.cpp @@ -2598,7 +2598,7 @@ void SimpleRegisterCoalescing::releaseMemory() { static bool isZeroLengthInterval(LiveInterval *li) { for (LiveInterval::Ranges::const_iterator i = li->ranges.begin(), e = li->ranges.end(); i != e; ++i) - if (i->end - i->start > LiveIntervals::InstrSlots::NUM) + if (i->end - i->start > LiveInterval::InstrSlots::NUM) return false; return true; } diff --git a/lib/CodeGen/SimpleRegisterCoalescing.h b/lib/CodeGen/SimpleRegisterCoalescing.h index d8ff2dc1524..a495bfd644a 100644 --- a/lib/CodeGen/SimpleRegisterCoalescing.h +++ b/lib/CodeGen/SimpleRegisterCoalescing.h @@ -133,7 +133,7 @@ namespace llvm { if (!li_->hasInterval(Reg)) return 0; return li_->getApproximateInstructionCount(li_->getInterval(Reg)) * - LiveIntervals::InstrSlots::NUM; + LiveInterval::InstrSlots::NUM; } /// print - Implement the dump method. diff --git a/lib/CodeGen/Spiller.cpp b/lib/CodeGen/Spiller.cpp index eb2a8a10b25..ce63121251e 100644 --- a/lib/CodeGen/Spiller.cpp +++ b/lib/CodeGen/Spiller.cpp @@ -12,6 +12,7 @@ #include "Spiller.h" #include "VirtRegMap.h" #include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/LiveStackAnalysis.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -19,28 +20,105 @@ #include "llvm/Target/TargetInstrInfo.h" #include "llvm/Support/Debug.h" -#include -#include - using namespace llvm; Spiller::~Spiller() {} namespace { -class TrivialSpiller : public Spiller { -public: - TrivialSpiller(MachineFunction *mf, LiveIntervals *lis, VirtRegMap *vrm) : - mf(mf), lis(lis), vrm(vrm) +/// Utility class for spillers. +class SpillerBase : public Spiller { +protected: + + MachineFunction *mf; + LiveIntervals *lis; + LiveStacks *ls; + MachineFrameInfo *mfi; + MachineRegisterInfo *mri; + const TargetInstrInfo *tii; + VirtRegMap *vrm; + + /// Construct a spiller base. + SpillerBase(MachineFunction *mf, LiveIntervals *lis, LiveStacks *ls, VirtRegMap *vrm) : + mf(mf), lis(lis), ls(ls), vrm(vrm) { mfi = mf->getFrameInfo(); mri = &mf->getRegInfo(); tii = mf->getTarget().getInstrInfo(); } - std::vector spill(LiveInterval *li) { + /// Insert a store of the given vreg to the given stack slot immediately + /// after the given instruction. Returns the base index of the inserted + /// instruction. The caller is responsible for adding an appropriate + /// LiveInterval to the LiveIntervals analysis. + unsigned insertStoreFor(MachineInstr *mi, unsigned ss, + unsigned newVReg, + const TargetRegisterClass *trc) { + MachineBasicBlock::iterator nextInstItr(mi); + ++nextInstItr; - DOUT << "Trivial spiller spilling " << *li << "\n"; + if (!lis->hasGapAfterInstr(lis->getInstructionIndex(mi))) { + lis->scaleNumbering(2); + ls->scaleNumbering(2); + } + + unsigned miIdx = lis->getInstructionIndex(mi); + + assert(lis->hasGapAfterInstr(miIdx)); + + tii->storeRegToStackSlot(*mi->getParent(), nextInstItr, newVReg, + true, ss, trc); + MachineBasicBlock::iterator storeInstItr(mi); + ++storeInstItr; + MachineInstr *storeInst = &*storeInstItr; + unsigned storeInstIdx = miIdx + LiveInterval::InstrSlots::NUM; + + assert(lis->getInstructionFromIndex(storeInstIdx) == 0 && + "Store inst index already in use."); + + lis->InsertMachineInstrInMaps(storeInst, storeInstIdx); + + return storeInstIdx; + } + + /// Insert a load of the given veg from the given stack slot immediately + /// before the given instruction. Returns the base index of the inserted + /// instruction. The caller is responsible for adding an appropriate + /// LiveInterval to the LiveIntervals analysis. + unsigned insertLoadFor(MachineInstr *mi, unsigned ss, + unsigned newVReg, + const TargetRegisterClass *trc) { + MachineBasicBlock::iterator useInstItr(mi); + + if (!lis->hasGapBeforeInstr(lis->getInstructionIndex(mi))) { + lis->scaleNumbering(2); + ls->scaleNumbering(2); + } + + unsigned miIdx = lis->getInstructionIndex(mi); + + assert(lis->hasGapBeforeInstr(miIdx)); + + tii->loadRegFromStackSlot(*mi->getParent(), useInstItr, newVReg, ss, trc); + MachineBasicBlock::iterator loadInstItr(mi); + --loadInstItr; + MachineInstr *loadInst = &*loadInstItr; + unsigned loadInstIdx = miIdx - LiveInterval::InstrSlots::NUM; + + assert(lis->getInstructionFromIndex(loadInstIdx) == 0 && + "Load inst index already in use."); + + lis->InsertMachineInstrInMaps(loadInst, loadInstIdx); + + return loadInstIdx; + } + + + /// Add spill ranges for every use/def of the live interval, inserting loads + /// immediately before each use, and stores after each def. No folding is + /// attempted. + std::vector trivialSpillEverywhere(LiveInterval *li) { + DOUT << "Spilling everywhere " << *li << "\n"; assert(li->weight != HUGE_VALF && "Attempting to spill already spilled value."); @@ -51,16 +129,16 @@ public: std::vector added; const TargetRegisterClass *trc = mri->getRegClass(li->reg); - /*unsigned ss = mfi->CreateStackObject(trc->getSize(), - trc->getAlignment());*/ unsigned ss = vrm->assignVirt2StackSlot(li->reg); - MachineRegisterInfo::reg_iterator regItr = mri->reg_begin(li->reg); - - while (regItr != mri->reg_end()) { + for (MachineRegisterInfo::reg_iterator + regItr = mri->reg_begin(li->reg); regItr != mri->reg_end();) { MachineInstr *mi = &*regItr; - + do { + ++regItr; + } while (regItr != mri->reg_end() && (&*regItr == mi)); + SmallVector indices; bool hasUse = false; bool hasDef = false; @@ -78,12 +156,12 @@ public: } unsigned newVReg = mri->createVirtualRegister(trc); - LiveInterval *newLI = &lis->getOrCreateInterval(newVReg); - newLI->weight = HUGE_VALF; - vrm->grow(); vrm->assignVirt2StackSlot(newVReg, ss); + LiveInterval *newLI = &lis->getOrCreateInterval(newVReg); + newLI->weight = HUGE_VALF; + for (unsigned i = 0; i < indices.size(); ++i) { mi->getOperand(indices[i]).setReg(newVReg); @@ -92,6 +170,8 @@ public: } } + assert(hasUse || hasDef); + if (hasUse) { unsigned loadInstIdx = insertLoadFor(mi, ss, newVReg, trc); unsigned start = lis->getDefIndex(loadInstIdx), @@ -103,7 +183,6 @@ public: LiveRange lr(start, end, vni); newLI->addRange(lr); - added.push_back(newLI); } if (hasDef) { @@ -117,90 +196,34 @@ public: LiveRange lr(start, end, vni); newLI->addRange(lr); - added.push_back(newLI); } - regItr = mri->reg_begin(li->reg); + added.push_back(newLI); } return added; } - -private: - - MachineFunction *mf; - LiveIntervals *lis; - MachineFrameInfo *mfi; - MachineRegisterInfo *mri; - const TargetInstrInfo *tii; - VirtRegMap *vrm; +}; +/// Spills any live range using the spill-everywhere method with no attempt at +/// folding. +class TrivialSpiller : public SpillerBase { +public: + TrivialSpiller(MachineFunction *mf, LiveIntervals *lis, LiveStacks *ls, VirtRegMap *vrm) : + SpillerBase(mf, lis, ls, vrm) {} - void makeRoomForInsertBefore(MachineInstr *mi) { - if (!lis->hasGapBeforeInstr(lis->getInstructionIndex(mi))) { - lis->computeNumbering(); - } - - assert(lis->hasGapBeforeInstr(lis->getInstructionIndex(mi))); - } - - unsigned insertStoreFor(MachineInstr *mi, unsigned ss, - unsigned newVReg, - const TargetRegisterClass *trc) { - MachineBasicBlock::iterator nextInstItr(mi); - ++nextInstItr; - - makeRoomForInsertBefore(&*nextInstItr); - - unsigned miIdx = lis->getInstructionIndex(mi); - - tii->storeRegToStackSlot(*mi->getParent(), nextInstItr, newVReg, - true, ss, trc); - MachineBasicBlock::iterator storeInstItr(mi); - ++storeInstItr; - MachineInstr *storeInst = &*storeInstItr; - unsigned storeInstIdx = miIdx + LiveIntervals::InstrSlots::NUM; - - assert(lis->getInstructionFromIndex(storeInstIdx) == 0 && - "Store inst index already in use."); - - lis->InsertMachineInstrInMaps(storeInst, storeInstIdx); - - return storeInstIdx; - } - - unsigned insertLoadFor(MachineInstr *mi, unsigned ss, - unsigned newVReg, - const TargetRegisterClass *trc) { - MachineBasicBlock::iterator useInstItr(mi); - - makeRoomForInsertBefore(mi); - - unsigned miIdx = lis->getInstructionIndex(mi); - - tii->loadRegFromStackSlot(*mi->getParent(), useInstItr, newVReg, ss, trc); - MachineBasicBlock::iterator loadInstItr(mi); - --loadInstItr; - MachineInstr *loadInst = &*loadInstItr; - unsigned loadInstIdx = miIdx - LiveIntervals::InstrSlots::NUM; - - assert(lis->getInstructionFromIndex(loadInstIdx) == 0 && - "Load inst index already in use."); - - lis->InsertMachineInstrInMaps(loadInst, loadInstIdx); - - return loadInstIdx; + std::vector spill(LiveInterval *li) { + return trivialSpillEverywhere(li); } }; } - llvm::Spiller* llvm::createSpiller(MachineFunction *mf, LiveIntervals *lis, - VirtRegMap *vrm) { - return new TrivialSpiller(mf, lis, vrm); + LiveStacks *ls, VirtRegMap *vrm) { + return new TrivialSpiller(mf, lis, ls, vrm); } diff --git a/lib/CodeGen/Spiller.h b/lib/CodeGen/Spiller.h index 730419b057d..cad054d744c 100644 --- a/lib/CodeGen/Spiller.h +++ b/lib/CodeGen/Spiller.h @@ -13,8 +13,9 @@ #include namespace llvm { - struct LiveInterval; + class LiveInterval; class LiveIntervals; + class LiveStacks; class MachineFunction; class VirtRegMap; @@ -30,7 +31,7 @@ namespace llvm { /// Create and return a spiller object, as specified on the command line. Spiller* createSpiller(MachineFunction *mf, LiveIntervals *li, - VirtRegMap *vrm); + LiveStacks *ls, VirtRegMap *vrm); } #endif diff --git a/lib/CodeGen/StrongPHIElimination.cpp b/lib/CodeGen/StrongPHIElimination.cpp index 5d7bc23694b..a2c12554f37 100644 --- a/lib/CodeGen/StrongPHIElimination.cpp +++ b/lib/CodeGen/StrongPHIElimination.cpp @@ -1027,7 +1027,7 @@ bool StrongPHIElimination::runOnMachineFunction(MachineFunction &Fn) { if (MBB != PInstr->getParent() && InputI.liveAt(LI.getMBBStartIdx(PInstr->getParent())) && InputI.expiredAt(LI.getInstructionIndex(PInstr) + - LiveIntervals::InstrSlots::NUM)) + LiveInterval::InstrSlots::NUM)) InputI.removeRange(LI.getMBBStartIdx(PInstr->getParent()), LI.getInstructionIndex(PInstr), true); diff --git a/lib/CodeGen/VirtRegRewriter.cpp b/lib/CodeGen/VirtRegRewriter.cpp index 36d16975494..b4c8bc12979 100644 --- a/lib/CodeGen/VirtRegRewriter.cpp +++ b/lib/CodeGen/VirtRegRewriter.cpp @@ -33,15 +33,16 @@ STATISTIC(NumSUnfold , "Number of stores unfolded"); STATISTIC(NumModRefUnfold, "Number of modref unfolded"); namespace { - enum RewriterName { simple, local }; + enum RewriterName { simple, local, trivial }; } static cl::opt RewriterOpt("rewriter", cl::desc("Rewriter to use: (default: local)"), cl::Prefix, - cl::values(clEnumVal(simple, "simple rewriter"), - clEnumVal(local, "local rewriter"), + cl::values(clEnumVal(simple, "simple rewriter"), + clEnumVal(local, "local rewriter"), + clEnumVal(trivial, "trivial rewriter"), clEnumValEnd), cl::init(local)); @@ -126,6 +127,42 @@ struct VISIBILITY_HIDDEN SimpleRewriter : public VirtRegRewriter { }; +/// This class is intended for use with the new spilling framework only. It +/// rewrites vreg def/uses to use the assigned preg, but does not insert any +/// spill code. +struct VISIBILITY_HIDDEN TrivialRewriter : public VirtRegRewriter { + + bool runOnMachineFunction(MachineFunction &MF, VirtRegMap &VRM, + LiveIntervals* LIs) { + DOUT << "********** REWRITE MACHINE CODE **********\n"; + DOUT << "********** Function: " << MF.getFunction()->getName() << '\n'; + MachineRegisterInfo *mri = &MF.getRegInfo(); + + bool changed = false; + + for (LiveIntervals::iterator liItr = LIs->begin(), liEnd = LIs->end(); + liItr != liEnd; ++liItr) { + + if (TargetRegisterInfo::isVirtualRegister(liItr->first)) { + if (VRM.hasPhys(liItr->first)) { + unsigned preg = VRM.getPhys(liItr->first); + mri->replaceRegWith(liItr->first, preg); + mri->setPhysRegUsed(preg); + changed = true; + } + } + else { + if (!liItr->second->empty()) { + mri->setPhysRegUsed(liItr->first); + } + } + } + + return changed; + } + +}; + // ************************************************************************ // /// AvailableSpills - As the local rewriter is scanning and rewriting an MBB @@ -2182,5 +2219,7 @@ llvm::VirtRegRewriter* llvm::createVirtRegRewriter() { return new LocalRewriter(); case simple: return new SimpleRewriter(); + case trivial: + return new TrivialRewriter(); } }