[llvm-commits] CVS: llvm/lib/Transforms/Scalar/LoopUnswitch.cpp
Chris Lattner
lattner at cs.uiuc.edu
Thu Feb 9 11:15:04 PST 2006
Changes in directory llvm/lib/Transforms/Scalar:
LoopUnswitch.cpp updated: 1.6 -> 1.7
---
Log message:
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.
---
Diffs of the changes: (+74 -86)
LoopUnswitch.cpp | 160 +++++++++++++++++++++++++------------------------------
1 files changed, 74 insertions(+), 86 deletions(-)
Index: llvm/lib/Transforms/Scalar/LoopUnswitch.cpp
diff -u llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:1.6 llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:1.7
--- llvm/lib/Transforms/Scalar/LoopUnswitch.cpp:1.6 Sun Jan 22 17:32:06 2006
+++ llvm/lib/Transforms/Scalar/LoopUnswitch.cpp Thu Feb 9 13:14:52 2006
@@ -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 <algorithm>
#include <iostream>
+#include <set>
using namespace llvm;
namespace {
@@ -46,7 +46,6 @@
class LoopUnswitch : public FunctionPass {
LoopInfo *LI; // Loop information
- DominatorSet *DS;
public:
virtual bool runOnFunction(Function &F);
bool visitLoop(Loop *L);
@@ -56,7 +55,6 @@
///
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.addRequiredID(LoopSimplifyID);
- //AU.addRequired<DominatorSet>();
AU.addRequired<LoopInfo>();
AU.addPreserved<LoopInfo>();
}
@@ -74,7 +72,6 @@
bool LoopUnswitch::runOnFunction(Function &F) {
bool Changed = false;
LI = &getAnalysis<LoopInfo>();
- DS = 0; //&getAnalysis<DominatorSet>();
// 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 @@
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<BasicBlock*> 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<Instruction>(*UI)->getParent();
+ if (!LoopBlocks.count(UserBB))
+ return true;
+ }
+ }
+ return false;
+}
+
bool LoopUnswitch::visitLoop(Loop *L) {
bool Changed = false;
@@ -103,27 +130,50 @@
TerminatorInst *TI = (*I)->getTerminator();
if (SwitchInst *SI = dyn_cast<SwitchInst>(TI)) {
if (!isa<Constant>(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<BranchInst>(TI))
- if (BI->isConditional() && !isa<Constant>(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<BranchInst>(TI);
+ if (!BI) continue;
+
+ // If this isn't branching on an invariant condition, we can't unswitch it.
+ if (!BI->isConditional() || isa<Constant>(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 @@
}
-/// 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<BasicBlock*> &OldExitBlocks,
- std::map<const Value*, Value*> &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<Instruction>(*UI)->getParent()) &&
- !NL->contains(cast<Instruction>(*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<InvokeInst>(NI))
- InsertPoint = II->getNormalDest()->begin();
- else
- ++InsertPoint;
- while (isa<PHINode>(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 @@
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<const Value*,Value*>::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<Instruction>(OII->second);
- InsertPHINodesForUsesOutsideLoop(OI, NI, *DS, L, NewLoop,
- ExitBlocks, ValueMap);
- }
- }
-
+
// Rewrite the original preheader to select between versions of the loop.
assert(isa<BranchInst>(OrigPreheader->getTerminator()) &&
cast<BranchInst>(OrigPreheader->getTerminator())->isUnconditional() &&
More information about the llvm-commits
mailing list