summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-09-03 23:03:18 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-09-03 23:03:18 +0000
commitc6ab01eccae05aee4bae81a875a6eb88907247c5 (patch)
treebd4c16b8d55d58e1697cf55275b6c8d167790348 /llvm/lib/Transforms
parentfb5d6852c6038455dca4da196558803005ced0d1 (diff)
downloadbcm5719-llvm-c6ab01eccae05aee4bae81a875a6eb88907247c5.tar.gz
bcm5719-llvm-c6ab01eccae05aee4bae81a875a6eb88907247c5.zip
IndVarSimplify: Don't let LFTR compare against a poison value
LinearFunctionTestReplace tries to use the *next* indvar to compare against when possible. However, it may be the case that the calculation for the next indvar has NUW/NSW flags and that it may only be safely used inside the loop. Using it in a comparison to calculate the exit condition could result in observing poison. This fixes PR20680. Differential Revision: http://reviews.llvm.org/D5174 llvm-svn: 217102
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/Scalar/IndVarSimplify.cpp24
1 files changed, 18 insertions, 6 deletions
diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
index 0d97b461c5c..a5f0dae87ea 100644
--- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
+++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
@@ -1641,15 +1641,27 @@ LinearFunctionTestReplace(Loop *L,
// compare against the post-incremented value, otherwise we must compare
// against the preincremented value.
if (L->getExitingBlock() == L->getLoopLatch()) {
- // Add one to the "backedge-taken" count to get the trip count.
- // This addition may overflow, which is valid as long as the comparison is
- // truncated to BackedgeTakenCount->getType().
- IVCount = SE->getAddExpr(BackedgeTakenCount,
- SE->getConstant(BackedgeTakenCount->getType(), 1));
// The BackedgeTaken expression contains the number of times that the
// backedge branches to the loop header. This is one less than the
// number of times the loop executes, so use the incremented indvar.
- CmpIndVar = IndVar->getIncomingValueForBlock(L->getExitingBlock());
+ llvm::Value *IncrementedIndvar = IndVar->getIncomingValueForBlock(L->getExitingBlock());
+ const auto *IncrementedIndvarSCEV =
+ cast<SCEVAddRecExpr>(SE->getSCEV(IncrementedIndvar));
+ // It is unsafe to use the incremented indvar if it has a wrapping flag, we
+ // don't want to compare against a poison value. Check the SCEV that
+ // corresponds to the incremented indvar, the SCEVExpander will only insert
+ // flags in the IR if the SCEV originally had wrapping flags.
+ if (ScalarEvolution::maskFlags(IncrementedIndvarSCEV->getNoWrapFlags(),
+ SCEV::FlagNUW | SCEV::FlagNSW) ==
+ SCEV::FlagAnyWrap) {
+ // Add one to the "backedge-taken" count to get the trip count.
+ // This addition may overflow, which is valid as long as the comparison is
+ // truncated to BackedgeTakenCount->getType().
+ IVCount =
+ SE->getAddExpr(BackedgeTakenCount,
+ SE->getConstant(BackedgeTakenCount->getType(), 1));
+ CmpIndVar = IncrementedIndvar;
+ }
}
Value *ExitCnt = genLoopLimit(IndVar, IVCount, L, Rewriter, SE);
OpenPOWER on IntegriCloud