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
This commit is contained in:
Sanjoy Das 2015-02-18 00:43:19 +00:00
parent e5c0c14213
commit 102061a494
1 changed files with 7 additions and 7 deletions

View File

@ -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");