aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms/Scalar/IndVarSimplify.cpp
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2010-04-12 21:13:43 +0000
committerDan Gohman <gohman@apple.com>2010-04-12 21:13:43 +0000
commitca9b7037e28759c200fe5ca98190cabd121a1bba (patch)
tree87d9cc525f270334d68ab1c057c8cba7b5cc8e81 /lib/Transforms/Scalar/IndVarSimplify.cpp
parentdae9efc23e959d4452f5b67706896ea292b687f3 (diff)
downloadexternal_llvm-ca9b7037e28759c200fe5ca98190cabd121a1bba.tar.gz
external_llvm-ca9b7037e28759c200fe5ca98190cabd121a1bba.tar.bz2
external_llvm-ca9b7037e28759c200fe5ca98190cabd121a1bba.zip
Suppress LinearFunctionTestReplace when the computed backedge-taken
expression is a UDiv and it doesn't appear that the UDiv came from the user's source. ScalarEvolution has recently figured out how to compute a tripcount expression for the inner loop in SingleSource/Benchmarks/Shootout/sieve.c, using a udiv. Emitting a udiv instruction dramatically slows down the enclosing loop. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@101068 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Scalar/IndVarSimplify.cpp')
-rw-r--r--lib/Transforms/Scalar/IndVarSimplify.cpp18
1 files changed, 18 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/IndVarSimplify.cpp b/lib/Transforms/Scalar/IndVarSimplify.cpp
index 4f779050d9..2693f3a9a9 100644
--- a/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -134,6 +134,24 @@ ICmpInst *IndVarSimplify::LinearFunctionTestReplace(Loop *L,
BasicBlock *ExitingBlock,
BranchInst *BI,
SCEVExpander &Rewriter) {
+ // Special case: If the backedge-taken count is a UDiv, it's very likely a
+ // UDiv that ScalarEvolution produced in order to compute a precise
+ // expression, rather than a UDiv from the user's code. If we can't find a
+ // UDiv in the code with some simple searching, assume the former and forego
+ // rewriting the loop.
+ if (isa<SCEVUDivExpr>(BackedgeTakenCount)) {
+ ICmpInst *OrigCond = dyn_cast<ICmpInst>(BI->getCondition());
+ if (!OrigCond) return 0;
+ const SCEV *R = SE->getSCEV(OrigCond->getOperand(1));
+ R = SE->getMinusSCEV(R, SE->getIntegerSCEV(1, R->getType()));
+ if (R != BackedgeTakenCount) {
+ const SCEV *L = SE->getSCEV(OrigCond->getOperand(0));
+ L = SE->getMinusSCEV(L, SE->getIntegerSCEV(1, L->getType()));
+ if (L != BackedgeTakenCount)
+ return 0;
+ }
+ }
+
// If the exiting block is not the same as the backedge block, we must compare
// against the preincremented value, otherwise we prefer to compare against
// the post-incremented value.