diff options
author | Andrew Trick <atrick@apple.com> | 2011-07-06 20:50:43 +0000 |
---|---|---|
committer | Andrew Trick <atrick@apple.com> | 2011-07-06 20:50:43 +0000 |
commit | 037d1c0c7e01cefeff7e538682c9a1e536e14030 (patch) | |
tree | d77b0b7bc5959c64864fefd70008d3b09678b47f | |
parent | 0392a0431eeed3b230fc14fff438066470b06599 (diff) | |
download | external_llvm-037d1c0c7e01cefeff7e538682c9a1e536e14030.zip external_llvm-037d1c0c7e01cefeff7e538682c9a1e536e14030.tar.gz external_llvm-037d1c0c7e01cefeff7e538682c9a1e536e14030.tar.bz2 |
indvars -disable-iv-rewrite: Added SimplifyCongruentIVs.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134530 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Transforms/Scalar/IndVarSimplify.cpp | 59 | ||||
-rw-r--r-- | test/Transforms/IndVarSimplify/no-iv-rewrite.ll | 50 | ||||
-rw-r--r-- | test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll | 9 |
3 files changed, 113 insertions, 5 deletions
diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp index 2b0dfc6..477f42c 100644 --- a/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -58,6 +58,7 @@ #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Target/TargetData.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/ADT/STLExtras.h" @@ -72,6 +73,7 @@ STATISTIC(NumElimIdentity, "Number of IV identities eliminated"); STATISTIC(NumElimExt , "Number of IV sign/zero extends eliminated"); STATISTIC(NumElimRem , "Number of IV remainder operations eliminated"); STATISTIC(NumElimCmp , "Number of IV comparisons eliminated"); +STATISTIC(NumElimIV , "Number of congruent IVs eliminated"); static cl::opt<bool> DisableIVRewrite( "disable-iv-rewrite", cl::Hidden, @@ -79,12 +81,15 @@ static cl::opt<bool> DisableIVRewrite( namespace { class IndVarSimplify : public LoopPass { + typedef DenseMap<const SCEV *, PHINode *> ExprToIVMapTy; + IVUsers *IU; LoopInfo *LI; ScalarEvolution *SE; DominatorTree *DT; TargetData *TD; + ExprToIVMapTy ExprToIVMap; SmallVector<WeakVH, 16> DeadInsts; bool Changed; public: @@ -114,6 +119,11 @@ namespace { } private: + virtual void releaseMemory() { + ExprToIVMap.clear(); + DeadInsts.clear(); + } + bool isValidRewrite(Value *FromVal, Value *ToVal); void SimplifyIVUsers(SCEVExpander &Rewriter); @@ -133,6 +143,8 @@ namespace { void RewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter); + void SimplifyCongruentIVs(Loop *L); + void RewriteIVExpressions(Loop *L, SCEVExpander &Rewriter); void SinkUnusedInvariants(Loop *L); @@ -1129,7 +1141,7 @@ void IndVarSimplify::SimplifyIVUsersNoRewrite(Loop *L, SCEVExpander &Rewriter) { // Instructions processed by SimplifyIVUsers for CurrIV. SmallPtrSet<Instruction*,16> Simplified; - // Use-def pairs if IVUsers waiting to be processed for CurrIV. + // Use-def pairs if IV users waiting to be processed for CurrIV. SmallVector<std::pair<Instruction*, Instruction*>, 8> SimpleIVUsers; // Push users of the current LoopPhi. In rare cases, pushIVUsers may be @@ -1175,6 +1187,45 @@ void IndVarSimplify::SimplifyIVUsersNoRewrite(Loop *L, SCEVExpander &Rewriter) { } } +/// SimplifyCongruentIVs - Check for congruent phis in this loop header and +/// populate ExprToIVMap for use later. +/// +void IndVarSimplify::SimplifyCongruentIVs(Loop *L) { + for (BasicBlock::iterator I = L->getHeader()->begin(); isa<PHINode>(I); ++I) { + PHINode *Phi = cast<PHINode>(I); + const SCEV *S = SE->getSCEV(Phi); + ExprToIVMapTy::const_iterator Pos; + bool Inserted; + tie(Pos, Inserted) = ExprToIVMap.insert(std::make_pair(S, Phi)); + if (Inserted) + continue; + PHINode *OrigPhi = Pos->second; + // Replacing the congruent phi is sufficient because acyclic redundancy + // elimination, CSE/GVN, should handle the rest. However, once SCEV proves + // that a phi is congruent, it's almost certain to be the head of an IV + // user cycle that is isomorphic with the original phi. So it's worth + // eagerly cleaning up the common case of a single IV increment. + if (BasicBlock *LatchBlock = L->getLoopLatch()) { + Instruction *OrigInc = + cast<Instruction>(OrigPhi->getIncomingValueForBlock(LatchBlock)); + Instruction *IsomorphicInc = + cast<Instruction>(Phi->getIncomingValueForBlock(LatchBlock)); + if (OrigInc != IsomorphicInc && + SE->getSCEV(OrigInc) == SE->getSCEV(IsomorphicInc) && + HoistStep(OrigInc, IsomorphicInc, DT)) { + DEBUG(dbgs() << "INDVARS: Eliminated congruent iv.inc: " + << *IsomorphicInc << '\n'); + IsomorphicInc->replaceAllUsesWith(OrigInc); + DeadInsts.push_back(IsomorphicInc); + } + } + DEBUG(dbgs() << "INDVARS: Eliminated congruent iv: " << *Phi << '\n'); + ++NumElimIV; + Phi->replaceAllUsesWith(OrigPhi); + DeadInsts.push_back(Phi); + } +} + bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { // If LoopSimplify form is not available, stay out of trouble. Some notes: // - LSR currently only supports LoopSimplify-form loops. Indvars' @@ -1194,6 +1245,7 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { DT = &getAnalysis<DominatorTree>(); TD = getAnalysisIfAvailable<TargetData>(); + ExprToIVMap.clear(); DeadInsts.clear(); Changed = false; @@ -1230,6 +1282,11 @@ bool IndVarSimplify::runOnLoop(Loop *L, LPPassManager &LPM) { if (!DisableIVRewrite) SimplifyIVUsers(Rewriter); + // Eliminate redundant IV cycles and populate ExprToIVMap. + // TODO: use ExprToIVMap to allow LFTR without canonical IVs + if (DisableIVRewrite) + SimplifyCongruentIVs(L); + // Compute the type of the largest recurrence expression, and decide whether // a canonical induction variable should be inserted. const Type *LargestType = 0; diff --git a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll index 639eb1d..9605670 100644 --- a/test/Transforms/IndVarSimplify/no-iv-rewrite.ll +++ b/test/Transforms/IndVarSimplify/no-iv-rewrite.ll @@ -270,3 +270,53 @@ cond_true: return: ret i32 %i.0 } + +; Eliminate the congruent phis j, k, and l. +; Eliminate the redundant IV increments k.next and l.next. +; Two phis should remain, one starting at %init, and one at %init1. +; Two increments should remain, one by %step and one by %step1. +; CHECK: loop: +; CHECK: phi i32 +; CHECK: phi i32 +; CHECK-NOT: phi +; CHECK: add i32 +; CHECK: add i32 +; CHECK-NOT: add +; CHECK: return: +; +; Five live-outs should remain. +; CHECK: lcssa = phi +; CHECK: lcssa = phi +; CHECK: lcssa = phi +; CHECK: lcssa = phi +; CHECK: lcssa = phi +; CHECK-NOT: phi +; CHECK: ret +define i32 @isomorphic(i32 %init, i32 %step, i32 %lim) nounwind { +entry: + %step1 = add i32 %step, 1 + %init1 = add i32 %init, %step1 + %l.0 = sub i32 %init1, %step1 + br label %loop + +loop: + %ii = phi i32 [ %init1, %entry ], [ %ii.next, %loop ] + %i = phi i32 [ %init, %entry ], [ %ii, %loop ] + %j = phi i32 [ %init, %entry ], [ %j.next, %loop ] + %k = phi i32 [ %init1, %entry ], [ %k.next, %loop ] + %l = phi i32 [ %l.0, %entry ], [ %l.next, %loop ] + %ii.next = add i32 %ii, %step1 + %j.next = add i32 %j, %step1 + %k.next = add i32 %k, %step1 + %l.step = add i32 %l, %step + %l.next = add i32 %l.step, 1 + %cmp = icmp ne i32 %ii.next, %lim + br i1 %cmp, label %loop, label %return + +return: + %sum1 = add i32 %i, %j.next + %sum2 = add i32 %sum1, %k.next + %sum3 = add i32 %sum1, %l.step + %sum4 = add i32 %sum1, %l.next + ret i32 %sum4 +} diff --git a/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll b/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll index 0c8857f..ace74ff 100644 --- a/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll +++ b/test/Transforms/IndVarSimplify/variable-stride-ivs-0.ll @@ -1,9 +1,9 @@ -; RUN: opt < %s -indvars -instcombine -S | \ -; RUN: grep {store i32 0} +; RUN: opt < %s -indvars -instcombine -S | FileCheck %s +; RUN: opt < %s -indvars -disable-iv-rewrite -instcombine -S | FileCheck %s +; ; Test that -indvars can reduce variable stride IVs. If it can reduce variable -; stride iv's, it will make %iv. and %m.0.0 isomorphic to each other without +; stride iv's, it will make %iv. and %m.0.0 isomorphic to each other without ; cycles, allowing the tmp.21 subtraction to be eliminated. -; END. define void @vnum_test8(i32* %data) { entry: @@ -20,6 +20,7 @@ no_exit.preheader: ; preds = %entry %tmp.16 = getelementptr i32* %data, i32 %tmp.9 ; <i32*> [#uses=1] br label %no_exit +; CHECK: store i32 0 no_exit: ; preds = %no_exit, %no_exit.preheader %iv.ui = phi i32 [ 0, %no_exit.preheader ], [ %iv..inc.ui, %no_exit ] ; <i32> [#uses=1] %iv. = phi i32 [ %tmp.5, %no_exit.preheader ], [ %iv..inc, %no_exit ] ; <i32> [#uses=2] |