[llvm] 02fdbc3 - Revert "[NFC][SCEV] Generalize monotonicity check for full and limited iteration space"

Max Kazantsev via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 24 03:10:07 PST 2020


Author: Max Kazantsev
Date: 2020-11-24T17:56:59+07:00
New Revision: 02fdbc3567249471349474c70828cb5a5d4881c8

URL: https://github.com/llvm/llvm-project/commit/02fdbc3567249471349474c70828cb5a5d4881c8
DIFF: https://github.com/llvm/llvm-project/commit/02fdbc3567249471349474c70828cb5a5d4881c8.diff

LOG: Revert "[NFC][SCEV] Generalize monotonicity check for full and limited iteration space"

This reverts commit 2734a9ebf4a31df0131acdfc739395a5e692c342.

This patch appeared to not be a NFC. It introduced an execution path where
monotonicity check on limited space started relying in existing nsw/nuw
flags, which is illegal. The motivating test will follow-up.

Added: 
    

Modified: 
    llvm/include/llvm/Analysis/ScalarEvolution.h
    llvm/lib/Analysis/ScalarEvolution.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Analysis/ScalarEvolution.h b/llvm/include/llvm/Analysis/ScalarEvolution.h
index 677433c32556..9c19ec986444 100644
--- a/llvm/include/llvm/Analysis/ScalarEvolution.h
+++ b/llvm/include/llvm/Analysis/ScalarEvolution.h
@@ -954,14 +954,9 @@ class ScalarEvolution {
   /// monotonically increasing or decreasing, returns
   /// Some(MonotonicallyIncreasing) and Some(MonotonicallyDecreasing)
   /// respectively. If we could not prove either of these facts, returns None.
-  ///
-  /// If NumIter was provided, then we are proving monotonicity during at least
-  /// NumIter first iterations. If it was not provided, then we are proving
-  /// monotonicity on all iteration space.
   Optional<MonotonicPredicateType>
-  getMonotonicPredicateType(const SCEVAddRecExpr *LHS, ICmpInst::Predicate Pred,
-                            Optional<const SCEV *> NumIter = None,
-                            const Instruction *Context = nullptr);
+  getMonotonicPredicateType(const SCEVAddRecExpr *LHS,
+                            ICmpInst::Predicate Pred);
 
   struct LoopInvariantPredicate {
     ICmpInst::Predicate Pred;
@@ -1920,9 +1915,9 @@ class ScalarEvolution {
   /// entry and backedge.
   SCEV::NoWrapFlags proveNoUnsignedWrapViaInduction(const SCEVAddRecExpr *AR);
 
-  Optional<MonotonicPredicateType> getMonotonicPredicateTypeImpl(
-      const SCEVAddRecExpr *LHS, ICmpInst::Predicate Pred,
-      Optional<const SCEV *> NumIter, const Instruction *Context);
+  Optional<MonotonicPredicateType>
+  getMonotonicPredicateTypeImpl(const SCEVAddRecExpr *LHS,
+                                ICmpInst::Predicate Pred);
 
   /// Return SCEV no-wrap flags that can be proven based on reasoning about
   /// how poison produced from no-wrap flags on this value (e.g. a nuw add)

diff  --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index a366ad355233..08ed363918a9 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -9504,19 +9504,15 @@ bool ScalarEvolution::isKnownOnEveryIteration(ICmpInst::Predicate Pred,
 
 Optional<ScalarEvolution::MonotonicPredicateType>
 ScalarEvolution::getMonotonicPredicateType(const SCEVAddRecExpr *LHS,
-                                           ICmpInst::Predicate Pred,
-                                           Optional<const SCEV *> NumIter,
-                                           const Instruction *Context) {
-  assert((!NumIter || !isa<SCEVCouldNotCompute>(*NumIter)) &&
-         "provided number of iterations must be computable!");
-  auto Result = getMonotonicPredicateTypeImpl(LHS, Pred, NumIter, Context);
+                                           ICmpInst::Predicate Pred) {
+  auto Result = getMonotonicPredicateTypeImpl(LHS, Pred);
 
 #ifndef NDEBUG
   // Verify an invariant: inverting the predicate should turn a monotonically
   // increasing change to a monotonically decreasing one, and vice versa.
   if (Result) {
-    auto ResultSwapped = getMonotonicPredicateTypeImpl(
-        LHS, ICmpInst::getSwappedPredicate(Pred), NumIter, Context);
+    auto ResultSwapped =
+        getMonotonicPredicateTypeImpl(LHS, ICmpInst::getSwappedPredicate(Pred));
 
     assert(ResultSwapped.hasValue() && "should be able to analyze both!");
     assert(ResultSwapped.getValue() != Result.getValue() &&
@@ -9529,9 +9525,7 @@ ScalarEvolution::getMonotonicPredicateType(const SCEVAddRecExpr *LHS,
 
 Optional<ScalarEvolution::MonotonicPredicateType>
 ScalarEvolution::getMonotonicPredicateTypeImpl(const SCEVAddRecExpr *LHS,
-                                               ICmpInst::Predicate Pred,
-                                               Optional<const SCEV *> NumIter,
-                                               const Instruction *Context) {
+                                               ICmpInst::Predicate Pred) {
   // A zero step value for LHS means the induction variable is essentially a
   // loop invariant value. We don't really depend on the predicate actually
   // flipping from false to true (for increasing predicates, and the other way
@@ -9550,60 +9544,23 @@ ScalarEvolution::getMonotonicPredicateTypeImpl(const SCEVAddRecExpr *LHS,
   assert((IsGreater || ICmpInst::isLE(Pred) || ICmpInst::isLT(Pred)) &&
          "Should be greater or less!");
 
-  bool IsUnsigned = ICmpInst::isUnsigned(Pred);
-  assert((IsUnsigned || ICmpInst::isSigned(Pred)) &&
-         "Should be either signed or unsigned!");
-  // Check if we can prove no-wrap in the relevant range.
-
-  const SCEV *Step = LHS->getStepRecurrence(*this);
-  bool IsStepNonNegative = isKnownNonNegative(Step);
-  bool IsStepNonPositive = isKnownNonPositive(Step);
-  // We need to know which direction the iteration is going.
-  if (!IsStepNonNegative && !IsStepNonPositive)
-    return None;
-
-  auto ProvedNoWrap = [&]() {
-    // If the AddRec already has the flag, we are done.
-    if (IsUnsigned ? LHS->hasNoUnsignedWrap() : LHS->hasNoSignedWrap())
-      return true;
-
-    if (!NumIter)
-      return false;
-    // We could not prove no-wrap on all iteration space. Can we prove it for
-    // first iterations? In order to achieve it, check that:
-    // 1. The addrec does not self-wrap;
-    // 2. start <= end for non-negative step and start >= end for non-positive
-    // step.
-    bool HasNoSelfWrap = LHS->hasNoSelfWrap();
-    if (!HasNoSelfWrap)
-      // If num iter has same type as the AddRec, and step is +/- 1, even max
-      // possible number of iterations is not enough to self-wrap.
-      if (NumIter.getValue()->getType() == LHS->getType())
-        if (Step == getOne(LHS->getType()) ||
-            Step == getMinusOne(LHS->getType()))
-          HasNoSelfWrap = true;
-    if (!HasNoSelfWrap)
-      return false;
-    const SCEV *Start = LHS->getStart();
-    const SCEV *End = LHS->evaluateAtIteration(*NumIter, *this);
-    ICmpInst::Predicate NoOverflowPred =
-        IsStepNonNegative ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_SGE;
-    if (IsUnsigned)
-      NoOverflowPred = ICmpInst::getUnsignedPredicate(NoOverflowPred);
-    return isKnownPredicateAt(NoOverflowPred, Start, End, Context);
-  };
+  // Check that AR does not wrap.
+  if (ICmpInst::isUnsigned(Pred)) {
+    if (!LHS->hasNoUnsignedWrap())
+      return None;
+    return IsGreater ? MonotonicallyIncreasing : MonotonicallyDecreasing;
+  } else {
+    assert(ICmpInst::isSigned(Pred) &&
+           "Relational predicate is either signed or unsigned!");
+    if (!LHS->hasNoSignedWrap())
+      return None;
 
-  // If nothing worked, bail.
-  if (!ProvedNoWrap())
-    return None;
+    const SCEV *Step = LHS->getStepRecurrence(*this);
 
-  if (IsUnsigned)
-    return IsGreater ? MonotonicallyIncreasing : MonotonicallyDecreasing;
-  else {
-    if (IsStepNonNegative)
+    if (isKnownNonNegative(Step))
       return IsGreater ? MonotonicallyIncreasing : MonotonicallyDecreasing;
 
-    if (IsStepNonPositive)
+    if (isKnownNonPositive(Step))
       return !IsGreater ? MonotonicallyIncreasing : MonotonicallyDecreasing;
 
     return None;
@@ -9664,6 +9621,7 @@ ScalarEvolution::getLoopInvariantExitCondDuringFirstIterations(
   // Try to prove the following set of facts:
   // - The predicate is monotonic in the iteration space.
   // - If the check does not fail on the 1st iteration:
+  //   - No overflow will happen during first MaxIter iterations;
   //   - It will not fail on the MaxIter'th iteration.
   // If the check does fail on the 1st iteration, we leave the loop and no
   // other checks matter.
@@ -9681,7 +9639,23 @@ ScalarEvolution::getLoopInvariantExitCondDuringFirstIterations(
   if (!AR || AR->getLoop() != L)
     return None;
 
-  if (!getMonotonicPredicateType(AR, Pred, MaxIter, Context))
+  // The predicate must be relational (i.e. <, <=, >=, >).
+  if (!ICmpInst::isRelational(Pred))
+    return None;
+
+  const SCEV *Step = AR->getStepRecurrence(*this);
+  bool IsStepNonPositive = isKnownNonPositive(Step);
+  if (!IsStepNonPositive && !isKnownNonNegative(Step))
+    return None;
+  bool HasNoSelfWrap = AR->hasNoSelfWrap();
+  if (!HasNoSelfWrap)
+    // If num iter has same type as the AddRec, and step is +/- 1, even max
+    // possible number of iterations is not enough to self-wrap.
+    if (MaxIter->getType() == AR->getType())
+      if (Step == getOne(AR->getType()) || Step == getMinusOne(AR->getType()))
+        HasNoSelfWrap = true;
+  // Only proceed with non-self-wrapping ARs.
+  if (!HasNoSelfWrap)
     return None;
 
   // Value of IV on suggested last iteration.
@@ -9689,9 +9663,20 @@ ScalarEvolution::getLoopInvariantExitCondDuringFirstIterations(
   // Does it still meet the requirement?
   if (!isKnownPredicateAt(Pred, Last, RHS, Context))
     return None;
+  // We know that the addrec does not have a self-wrap. To prove that there is
+  // no signed/unsigned wrap, we need to check that
+  // Start <= Last for positive step or Start >= Last for negative step. Either
+  // works for zero step.
+  ICmpInst::Predicate NoOverflowPred =
+      CmpInst::isSigned(Pred) ? ICmpInst::ICMP_SLE : ICmpInst::ICMP_ULE;
+  if (IsStepNonPositive)
+    NoOverflowPred = CmpInst::getSwappedPredicate(NoOverflowPred);
+  const SCEV *Start = AR->getStart();
+  if (!isKnownPredicateAt(NoOverflowPred, Start, Last, Context))
+    return None;
 
   // Everything is fine.
-  return ScalarEvolution::LoopInvariantPredicate(Pred, AR->getStart(), RHS);
+  return ScalarEvolution::LoopInvariantPredicate(Pred, Start, RHS);
 }
 
 bool ScalarEvolution::isKnownPredicateViaConstantRanges(


        


More information about the llvm-commits mailing list