From: Owen Anderson Date: Wed, 19 Nov 2008 04:28:29 +0000 (+0000) Subject: Add support for rematerialization in pre-alloc-splitting. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=75fa96bb7127f5797873cb7482ecdf6b82eeef5a;p=oota-llvm.git Add support for rematerialization in pre-alloc-splitting. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59587 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/PreAllocSplitting.cpp b/lib/CodeGen/PreAllocSplitting.cpp index 2e385c8e8ef..c207274ce2f 100644 --- a/lib/CodeGen/PreAllocSplitting.cpp +++ b/lib/CodeGen/PreAllocSplitting.cpp @@ -39,6 +39,7 @@ using namespace llvm; static cl::opt PreSplitLimit("pre-split-limit", cl::init(-1), cl::Hidden); STATISTIC(NumSplits, "Number of intervals split"); +STATISTIC(NumRemats, "Number of intervals split by rematerialization"); namespace { class VISIBILITY_HIDDEN PreAllocSplitting : public MachineFunctionPass { @@ -153,6 +154,11 @@ namespace { bool createsNewJoin(LiveRange* LR, MachineBasicBlock* DefMBB, MachineBasicBlock* BarrierMBB); + bool Rematerialize(unsigned vreg, VNInfo* ValNo, + MachineInstr* DefMI, + MachineBasicBlock::iterator RestorePt, + unsigned RestoreIdx, + SmallPtrSet& RefsInMBB); }; } // end anonymous namespace @@ -627,6 +633,90 @@ PreAllocSplitting::ShrinkWrapLiveInterval(VNInfo *ValNo, MachineBasicBlock *MBB, return; } +bool PreAllocSplitting::Rematerialize(unsigned vreg, VNInfo* ValNo, + MachineInstr* DefMI, + MachineBasicBlock::iterator RestorePt, + unsigned RestoreIdx, + SmallPtrSet& RefsInMBB) { + MachineBasicBlock& MBB = *RestorePt->getParent(); + + MachineBasicBlock::iterator KillPt = BarrierMBB->end(); + unsigned KillIdx = 0; + if (ValNo->def == ~0U || DefMI->getParent() == BarrierMBB) + KillPt = findSpillPoint(BarrierMBB, Barrier, NULL, RefsInMBB, KillIdx); + else + KillPt = findNextEmptySlot(DefMI->getParent(), DefMI, KillIdx); + + if (KillPt == DefMI->getParent()->end()) + return false; + + TII->reMaterialize(MBB, RestorePt, vreg, DefMI); + LIs->InsertMachineInstrInMaps(prior(RestorePt), RestoreIdx); + + if (KillPt->getParent() == BarrierMBB) { + UpdateRegisterInterval(ValNo, LIs->getUseIndex(KillIdx)+1, + LIs->getDefIndex(RestoreIdx)); + + ++NumSplits; + ++NumRemats; + 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; + DenseMap > UseMIs; + SmallPtrSet Seen; + SmallVector UseMBBs; + 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(); + // Remember which other mbb's use this val#. + if (Seen.insert(UseMBB) && UseMBB != BarrierMBB) + UseMBBs.push_back(UseMBB); + DenseMap >::iterator + UMII = Uses.find(UseMBB); + if (UMII != Uses.end()) { + DenseMap >::iterator + UMII2 = UseMIs.find(UseMBB); + UMII->second.push_back(&UseMO); + UMII2->second.insert(UseMI); + } else { + SmallVector Ops; + Ops.push_back(&UseMO); + Uses.insert(std::make_pair(UseMBB, Ops)); + SmallPtrSet MIs; + MIs.insert(UseMI); + UseMIs.insert(std::make_pair(UseMBB, MIs)); + } + } + + // Walk up the predecessor chains. + SmallPtrSet Visited; + ShrinkWrapLiveInterval(ValNo, BarrierMBB, NULL, DefMI->getParent(), Visited, + Uses, UseMIs, UseMBBs); + + // FIXME: If ValNo->hasPHIKill is false, then renumber the val# by + // the restore. + + // Remove live range from barrier to the restore. FIXME: Find a better + // point to re-start the live interval. + UpdateRegisterInterval(ValNo, LIs->getUseIndex(BarrierIdx)+1, + LIs->getDefIndex(RestoreIdx)); + + ++NumSplits; + ++NumRemats; + return true; + +} + /// 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. @@ -644,11 +734,8 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) { abort(); } - // FIXME: For now, if definition is rematerializable, do not split. MachineInstr *DefMI = (ValNo->def != ~0U) ? LIs->getInstructionFromIndex(ValNo->def) : NULL; - if (DefMI && LIs->isReMaterializable(*LI, ValNo, DefMI)) - return false; // If this would create a new join point, do not split. if (DefMI && createsNewJoin(LR, DefMI->getParent(), Barrier->getParent())) @@ -670,6 +757,11 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) { if (RestorePt == BarrierMBB->end()) return false; + if (DefMI && LIs->isReMaterializable(*LI, ValNo, DefMI)) + if (Rematerialize(LI->reg, ValNo, DefMI, RestorePt, + RestoreIndex, RefsInMBB)) + return true; + // Add a spill either before the barrier or after the definition. MachineBasicBlock *DefMBB = DefMI ? DefMI->getParent() : NULL; const TargetRegisterClass *RC = MRI->getRegClass(CurrLI->reg); diff --git a/test/CodeGen/X86/pre-split2.ll b/test/CodeGen/X86/pre-split2.ll index 57903fdb51c..1d69aa85442 100644 --- a/test/CodeGen/X86/pre-split2.ll +++ b/test/CodeGen/X86/pre-split2.ll @@ -1,5 +1,5 @@ ; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -pre-alloc-split -stats |& \ -; RUN: not grep {pre-alloc-split} +; RUN: grep {pre-alloc-split} | count 2 define i32 @t() { entry: