diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index e62c31d4e6f..1244368b601 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -219,6 +219,39 @@ namespace llvm { return i2miMap_[index]; } + /// hasGapBeforeInstr - Return true if the previous instruction slot, + /// i.e. Index - InstrSlots::NUM, is not occupied. + bool hasGapBeforeInstr(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). + unsigned findGapBeforeInstr(unsigned Index, bool Furthest = false) { + Index = getBaseIndex(Index - InstrSlots::NUM); + if (getInstructionFromIndex(Index)) + return 0; // No gap! + if (!Furthest) + return Index; + unsigned PrevIndex = getBaseIndex(Index - InstrSlots::NUM); + while (getInstructionFromIndex(Index)) { + Index = PrevIndex; + PrevIndex = getBaseIndex(Index - InstrSlots::NUM); + } + return Index; + } + + /// InsertMachineInstrInMaps - Insert the specified machine instruction + /// into the instruction index map at the given index. + void InsertMachineInstrInMaps(MachineInstr *MI, unsigned Index) { + i2miMap_[Index / InstrSlots::NUM] = MI; + Mi2IndexMap::iterator it = mi2iMap_.find(MI); + assert(it == mi2iMap_.end() && "Already in map!"); + mi2iMap_[MI] = Index; + } + /// conflictsWithPhysRegDef - Returns true if the specified register /// is defined during the duration of the specified interval. bool conflictsWithPhysRegDef(const LiveInterval &li, VirtRegMap &vrm, diff --git a/lib/CodeGen/PreAllocSplitting.cpp b/lib/CodeGen/PreAllocSplitting.cpp index 7b4ec8efbcf..9ac799cf360 100644 --- a/lib/CodeGen/PreAllocSplitting.cpp +++ b/lib/CodeGen/PreAllocSplitting.cpp @@ -16,29 +16,51 @@ #define DEBUG_TYPE "pre-alloc-split" #include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineLoopInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/RegisterCoalescer.h" +#include "llvm/Target/TargetInstrInfo.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include "llvm/Target/TargetRegisterInfo.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/ADT/PostOrderIterator.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/Statistic.h" +#include using namespace llvm; +STATISTIC(NumSplit , "Number of intervals split"); + namespace { class VISIBILITY_HIDDEN PreAllocSplitting : public MachineFunctionPass { - // ProcessedBarriers - Register live interval barriers that have already - // been processed. - SmallPtrSet ProcessedBarriers; + MachineFunction *CurMF; + const TargetMachine *TM; + const TargetInstrInfo *TII; + MachineFrameInfo *MFI; + MachineRegisterInfo *MRI; + LiveIntervals *LIs; + + // Barrier - Current barrier being processed. + MachineInstr *Barrier; + + // BarrierMBB - Basic block where the barrier resides in. + MachineBasicBlock *BarrierMBB; + + // Barrier - Current barrier index. + unsigned BarrierIdx; + + // CurrLI - Current live interval being split. + LiveInterval *CurrLI; + + // LIValNoSSMap - A map from live interval and val# pairs to spill slots. + // This records what live interval's val# has been split and what spill + // slot was used. + std::map, int> LIValNoSSMap; - // ActiveBarriers - Register live interval barriers that are currently - // being processed. - SmallSet ActiveBarriers; public: static char ID; PreAllocSplitting() : MachineFunctionPass(&ID) {} @@ -48,24 +70,60 @@ namespace { virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); AU.addPreserved(); - AU.addPreserved(); AU.addPreserved(); if (StrongPHIElim) AU.addPreservedID(StrongPHIEliminationID); else AU.addPreservedID(PHIEliminationID); - AU.addPreservedID(TwoAddressInstructionPassID); MachineFunctionPass::getAnalysisUsage(AU); } virtual void releaseMemory() { - ProcessedBarriers.clear(); - ActiveBarriers.clear(); + LIValNoSSMap.clear(); } virtual const char *getPassName() const { return "Pre-Register Allocaton Live Interval Splitting"; } + + /// print - Implement the dump method. + virtual void print(std::ostream &O, const Module* M = 0) const { + LIs->print(O, M); + } + + void print(std::ostream *O, const Module* M = 0) const { + if (O) print(*O, M); + } + + private: + MachineBasicBlock::iterator + findNextEmptySlot(MachineBasicBlock*, MachineInstr*, + unsigned&); + + MachineBasicBlock::iterator + findSpillPoint(MachineBasicBlock*, MachineInstr*, + SmallPtrSet&, unsigned&); + + MachineBasicBlock::iterator + findRestorePoint(MachineBasicBlock*, MachineInstr*, + SmallPtrSet&, unsigned&); + + void RecordSplit(unsigned, unsigned, unsigned, int); + + bool isAlreadySplit(unsigned, unsigned, int&); + + void UpdateIntervalForSplit(VNInfo*, unsigned, unsigned); + + bool ShrinkWrapToLastUse(MachineBasicBlock*, + std::vector&); + + void ShrinkWrapLiveInterval(VNInfo*, MachineBasicBlock*, + MachineBasicBlock*, SmallPtrSet&, + DenseMap >&); + + bool SplitRegLiveInterval(LiveInterval*); + + bool SplitRegLiveIntervals(const TargetRegisterClass **); }; } // end anonymous namespace @@ -76,6 +134,507 @@ X("pre-alloc-splitting", "Pre-Register Allocation Live Interval Splitting"); const PassInfo *const llvm::PreAllocSplittingID = &X; -bool PreAllocSplitting::runOnMachineFunction(MachineFunction &MF) { - return false; + +/// findNextEmptySlot - Find a gap after the given machine instruction in the +/// instruction index map. If there isn't one, return end(). +MachineBasicBlock::iterator +PreAllocSplitting::findNextEmptySlot(MachineBasicBlock *MBB, MachineInstr *MI, + unsigned &SpotIndex) { + MachineBasicBlock::iterator MII = MI; + if (++MII != MBB->end()) { + unsigned Index = LIs->findGapBeforeInstr(LIs->getInstructionIndex(MII)); + if (Index) { + SpotIndex = Index; + return MII; + } + } + return MBB->end(); +} + +/// findSpillPoint - Find a gap as far away from the given MI that's suitable +/// for spilling the current live interval. The index must be before any +/// defs and uses of the live interval register in the mbb. Return begin() if +/// none is found. +MachineBasicBlock::iterator +PreAllocSplitting::findSpillPoint(MachineBasicBlock *MBB, MachineInstr *MI, + SmallPtrSet &RefsInMBB, + unsigned &SpillIndex) { + MachineBasicBlock::iterator Pt = MBB->begin(); + + // Go top down if RefsInMBB is empty. + if (RefsInMBB.empty()) { + MachineBasicBlock::iterator MII = MBB->begin(); + MachineBasicBlock::iterator EndPt = MI; + do { + ++MII; + unsigned Index = LIs->getInstructionIndex(MII); + unsigned Gap = LIs->findGapBeforeInstr(Index); + if (Gap) { + Pt = MII; + SpillIndex = Gap; + break; + } + } while (MII != EndPt); + } else { + MachineBasicBlock::iterator MII = MI; + while (MII != MBB->begin() && !RefsInMBB.count(MII)) { + unsigned Index = LIs->getInstructionIndex(MII); + if (LIs->hasGapBeforeInstr(Index)) { + Pt = MII; + SpillIndex = LIs->findGapBeforeInstr(Index, true); + } + --MII; + } + } + + return Pt; +} + +/// findRestorePoint - Find a gap in the instruction index map that's suitable +/// for restoring the current live interval value. The index must be before any +/// uses of the live interval register in the mbb. Return end() if none is +/// found. +MachineBasicBlock::iterator +PreAllocSplitting::findRestorePoint(MachineBasicBlock *MBB, MachineInstr *MI, + SmallPtrSet &RefsInMBB, + unsigned &RestoreIndex) { + MachineBasicBlock::iterator Pt = MBB->end(); + + // Go bottom up if RefsInMBB is empty. + if (RefsInMBB.empty()) { + MachineBasicBlock::iterator MII = MBB->end(); + MachineBasicBlock::iterator EndPt = MI; + do { + --MII; + unsigned Index = LIs->getInstructionIndex(MII); + unsigned Gap = LIs->hasGapBeforeInstr(Index); + if (Gap) { + Pt = MII; + RestoreIndex = Gap; + break; + } + } while (MII != EndPt); + } else { + MachineBasicBlock::iterator MII = MI; + MII = ++MII; + while (MII != MBB->end()) { + unsigned Index = LIs->getInstructionIndex(MII); + unsigned Gap = LIs->findGapBeforeInstr(Index); + if (Gap) { + Pt = MII; + RestoreIndex = Gap; + } + if (RefsInMBB.count(MII)) + break; + ++MII; + } + } + + return Pt; +} + +/// RecordSplit - Given a register live interval is split, remember the spill +/// slot where the val#s are in. +void PreAllocSplitting::RecordSplit(unsigned Reg, unsigned SpillIndex, + unsigned RestoreIndex, int SS) { + LiveInterval::iterator LR = + CurrLI->FindLiveRangeContaining(LIs->getUseIndex(SpillIndex)); + LIValNoSSMap.insert(std::make_pair(std::make_pair(CurrLI->reg, LR->valno->id), + SS)); + LR = CurrLI->FindLiveRangeContaining(LIs->getDefIndex(RestoreIndex)); + LIValNoSSMap.insert(std::make_pair(std::make_pair(CurrLI->reg, LR->valno->id), + SS)); +} + +/// isAlreadySplit - Return if a given val# of a register live interval is already +/// split. Also return by reference the spill stock where the value is. +bool PreAllocSplitting::isAlreadySplit(unsigned Reg, unsigned ValNoId, int &SS){ + std::map, int>::iterator I = + LIValNoSSMap.find(std::make_pair(Reg, ValNoId)); + if (I == LIValNoSSMap.end()) + return false; + SS = I->second; + return true; +} + +/// UpdateIntervalForSplit - Given the specified val# of the current live +/// interval is being split, and the split and rejoin indices, update the live +/// interval accordingly. +void +PreAllocSplitting::UpdateIntervalForSplit(VNInfo *ValNo, unsigned SplitIndex, + unsigned JoinIndex) { + SmallVector, 4> Before; + SmallVector, 4> After; + SmallVector BeforeKills; + SmallVector AfterKills; + SmallPtrSet Processed; + + // First, let's figure out which parts of the live interval is now defined + // by the restore, which are defined by the original definition. + const LiveRange *LR = CurrLI->getLiveRangeContaining(JoinIndex); + After.push_back(std::make_pair(JoinIndex, LR->end)); + assert(LR->contains(SplitIndex)); + Before.push_back(std::make_pair(LR->start, SplitIndex)); + BeforeKills.push_back(SplitIndex); + Processed.insert(LR); + + SmallVector WorkList; + MachineBasicBlock *MBB = LIs->getMBBFromIndex(LR->end-1); + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) + WorkList.push_back(*SI); + + while (!WorkList.empty()) { + MBB = WorkList.back(); + WorkList.pop_back(); + unsigned Idx = LIs->getMBBStartIdx(MBB); + LR = CurrLI->getLiveRangeContaining(Idx); + if (LR && LR->valno == ValNo && !Processed.count(LR)) { + After.push_back(std::make_pair(LR->start, LR->end)); + if (CurrLI->isKill(ValNo, LR->end)) + AfterKills.push_back(LR->end); + Idx = LIs->getMBBEndIdx(MBB); + if (LR->end > Idx) { + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) + WorkList.push_back(*SI); + if (LR->end > Idx+1) { + MBB = LIs->getMBBFromIndex(LR->end-1); + for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), + SE = MBB->succ_end(); SI != SE; ++SI) + WorkList.push_back(*SI); + } + } + Processed.insert(LR); + } + } + + for (LiveInterval::iterator I = CurrLI->begin(), E = CurrLI->end(); + I != E; ++I) { + LiveRange *LR = I; + if (LR->valno == ValNo && !Processed.count(LR)) { + Before.push_back(std::make_pair(LR->start, LR->end)); + if (CurrLI->isKill(ValNo, LR->end)) + BeforeKills.push_back(LR->end); + } + } + + // Now create new val#s to represent the live ranges defined by the old def + // those defined by the restore. + unsigned AfterDef = ValNo->def; + MachineInstr *AfterCopy = ValNo->copy; + bool HasPHIKill = ValNo->hasPHIKill; + CurrLI->removeValNo(ValNo); + VNInfo *BValNo = CurrLI->getNextValue(AfterDef, AfterCopy, + LIs->getVNInfoAllocator()); + VNInfo *AValNo = CurrLI->getNextValue(JoinIndex,0, LIs->getVNInfoAllocator()); + AValNo->hasPHIKill = HasPHIKill; + CurrLI->addKills(AValNo, AfterKills); + CurrLI->addKills(BValNo, BeforeKills); + + for (unsigned i = 0, e = Before.size(); i != e; ++i) { + unsigned Start = Before[i].first; + unsigned End = Before[i].second; + CurrLI->addRange(LiveRange(Start, End, BValNo)); + } + for (unsigned i = 0, e = After.size(); i != e; ++i) { + unsigned Start = After[i].first; + unsigned End = After[i].second; + CurrLI->addRange(LiveRange(Start, End, AValNo)); + } +} + +/// ShrinkWrapToLastUse - There are uses of the current live interval in the +/// given block, shrink wrap the live interval to the last use (i.e. remove +/// from last use to the end of the mbb). In case mbb is the where the barrier +/// is, remove from the last use to the barrier. +bool +PreAllocSplitting::ShrinkWrapToLastUse(MachineBasicBlock *MBB, + std::vector &Uses) { + MachineOperand *LastMO = 0; + MachineInstr *LastMI = 0; + if (MBB != BarrierMBB && Uses.size() == 1) { + // Single use, no need to traverse the block. We can't assume this for the + // barrier bb though since the use is probably below the barrier. + LastMO = Uses[0]; + LastMI = LastMO->getParent(); + } else { + SmallPtrSet UseMIs; + for (unsigned i = 0, e = Uses.size(); i != e; ++i) + UseMIs.insert(Uses[i]->getParent()); + MachineBasicBlock::iterator MII; + if (MBB == BarrierMBB) { + MII = Barrier; + --MII; + } else + MII = MBB->end(); + for (MachineBasicBlock::iterator MEE = MBB->begin(); MII != MEE; --MII) { + MachineInstr *UseMI = &*MII; + if (!UseMIs.count(UseMI)) + continue; + for (unsigned i = 0, e = UseMI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = UseMI->getOperand(i); + if (MO.isReg() && MO.getReg() == CurrLI->reg) { + LastMO = &MO; + break; + } + } + LastMI = UseMI; + break; + } + } + + // Cut off live range from last use (or beginning of the mbb if there + // are no uses in it) to the end of the mbb. + unsigned RangeStart, RangeEnd = LIs->getMBBEndIdx(MBB)+1; + if (LastMI) { + RangeStart = LIs->getUseIndex(LIs->getInstructionIndex(LastMI))+1; + assert(!LastMO->isKill() && "Last use already terminates the interval?"); + LastMO->setIsKill(); + } else { + assert(MBB == BarrierMBB); + RangeStart = LIs->getMBBStartIdx(MBB); + } + if (MBB == BarrierMBB) + RangeEnd = LIs->getUseIndex(BarrierIdx); + CurrLI->removeRange(RangeStart, RangeEnd); + + // Return true if the last use becomes a new kill. + return LastMI; +} + +/// ShrinkWrapLiveInterval - Recursively traverse the predecessor +/// chain to find the new 'kills' and shrink wrap the live interval to the +/// new kill indices. +void +PreAllocSplitting::ShrinkWrapLiveInterval(VNInfo *ValNo, + MachineBasicBlock *MBB, MachineBasicBlock *DefMBB, + SmallPtrSet &Visited, + DenseMap > &Uses) { + if (!Visited.insert(MBB)) + return; + + DenseMap >::iterator UMII = + Uses.find(MBB->getNumber()); + if (UMII != Uses.end()) { + // At least one use in this mbb, lets look for the kill. + if (ShrinkWrapToLastUse(MBB, UMII->second)) + // Found a kill, shrink wrapping of this path ends here. + return; + } else { + // Remove entire live range of the bb out of the live interval. + CurrLI->removeRange(LIs->getMBBStartIdx(MBB), LIs->getMBBEndIdx(MBB)); + abort(); // FIXME + } + + if (MBB == DefMBB) + // Reached the def mbb, stop traversing this path further. + return; + + // Traverse the pathes up the predecessor chains further. + for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(), + PE = MBB->pred_end(); PI != PE; ++PI) { + MachineBasicBlock *Pred = *PI; + if (Pred == MBB) + continue; + if (Pred == DefMBB && ValNo->hasPHIKill) + // Pred is the def bb and the def reaches other val#s, we must + // allow the value to be live out of the bb. + continue; + ShrinkWrapLiveInterval(ValNo, Pred, DefMBB, Visited, Uses); + } + + return; +} + +/// SplitRegLiveInterval - Split (spill and restore) the given live interval +/// so it would not cross the barrier that's being processed. Shrink wrap +/// (minimize) the live interval to the last uses. +bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) { + CurrLI = LI; + + // Find live range where current interval cross the barrier. + LiveInterval::iterator LR = + CurrLI->FindLiveRangeContaining(LIs->getUseIndex(BarrierIdx)); + VNInfo *ValNo = LR->valno; + + if (ValNo->def == ~1U) { + // Defined by a dead def? How can this be? + assert(0 && "Val# is defined by a dead def?"); + abort(); + } + + // Find all references in the barrier mbb. + SmallPtrSet RefsInMBB; + for (MachineRegisterInfo::reg_iterator I = MRI->reg_begin(CurrLI->reg), + E = MRI->reg_end(); I != E; ++I) { + MachineInstr *RefMI = &*I; + if (RefMI->getParent() == BarrierMBB) + RefsInMBB.insert(RefMI); + } + + // Find a point to restore the value after the barrier. + unsigned RestoreIndex; + MachineBasicBlock::iterator RestorePt = + findRestorePoint(BarrierMBB, Barrier, RefsInMBB, RestoreIndex); + if (RestorePt == BarrierMBB->end()) + return false; + + // Add a spill either before the barrier or after the definition. + MachineBasicBlock *DefMBB = NULL; + const TargetRegisterClass *RC = MRI->getRegClass(CurrLI->reg); + int SS; + unsigned SpillIndex = 0; + if (isAlreadySplit(CurrLI->reg, ValNo->id, SS)) { + // If it's already split, just restore the value. There is no need to spill + // the def again. + abort(); // FIXME + } else if (ValNo->def == ~0U) { + // If it's defined by a phi, we must split just before the barrier. + MachineBasicBlock::iterator SpillPt = + findSpillPoint(BarrierMBB, Barrier, RefsInMBB, SpillIndex); + if (SpillPt == BarrierMBB->begin()) + return false; // No gap to insert spill. + // Add spill. + SS = MFI->CreateStackObject(RC->getSize(), RC->getAlignment()); + TII->storeRegToStackSlot(*BarrierMBB, SpillPt, CurrLI->reg, true, SS, RC); + MachineInstr *StoreMI = prior(SpillPt); + LIs->InsertMachineInstrInMaps(StoreMI, SpillIndex); + } else { + // Check if it's possible to insert a spill after the def MI. + MachineInstr *DefMI = LIs->getInstructionFromIndex(ValNo->def); + DefMBB = DefMI->getParent(); + MachineBasicBlock::iterator SpillPt = + findNextEmptySlot(DefMBB, DefMI, SpillIndex); + if (SpillPt == DefMBB->end()) + return false; // No gap to insert spill. + SS = MFI->CreateStackObject(RC->getSize(), RC->getAlignment()); + + // Add spill. The store instruction does *not* kill the register. + TII->storeRegToStackSlot(*DefMBB, SpillPt, CurrLI->reg, false, SS, RC); + MachineInstr *StoreMI = prior(SpillPt); + LIs->InsertMachineInstrInMaps(StoreMI, SpillIndex); + } + + // Add restore. + // FIXME: Create live interval for stack slot. + TII->loadRegFromStackSlot(*BarrierMBB, RestorePt, CurrLI->reg, SS, RC); + MachineInstr *LoadMI = prior(RestorePt); + LIs->InsertMachineInstrInMaps(LoadMI, RestoreIndex); + + // If live interval is spilled in the same block as the barrier, just + // create a hole in the interval. + if (!DefMBB || + LIs->getInstructionFromIndex(SpillIndex)->getParent() == BarrierMBB) { + UpdateIntervalForSplit(ValNo, LIs->getUseIndex(SpillIndex)+1, + LIs->getDefIndex(RestoreIndex)); + + // Record val# values are in the specific spill slot. + RecordSplit(CurrLI->reg, SpillIndex, RestoreIndex, SS); + + ++NumSplit; + return true; + } + + // Shrink wrap the live interval by walking up the CFG and find the + // new kills. + // Now let's find all the uses of the val#. + DenseMap > Uses; + for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(CurrLI->reg), + UE = MRI->use_end(); UI != UE; ++UI) { + MachineOperand &UseMO = UI.getOperand(); + MachineInstr *UseMI = UseMO.getParent(); + unsigned UseIdx = LIs->getInstructionIndex(UseMI); + LiveInterval::iterator ULR = CurrLI->FindLiveRangeContaining(UseIdx); + if (ULR->valno != ValNo) + continue; + MachineBasicBlock *UseMBB = UseMI->getParent(); + unsigned MBBId = UseMBB->getNumber(); + DenseMap >::iterator UMII = + Uses.find(MBBId); + if (UMII != Uses.end()) + UMII->second.push_back(&UseMO); + else { + std::vector Ops; + Ops.push_back(&UseMO); + Uses.insert(std::make_pair(MBBId, Ops)); + } + } + + // Walk up the predecessor chains. + SmallPtrSet Visited; + ShrinkWrapLiveInterval(ValNo, BarrierMBB, DefMBB, Visited, Uses); + + // Remove live range from barrier to the restore. FIXME: Find a better + // point to re-start the live interval. + UpdateIntervalForSplit(ValNo, LIs->getUseIndex(BarrierIdx)+1, + LIs->getDefIndex(RestoreIndex)); + // Record val# values are in the specific spill slot. + RecordSplit(CurrLI->reg, BarrierIdx, RestoreIndex, SS); + + ++NumSplit; + return true; +} + +/// SplitRegLiveIntervals - Split all register live intervals that cross the +/// barrier that's being processed. +bool +PreAllocSplitting::SplitRegLiveIntervals(const TargetRegisterClass **RCs) { + // First find all the virtual registers whose live intervals are intercepted + // by the current barrier. + SmallVector Intervals; + for (const TargetRegisterClass **RC = RCs; *RC; ++RC) { + std::vector &VRs = MRI->getRegClassVirtRegs(*RC); + for (unsigned i = 0, e = VRs.size(); i != e; ++i) { + unsigned Reg = VRs[i]; + if (!LIs->hasInterval(Reg)) + continue; + LiveInterval *LI = &LIs->getInterval(Reg); + if (LI->liveAt(BarrierIdx) && !Barrier->readsRegister(Reg)) + // Virtual register live interval is intercepted by the barrier. We + // should split and shrink wrap its interval if possible. + Intervals.push_back(LI); + } + } + + // Process the affected live intervals. + bool Change = false; + while (!Intervals.empty()) { + LiveInterval *LI = Intervals.back(); + Intervals.pop_back(); + Change |= SplitRegLiveInterval(LI); + } + + return Change; +} + +bool PreAllocSplitting::runOnMachineFunction(MachineFunction &MF) { + CurMF = &MF; + TM = &MF.getTarget(); + TII = TM->getInstrInfo(); + MFI = MF.getFrameInfo(); + MRI = &MF.getRegInfo(); + LIs = &getAnalysis(); + + bool MadeChange = false; + + // Make sure blocks are numbered in order. + MF.RenumberBlocks(); + + for (MachineFunction::reverse_iterator I = MF.rbegin(), E = MF.rend(); + I != E; ++I) { + BarrierMBB = &*I; + for (MachineBasicBlock::reverse_iterator II = BarrierMBB->rbegin(), + EE = BarrierMBB->rend(); II != EE; ++II) { + Barrier = &*II; + const TargetRegisterClass **BarrierRCs = + Barrier->getDesc().getRegClassBarriers(); + if (!BarrierRCs) + continue; + BarrierIdx = LIs->getInstructionIndex(Barrier); + MadeChange |= SplitRegLiveIntervals(BarrierRCs); + } + } + + return MadeChange; } diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index ede387e7b79..c382a4a33fb 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/lib/CodeGen/RegAllocLinearScan.cpp @@ -49,6 +49,11 @@ NewHeuristic("new-spilling-heuristic", cl::desc("Use new spilling heuristic"), cl::init(false), cl::Hidden); +static cl::opt +PreSplitIntervals("pre-alloc-split", + cl::desc("Pre-register allocation live interval splitting"), + cl::init(false), cl::Hidden); + static RegisterRegAlloc linearscanRegAlloc("linearscan", "linear scan register allocator", createLinearScanRegisterAllocator); @@ -113,6 +118,8 @@ namespace { // Make sure PassManager knows which analyses to make available // to coalescing and which analyses coalescing invalidates. AU.addRequiredTransitive(); + if (PreSplitIntervals) + AU.addRequiredID(PreAllocSplittingID); AU.addRequired(); AU.addPreserved(); AU.addRequired();