From fb7f64ea0d6eb8594d91550c39423135abb05bb9 Mon Sep 17 00:00:00 2001 From: Owen Anderson Date: Wed, 4 Mar 2009 08:52:31 +0000 Subject: [PATCH] Add a restore folder, which shaves a dozen or so machineinstrs off oggenc. Update a testcase to check this. llvm-svn: 66029 --- lib/CodeGen/PreAllocSplitting.cpp | 81 ++++++++++++++++++++++++++++--- test/CodeGen/X86/pre-split6.ll | 2 +- 2 files changed, 76 insertions(+), 7 deletions(-) diff --git a/lib/CodeGen/PreAllocSplitting.cpp b/lib/CodeGen/PreAllocSplitting.cpp index 9e955bd6969..f08bc20d954 100644 --- a/lib/CodeGen/PreAllocSplitting.cpp +++ b/lib/CodeGen/PreAllocSplitting.cpp @@ -159,6 +159,12 @@ namespace { MachineBasicBlock* MBB, int& SS, SmallPtrSet& RefsInMBB); + MachineInstr* FoldRestore(unsigned vreg, + const TargetRegisterClass* RC, + MachineInstr* Barrier, + MachineBasicBlock* MBB, + int SS, + SmallPtrSet& RefsInMBB); void RenumberValno(VNInfo* VN); void ReconstructLiveInterval(LiveInterval* LI); bool removeDeadSpills(SmallPtrSet& split); @@ -1001,6 +1007,59 @@ MachineInstr* PreAllocSplitting::FoldSpill(unsigned vreg, return FMI; } +MachineInstr* PreAllocSplitting::FoldRestore(unsigned vreg, + const TargetRegisterClass* RC, + MachineInstr* Barrier, + MachineBasicBlock* MBB, + int SS, + SmallPtrSet& RefsInMBB) { + // Go top down if RefsInMBB is empty. + if (RefsInMBB.empty()) + return 0; + + // Can't fold a restore between a call stack setup and teardown. + MachineBasicBlock::iterator FoldPt = Barrier; + while (FoldPt != MBB->getFirstTerminator() && !RefsInMBB.count(FoldPt)) { + ++FoldPt; + + if (FoldPt->getOpcode() == TRI->getCallFrameSetupOpcode()) { + while (FoldPt != MBB->getFirstTerminator() && + FoldPt->getOpcode() != TRI->getCallFrameDestroyOpcode()) { + if (RefsInMBB.count(FoldPt)) + return 0; + + ++FoldPt; + } + + ++FoldPt; + } + } + + if (FoldPt == MBB->getFirstTerminator()) + return 0; + + int OpIdx = FoldPt->findRegisterUseOperandIdx(vreg, true); + if (OpIdx == -1) + return 0; + + SmallVector Ops; + Ops.push_back(OpIdx); + + if (!TII->canFoldMemoryOperand(FoldPt, Ops)) + return 0; + + MachineInstr* FMI = TII->foldMemoryOperand(*MBB->getParent(), + FoldPt, Ops, SS); + + if (FMI) { + LIs->ReplaceMachineInstrInMaps(FoldPt, FMI); + FMI = MBB->insert(MBB->erase(FoldPt), FMI); + ++NumFolds; + } + + return FMI; +} + /// 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. @@ -1108,18 +1167,28 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) { Def2SpillMap[ValNo->def] = SpillIndex; // Add restore. - TII->loadRegFromStackSlot(*BarrierMBB, RestorePt, CurrLI->reg, SS, RC); - MachineInstr *LoadMI = prior(RestorePt); - LIs->InsertMachineInstrInMaps(LoadMI, RestoreIndex); + bool FoldedRestore = false; + if (MachineInstr* LMI = FoldRestore(CurrLI->reg, RC, Barrier, + BarrierMBB, SS, RefsInMBB)) { + RestorePt = LMI; + FoldedRestore = true; + } else { + TII->loadRegFromStackSlot(*BarrierMBB, RestorePt, CurrLI->reg, SS, RC); + MachineInstr *LoadMI = prior(RestorePt); + LIs->InsertMachineInstrInMaps(LoadMI, RestoreIndex); + } // Update spill stack slot live interval. UpdateSpillSlotInterval(ValNo, LIs->getUseIndex(SpillIndex)+1, LIs->getDefIndex(RestoreIndex)); ReconstructLiveInterval(CurrLI); - unsigned RestoreIdx = LIs->getInstructionIndex(prior(RestorePt)); - RestoreIdx = LiveIntervals::getDefIndex(RestoreIdx); - RenumberValno(CurrLI->findDefinedVNInfo(RestoreIdx)); + + if (!FoldedRestore) { + unsigned RestoreIdx = LIs->getInstructionIndex(prior(RestorePt)); + RestoreIdx = LiveIntervals::getDefIndex(RestoreIdx); + RenumberValno(CurrLI->findDefinedVNInfo(RestoreIdx)); + } ++NumSplits; return true; diff --git a/test/CodeGen/X86/pre-split6.ll b/test/CodeGen/X86/pre-split6.ll index c075b2a39e7..780822372f6 100644 --- a/test/CodeGen/X86/pre-split6.ll +++ b/test/CodeGen/X86/pre-split6.ll @@ -1,4 +1,4 @@ -; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -pre-alloc-split +; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -pre-alloc-split | grep {divsd 8} | count 1 @current_surfaces.b = external global i1 ; [#uses=1]