summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
diff options
context:
space:
mode:
authorSanjoy Das <sanjoy@playingwithpointers.com>2015-07-09 18:46:12 +0000
committerSanjoy Das <sanjoy@playingwithpointers.com>2015-07-09 18:46:12 +0000
commit6f062c8c2a3de7140341dbe03af80ae840c91492 (patch)
treee143c871b302e9fc25d37b3db094576f09ee5773 /llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
parent1bd3c9abd8984544380f3ea48d343790dcee0263 (diff)
downloadbcm5719-llvm-6f062c8c2a3de7140341dbe03af80ae840c91492.tar.gz
bcm5719-llvm-6f062c8c2a3de7140341dbe03af80ae840c91492.zip
[IndVars] Try to use existing values in RewriteLoopExitValues.
Summary: In RewriteLoopExitValues, before expanding out an SCEV expression using SCEVExpander, try to see if an existing LLVM IR expression already computes the value we're interested in. If so use that existing expression. Apart from reducing IndVars' reliance on the rest of the compilation pipeline, this also prevents IndVars from concluding some expressions as "high cost" when they're not. For instance, `InductiveRangeCheckElimination` often emits code of the following form: ``` len = umin(len_A, len_B) loop: ... if (i++ < len) goto loop outside_loop: use(i) ``` `SCEVExpander` refuses to rewrite the use of `i` in `outside_loop`, since it thinks the value of `i` on loop exit, `len`, is a high cost expansion since it contains an `umax` in it. With this change, `IndVars` can see that it can re-use `len` instead of creating a new expression to compute `umin(len_A, len_B)`. I considered putting this cleverness in `SCEVExpander`, but I was worried that it may then have a deterimental effect on other passes that use it. So I decided it was better to just do this in the one place where it seems like an obviously good idea, with the intent of generalizing later if needed. Reviewers: atrick, reames Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D10782 llvm-svn: 241838
Diffstat (limited to 'llvm/lib/Transforms/Scalar/IndVarSimplify.cpp')
-rw-r--r--llvm/lib/Transforms/Scalar/IndVarSimplify.cpp56
1 files changed, 54 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
index 6f0375487af..2a954d9961f 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -41,6 +41,7 @@
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/PatternMatch.h"
#include "llvm/IR/Type.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
@@ -135,6 +136,10 @@ namespace {
PHINode *IndVar, SCEVExpander &Rewriter);
void SinkUnusedInvariants(Loop *L);
+
+ Value *ExpandSCEVIfNeeded(SCEVExpander &Rewriter, const SCEV *S, Loop *L,
+ Instruction *InsertPt, Type *Ty,
+ bool &IsHighCostExpansion);
};
}
@@ -496,6 +501,52 @@ struct RewritePhi {
};
}
+Value *IndVarSimplify::ExpandSCEVIfNeeded(SCEVExpander &Rewriter, const SCEV *S,
+ Loop *L, Instruction *InsertPt,
+ Type *ResultTy,
+ bool &IsHighCostExpansion) {
+ using namespace llvm::PatternMatch;
+
+ if (!Rewriter.isHighCostExpansion(S, L)) {
+ IsHighCostExpansion = false;
+ return Rewriter.expandCodeFor(S, ResultTy, InsertPt);
+ }
+
+ // Before expanding S into an expensive LLVM expression, see if we can use an
+ // already existing value as the expansion for S. There is potential to make
+ // this significantly smarter, but this simple heuristic already gets some
+ // interesting cases.
+
+ SmallVector<BasicBlock *, 4> Latches;
+ L->getLoopLatches(Latches);
+
+ for (BasicBlock *BB : Latches) {
+ ICmpInst::Predicate Pred;
+ Instruction *LHS, *RHS;
+ BasicBlock *TrueBB, *FalseBB;
+
+ if (!match(BB->getTerminator(),
+ m_Br(m_ICmp(Pred, m_Instruction(LHS), m_Instruction(RHS)),
+ TrueBB, FalseBB)))
+ continue;
+
+ if (SE->getSCEV(LHS) == S && DT->dominates(LHS, InsertPt)) {
+ IsHighCostExpansion = false;
+ return LHS;
+ }
+
+ if (SE->getSCEV(RHS) == S && DT->dominates(RHS, InsertPt)) {
+ IsHighCostExpansion = false;
+ return RHS;
+ }
+ }
+
+ // We didn't find anything, fall back to using SCEVExpander.
+ assert(Rewriter.isHighCostExpansion(S, L) && "this should not have changed!");
+ IsHighCostExpansion = true;
+ return Rewriter.expandCodeFor(S, ResultTy, InsertPt);
+}
+
//===----------------------------------------------------------------------===//
// RewriteLoopExitValues - Optimize IV users outside the loop.
// As a side effect, reduces the amount of IV processing within the loop.
@@ -628,7 +679,9 @@ void IndVarSimplify::RewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter) {
continue;
}
- Value *ExitVal = Rewriter.expandCodeFor(ExitValue, PN->getType(), Inst);
+ bool HighCost = false;
+ Value *ExitVal = ExpandSCEVIfNeeded(Rewriter, ExitValue, L, Inst,
+ PN->getType(), HighCost);
DEBUG(dbgs() << "INDVARS: RLEV: AfterLoopVal = " << *ExitVal << '\n'
<< " LoopVal = " << *Inst << "\n");
@@ -637,7 +690,6 @@ void IndVarSimplify::RewriteLoopExitValues(Loop *L, SCEVExpander &Rewriter) {
DeadInsts.push_back(ExitVal);
continue;
}
- bool HighCost = Rewriter.isHighCostExpansion(ExitValue, L);
// Collect all the candidate PHINodes to be rewritten.
RewritePhiSet.push_back(
OpenPOWER on IntegriCloud