[llvm] r267110 - [SCEV] Extract out a `isSCEVExprNeverPoison` helper; NFCI
Sanjoy Das via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 21 22:38:54 PDT 2016
Author: sanjoy
Date: Fri Apr 22 00:38:54 2016
New Revision: 267110
URL: http://llvm.org/viewvc/llvm-project?rev=267110&view=rev
Log:
[SCEV] Extract out a `isSCEVExprNeverPoison` helper; NFCI
Summary:
Also adds a small comment blurb on control flow + no-wrap flags, since
that question came up a few days back on llvm-dev.
Reviewers: bjarke.roune, broune
Subscribers: sanjoy, mcrosier, llvm-commits, mzolotukhin
Differential Revision: http://reviews.llvm.org/D19209
Modified:
llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
llvm/trunk/lib/Analysis/ScalarEvolution.cpp
Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=267110&r1=267109&r2=267110&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Fri Apr 22 00:38:54 2016
@@ -1095,6 +1095,24 @@ namespace llvm {
// (e.g. a nuw add) would trigger undefined behavior on overflow.
SCEV::NoWrapFlags getNoWrapFlagsFromUB(const Value *V);
+ /// Return true if the SCEV corresponding to \p I is never poison. Proving
+ /// this is more complex than proving that just \p I is never poison, since
+ /// SCEV commons expressions across control flow, and you can have cases
+ /// like:
+ ///
+ /// idx0 = a + b;
+ /// ptr[idx0] = 100;
+ /// if (<condition>) {
+ /// idx1 = a +nsw b;
+ /// ptr[idx1] = 200;
+ /// }
+ ///
+ /// where the SCEV expression (+ a b) is guaranteed to not be poison (and
+ /// hence not sign-overflow) only if "<condition>" is true. Since both
+ /// `idx0` and `idx1` will be mapped to the same SCEV expression, (+ a b),
+ /// it is not okay to annotate (+ a b) with <nsw> in the above example.
+ bool isSCEVExprNeverPoison(const Instruction *I);
+
public:
ScalarEvolution(Function &F, TargetLibraryInfo &TLI, AssumptionCache &AC,
DominatorTree &DT, LoopInfo &LI);
Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=267110&r1=267109&r2=267110&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Fri Apr 22 00:38:54 2016
@@ -4767,46 +4767,58 @@ SCEV::NoWrapFlags ScalarEvolution::getNo
if (Flags == SCEV::FlagAnyWrap)
return SCEV::FlagAnyWrap;
- // Here we check that BinOp is in the header of the innermost loop
- // containing BinOp, since we only deal with instructions in the loop
- // header. The actual loop we need to check later will come from an add
- // recurrence, but getting that requires computing the SCEV of the operands,
- // which can be expensive. This check we can do cheaply to rule out some
- // cases early.
- Loop *InnermostContainingLoop = LI.getLoopFor(BinOp->getParent());
+ return isSCEVExprNeverPoison(BinOp) ? Flags : SCEV::FlagAnyWrap;
+}
+
+bool ScalarEvolution::isSCEVExprNeverPoison(const Instruction *I) {
+ // Here we check that I is in the header of the innermost loop containing I,
+ // since we only deal with instructions in the loop header. The actual loop we
+ // need to check later will come from an add recurrence, but getting that
+ // requires computing the SCEV of the operands, which can be expensive. This
+ // check we can do cheaply to rule out some cases early.
+ Loop *InnermostContainingLoop = LI.getLoopFor(I->getParent());
if (InnermostContainingLoop == nullptr ||
- InnermostContainingLoop->getHeader() != BinOp->getParent())
- return SCEV::FlagAnyWrap;
+ InnermostContainingLoop->getHeader() != I->getParent())
+ return false;
- // Only proceed if we can prove that BinOp does not yield poison.
- if (!isKnownNotFullPoison(BinOp)) return SCEV::FlagAnyWrap;
+ // Only proceed if we can prove that I does not yield poison.
+ if (!isKnownNotFullPoison(I)) return false;
- // At this point we know that if V is executed, then it does not wrap
- // according to at least one of NSW or NUW. If V is not executed, then we do
- // not know if the calculation that V represents would wrap. Multiple
- // instructions can map to the same SCEV. If we apply NSW or NUW from V to
+ // At this point we know that if I is executed, then it does not wrap
+ // according to at least one of NSW or NUW. If I is not executed, then we do
+ // not know if the calculation that I represents would wrap. Multiple
+ // instructions can map to the same SCEV. If we apply NSW or NUW from I to
// the SCEV, we must guarantee no wrapping for that SCEV also when it is
// derived from other instructions that map to the same SCEV. We cannot make
- // that guarantee for cases where V is not executed. So we need to find the
- // loop that V is considered in relation to and prove that V is executed for
- // every iteration of that loop. That implies that the value that V
+ // that guarantee for cases where I is not executed. So we need to find the
+ // loop that I is considered in relation to and prove that I is executed for
+ // every iteration of that loop. That implies that the value that I
// calculates does not wrap anywhere in the loop, so then we can apply the
// flags to the SCEV.
//
- // We check isLoopInvariant to disambiguate in case we are adding two
- // recurrences from different loops, so that we know which loop to prove
- // that V is executed in.
- for (int OpIndex = 0; OpIndex < 2; ++OpIndex) {
- const SCEV *Op = getSCEV(BinOp->getOperand(OpIndex));
+ // We check isLoopInvariant to disambiguate in case we are adding recurrences
+ // from different loops, so that we know which loop to prove that I is
+ // executed in.
+ for (unsigned OpIndex = 0; OpIndex < I->getNumOperands(); ++OpIndex) {
+ const SCEV *Op = getSCEV(I->getOperand(OpIndex));
if (auto *AddRec = dyn_cast<SCEVAddRecExpr>(Op)) {
- const int OtherOpIndex = 1 - OpIndex;
- const SCEV *OtherOp = getSCEV(BinOp->getOperand(OtherOpIndex));
- if (isLoopInvariant(OtherOp, AddRec->getLoop()) &&
- isGuaranteedToExecuteForEveryIteration(BinOp, AddRec->getLoop()))
- return Flags;
+ bool AllOtherOpsLoopInvariant = true;
+ for (unsigned OtherOpIndex = 0; OtherOpIndex < I->getNumOperands();
+ ++OtherOpIndex) {
+ if (OtherOpIndex != OpIndex) {
+ const SCEV *OtherOp = getSCEV(I->getOperand(OtherOpIndex));
+ if (!isLoopInvariant(OtherOp, AddRec->getLoop())) {
+ AllOtherOpsLoopInvariant = false;
+ break;
+ }
+ }
+ }
+ if (AllOtherOpsLoopInvariant &&
+ isGuaranteedToExecuteForEveryIteration(I, AddRec->getLoop()))
+ return true;
}
}
- return SCEV::FlagAnyWrap;
+ return false;
}
/// createSCEV - We know that there is no SCEV for the specified value. Analyze
More information about the llvm-commits
mailing list