From 2f4b898e8cecbc8d94d877834a210827312e4671 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 9 Feb 2006 19:14:52 +0000 Subject: [PATCH] Simplify the loop-unswitch pass, by not even trying to unswitch loops with uses of loop values outside the loop. We need loop-closed SSA form to do this right, or to use SSA rewriting if we really care. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26089 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Scalar/LoopUnswitch.cpp | 160 ++++++++++++------------- 1 file changed, 74 insertions(+), 86 deletions(-) diff --git a/lib/Transforms/Scalar/LoopUnswitch.cpp b/lib/Transforms/Scalar/LoopUnswitch.cpp index 66e386e5a62..3cdfd473815 100644 --- a/lib/Transforms/Scalar/LoopUnswitch.cpp +++ b/lib/Transforms/Scalar/LoopUnswitch.cpp @@ -31,7 +31,6 @@ #include "llvm/Constants.h" #include "llvm/Function.h" #include "llvm/Instructions.h" -#include "llvm/Analysis/Dominators.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/Local.h" @@ -39,6 +38,7 @@ #include "llvm/ADT/Statistic.h" #include #include +#include using namespace llvm; namespace { @@ -46,7 +46,6 @@ namespace { class LoopUnswitch : public FunctionPass { LoopInfo *LI; // Loop information - DominatorSet *DS; public: virtual bool runOnFunction(Function &F); bool visitLoop(Loop *L); @@ -56,7 +55,6 @@ namespace { /// virtual void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequiredID(LoopSimplifyID); - //AU.addRequired(); AU.addRequired(); AU.addPreserved(); } @@ -74,7 +72,6 @@ FunctionPass *llvm::createLoopUnswitchPass() { return new LoopUnswitch(); } bool LoopUnswitch::runOnFunction(Function &F) { bool Changed = false; LI = &getAnalysis(); - DS = 0; //&getAnalysis(); // Transform all the top-level loops. Copy the loop list so that the child // can update the loop tree if it needs to delete the loop. @@ -85,6 +82,36 @@ bool LoopUnswitch::runOnFunction(Function &F) { return Changed; } + +/// InsertPHINodesForUsesOutsideLoop - If this instruction is used outside of +/// the specified loop, insert a PHI node in the appropriate exit block to merge +/// the values in the two different loop versions. +/// +/// Most values are not used outside of the loop they are defined in, so be +/// efficient for this case. +/// +static bool LoopValuesUsedOutsideLoop(Loop *L) { + // We will be doing lots of "loop contains block" queries. Loop::contains is + // linear time, use a set to speed this up. + std::set LoopBlocks; + + for (Loop::block_iterator BB = L->block_begin(), E = L->block_end(); + BB != E; ++BB) + LoopBlocks.insert(*BB); + + for (Loop::block_iterator BB = L->block_begin(), E = L->block_end(); + BB != E; ++BB) { + for (BasicBlock::iterator I = (*BB)->begin(), E = (*BB)->end(); I != E; ++I) + for (Value::use_iterator UI = I->use_begin(), E = I->use_end(); UI != E; + ++UI) { + BasicBlock *UserBB = cast(*UI)->getParent(); + if (!LoopBlocks.count(UserBB)) + return true; + } + } + return false; +} + bool LoopUnswitch::visitLoop(Loop *L) { bool Changed = false; @@ -103,27 +130,50 @@ bool LoopUnswitch::visitLoop(Loop *L) { TerminatorInst *TI = (*I)->getTerminator(); if (SwitchInst *SI = dyn_cast(TI)) { if (!isa(SI) && L->isLoopInvariant(SI->getCondition())) - DEBUG(std::cerr << "Can't unswitching 'switch' loop %" + DEBUG(std::cerr << "TODO: Implement unswitching 'switch' loop %" << L->getHeader()->getName() << ", cost = " << L->getBlocks().size() << "\n" << **I); - } else if (BranchInst *BI = dyn_cast(TI)) - if (BI->isConditional() && !isa(BI->getCondition()) && - L->isLoopInvariant(BI->getCondition())) { - // Check to see if it would be profitable to unswitch this loop. - if (L->getBlocks().size() > 10) { - DEBUG(std::cerr << "NOT unswitching loop %" - << L->getHeader()->getName() << ", cost too high: " - << L->getBlocks().size() << "\n"); - } else { - // FIXME: check for profitability. - //std::cerr << "BEFORE:\n"; LI->dump(); - - VersionLoop(BI->getCondition(), L); - - //std::cerr << "AFTER:\n"; LI->dump(); - return true; - } - } + continue; + } + + BranchInst *BI = dyn_cast(TI); + if (!BI) continue; + + // If this isn't branching on an invariant condition, we can't unswitch it. + if (!BI->isConditional() || isa(BI->getCondition()) || + !L->isLoopInvariant(BI->getCondition())) + continue; + + // Check to see if it would be profitable to unswitch this loop. + if (L->getBlocks().size() > 10) { + // FIXME: this should estimate growth by the amount of code shared by the + // resultant unswitched loops. This should have no code growth: + // for () { if (iv) {...} } + // as one copy of the loop will be empty. + // + DEBUG(std::cerr << "NOT unswitching loop %" + << L->getHeader()->getName() << ", cost too high: " + << L->getBlocks().size() << "\n"); + continue; + } + + // If this loop has live-out values, we can't unswitch it. We need something + // like loop-closed SSA form in order to know how to insert PHI nodes for + // these values. + if (LoopValuesUsedOutsideLoop(L)) { + DEBUG(std::cerr << "NOT unswitching loop %" + << L->getHeader()->getName() + << ", a loop value is used outside loop!\n"); + continue; + } + + //std::cerr << "BEFORE:\n"; LI->dump(); + VersionLoop(BI->getCondition(), L); + //std::cerr << "AFTER:\n"; LI->dump(); + + // FIXME: Why return here? What if we have: + // "for () { if (iv1) { if (iv2) { } } }" ? + return true; } return Changed; @@ -191,52 +241,6 @@ static Loop *CloneLoop(Loop *L, Loop *PL, std::map &VM, } -/// InsertPHINodesForUsesOutsideLoop - If this instruction is used outside of -/// the specified loop, insert a PHI node in the appropriate exit block to merge -/// the values in the two different loop versions. -/// -/// Most values are not used outside of the loop they are defined in, so be -/// efficient for this case. -/// -static AllocaInst * -InsertPHINodesForUsesOutsideLoop(Instruction *OI, Instruction *NI, - DominatorSet &DS, Loop *OL, Loop *NL, - std::vector &OldExitBlocks, - std::map &ValueMap) { - assert(OI->getType() == NI->getType() && OI->getOpcode() == NI->getOpcode() && - "Hrm, should be mapping between identical instructions!"); - for (Value::use_iterator UI = OI->use_begin(), E = OI->use_end(); UI != E; - ++UI) - if (!OL->contains(cast(*UI)->getParent()) && - !NL->contains(cast(*UI)->getParent())) - goto UsedOutsideOfLoop; - return 0; - -UsedOutsideOfLoop: - // Okay, this instruction is used outside of the current loop. Insert a PHI - // nodes for the instruction merging the values together. - - // FIXME: For now we just spill the object to the stack, assuming that a - // subsequent mem2reg pass will clean up after us. This should be improved in - // two ways: - // 1. If there is only one exit block, trivially insert the PHI nodes - // 2. Once we update domfrontier, we should do the promotion after everything - // is stable again. - AllocaInst *Result = DemoteRegToStack(*OI); - - // Store to the stack location right after the new instruction. - BasicBlock::iterator InsertPoint = NI; - if (InvokeInst *II = dyn_cast(NI)) - InsertPoint = II->getNormalDest()->begin(); - else - ++InsertPoint; - while (isa(InsertPoint)) ++InsertPoint; - new StoreInst(NI, Result, InsertPoint); - return Result; -} - - - /// VersionLoop - We determined that the loop is profitable to unswitch and /// contains a branch on a loop invariant condition. Split it into loop /// versions and test the condition outside of either loop. @@ -298,23 +302,7 @@ void LoopUnswitch::VersionLoop(Value *LIC, Loop *L) { for (BasicBlock::iterator I = NewBlocks[i]->begin(), E = NewBlocks[i]->end(); I != E; ++I) RemapInstruction(I, ValueMap); - - // If the instructions are used outside of the loop, insert a PHI node in any - // exit blocks dominated by the instruction. - for (unsigned i = 0, e = NewBlocks.size(); i != e; ++i) - for (BasicBlock::iterator OI = LoopBlocks[i]->begin(), - E = LoopBlocks[i]->end(); OI != E; ++OI) - if (!OI->use_empty()) { - std::map::iterator OII = ValueMap.find(OI); - // The PHINode rewriting stuff can insert stores that are not in the - // mapping. Don't mess around with them. - if (OII != ValueMap.end()) { - Instruction *NI = cast(OII->second); - InsertPHINodesForUsesOutsideLoop(OI, NI, *DS, L, NewLoop, - ExitBlocks, ValueMap); - } - } - + // Rewrite the original preheader to select between versions of the loop. assert(isa(OrigPreheader->getTerminator()) && cast(OrigPreheader->getTerminator())->isUnconditional() &&