summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSanjoy Das <sanjoy@playingwithpointers.com>2015-02-18 00:43:19 +0000
committerSanjoy Das <sanjoy@playingwithpointers.com>2015-02-18 00:43:19 +0000
commit102061a4947c9a07db3b874ffe26724d6fd43683 (patch)
treec3b2650bf690a42f4372dbb3f7b3805e69f41df6
parente5c0c14213b984c8b27c593a28b29136f626ad96 (diff)
downloadbcm5719-llvm-102061a4947c9a07db3b874ffe26724d6fd43683.tar.gz
bcm5719-llvm-102061a4947c9a07db3b874ffe26724d6fd43683.zip
Bugfix: SCEV incorrectly marks certain expressions as nsw
I could not come up with a test case for this one; but I don't think `getPreStartForSignExtend` can assume `AR` is `nsw` -- there is one place in scalar evolution that calls `getSignExtendAddRecStart(AR, ...)` without proving that `AR` is `nsw` (line 1564) OperandExtendedAdd = getAddExpr(WideStart, getMulExpr(WideMaxBECount, getZeroExtendExpr(Step, WideTy))); if (SAdd == OperandExtendedAdd) { // If AR wraps around then // // abs(Step) * MaxBECount > unsigned-max(AR->getType()) // => SAdd != OperandExtendedAdd // // Thus (AR is not NW => SAdd != OperandExtendedAdd) <=> // (SAdd == OperandExtendedAdd => AR is NW) const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(SCEV::FlagNW); // Return the expression with the addrec on the outside. return getAddRecExpr(getSignExtendAddRecStart(AR, Ty, this), getZeroExtendExpr(Step, Ty), L, AR->getNoWrapFlags()); } Differential Revision: http://reviews.llvm.org/D7640 llvm-svn: 229594
-rw-r--r--llvm/lib/Analysis/ScalarEvolution.cpp14
1 files changed, 7 insertions, 7 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 6edd8621ab3..2ff254394a3 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -1327,12 +1327,12 @@ static const SCEV *getOverflowLimitForStep(const SCEV *Step,
return nullptr;
}
-// The recurrence AR has been shown to have no signed wrap. Typically, if we can
-// prove NSW for AR, then we can just as easily prove NSW for its preincrement
-// or postincrement sibling. This allows normalizing a sign extended AddRec as
-// such: {sext(Step + Start),+,Step} => {(Step + sext(Start),+,Step} As a
-// result, the expression "Step + sext(PreIncAR)" is congruent with
-// "sext(PostIncAR)"
+// The recurrence AR has been shown to have no signed wrap or something close to
+// it. Typically, if we can prove NSW for AR, then we can just as easily prove
+// NSW for its preincrement or postincrement sibling. This allows normalizing a
+// sign extended AddRec as such: {sext(Step + Start),+,Step} => {(Step +
+// sext(Start),+,Step} As a result, the expression "Step + sext(PreIncAR)" is
+// congruent with "sext(PostIncAR)"
static const SCEV *getPreStartForSignExtend(const SCEVAddRecExpr *AR,
Type *Ty,
ScalarEvolution *SE) {
@@ -1392,7 +1392,7 @@ static const SCEV *getPreStartForSignExtend(const SCEVAddRecExpr *AR,
SE->getSignExtendExpr(Step, WideTy));
if (SE->getSignExtendExpr(Start, WideTy) == OperandExtendedStart) {
// Cache knowledge of PreAR NSW.
- if (PreAR)
+ if (PreAR && AR->getNoWrapFlags(SCEV::FlagNSW))
const_cast<SCEVAddRecExpr *>(PreAR)->setNoWrapFlags(SCEV::FlagNSW);
// FIXME: this optimization needs a unit test
DEBUG(dbgs() << "SCEV: untested prestart overflow check\n");
OpenPOWER on IntegriCloud