[llvm] r262639 - [SCEV] Prove no-overflow via constant ranges

Sanjoy Das via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 3 10:31:30 PST 2016


Author: sanjoy
Date: Thu Mar  3 12:31:29 2016
New Revision: 262639

URL: http://llvm.org/viewvc/llvm-project?rev=262639&view=rev
Log:
[SCEV] Prove no-overflow via constant ranges

Exploit ScalarEvolution::getRange's newly acquired smartness (since
r262438) by using that to infer nsw and nuw when possible.

Added:
    llvm/trunk/test/Analysis/ScalarEvolution/increasing-or-decreasing-iv.ll
      - copied, changed from r262638, llvm/trunk/test/Analysis/ScalarEvolution/increasing-and-decreasing-range.ll
Removed:
    llvm/trunk/test/Analysis/ScalarEvolution/increasing-and-decreasing-range.ll
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=262639&r1=262638&r2=262639&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Thu Mar  3 12:31:29 2016
@@ -900,6 +900,9 @@ namespace llvm {
     bool proveNoWrapByVaryingStart(const SCEV *Start, const SCEV *Step,
                                    const Loop *L);
 
+    /// Try to prove NSW or NUW on \p AR relying on ConstantRange manipulation.
+    SCEV::NoWrapFlags proveNoWrapViaConstantRanges(const SCEVAddRecExpr *AR);
+
     bool isMonotonicPredicateImpl(const SCEVAddRecExpr *LHS,
                                   ICmpInst::Predicate Pred, bool &Increasing);
 

Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=262639&r1=262638&r2=262639&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Thu Mar  3 12:31:29 2016
@@ -1454,6 +1454,11 @@ const SCEV *ScalarEvolution::getZeroExte
       unsigned BitWidth = getTypeSizeInBits(AR->getType());
       const Loop *L = AR->getLoop();
 
+      if (!AR->hasNoUnsignedWrap()) {
+        auto NewFlags = proveNoWrapViaConstantRanges(AR);
+        const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(NewFlags);
+      }
+
       // If we have special knowledge that this addrec won't overflow,
       // we don't need to do any further analysis.
       if (AR->hasNoUnsignedWrap())
@@ -1663,6 +1668,11 @@ const SCEV *ScalarEvolution::getSignExte
       unsigned BitWidth = getTypeSizeInBits(AR->getType());
       const Loop *L = AR->getLoop();
 
+      if (!AR->hasNoSignedWrap()) {
+        auto NewFlags = proveNoWrapViaConstantRanges(AR);
+        const_cast<SCEVAddRecExpr *>(AR)->setNoWrapFlags(NewFlags);
+      }
+
       // If we have special knowledge that this addrec won't overflow,
       // we don't need to do any further analysis.
       if (AR->hasNoSignedWrap())
@@ -3757,6 +3767,37 @@ private:
 };
 } // end anonymous namespace
 
+SCEV::NoWrapFlags
+ScalarEvolution::proveNoWrapViaConstantRanges(const SCEVAddRecExpr *AR) {
+  if (!AR->isAffine())
+    return SCEV::FlagAnyWrap;
+
+  typedef OverflowingBinaryOperator OBO;
+  SCEV::NoWrapFlags Result = SCEV::FlagAnyWrap;
+
+  if (!AR->hasNoSignedWrap()) {
+    ConstantRange AddRecRange = getSignedRange(AR);
+    ConstantRange IncRange = getSignedRange(AR->getStepRecurrence(*this));
+
+    auto NSWRegion = ConstantRange::makeGuaranteedNoWrapRegion(
+        Instruction::Add, IncRange, OBO::NoSignedWrap);
+    if (NSWRegion.contains(AddRecRange))
+      Result = ScalarEvolution::setFlags(Result, SCEV::FlagNSW);
+  }
+
+  if (!AR->hasNoUnsignedWrap()) {
+    ConstantRange AddRecRange = getUnsignedRange(AR);
+    ConstantRange IncRange = getUnsignedRange(AR->getStepRecurrence(*this));
+
+    auto NUWRegion = ConstantRange::makeGuaranteedNoWrapRegion(
+        Instruction::Add, IncRange, OBO::NoUnsignedWrap);
+    if (NUWRegion.contains(AddRecRange))
+      Result = ScalarEvolution::setFlags(Result, SCEV::FlagNUW);
+  }
+
+  return Result;
+}
+
 const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
   const Loop *L = LI.getLoopFor(PN->getParent());
   if (!L || L->getHeader() != PN->getParent())

Removed: llvm/trunk/test/Analysis/ScalarEvolution/increasing-and-decreasing-range.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/increasing-and-decreasing-range.ll?rev=262638&view=auto
==============================================================================
--- llvm/trunk/test/Analysis/ScalarEvolution/increasing-and-decreasing-range.ll (original)
+++ llvm/trunk/test/Analysis/ScalarEvolution/increasing-and-decreasing-range.ll (removed)
@@ -1,88 +0,0 @@
-; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s
-
-define void @f0(i1 %c) {
-; CHECK-LABEL: Classifying expressions for: @f0
-entry:
-  %start = select i1 %c, i32 127, i32 0
-  %step  = select i1 %c, i32 -1,  i32 1
-  br label %loop
-
-loop:
-  %loop.iv = phi i32 [ 0, %entry ], [ %loop.iv.inc, %loop ]
-  %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ]
-; CHECK: %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ]
-; CHECK-NEXT:  -->  {%start,+,%step}<%loop> U: [0,128) S: [0,128)
-  %iv.next = add i32 %iv, %step
-  %loop.iv.inc = add i32 %loop.iv, 1
-  %be.cond = icmp ne i32 %loop.iv.inc, 128
-  br i1 %be.cond, label %loop, label %leave
-
-leave:
-  ret void
-}
-
-define void @f1(i1 %c) {
-; CHECK-LABEL: Classifying expressions for: @f1
-entry:
-  %start = select i1 %c, i32 120, i32 0
-  %step  = select i1 %c, i32 -8,  i32 8
-  br label %loop
-
-loop:
-  %loop.iv = phi i32 [ 0, %entry ], [ %loop.iv.inc, %loop ]
-  %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ]
-
-; CHECK:  %iv.1 = add i32 %iv, 1
-; CHECK-NEXT:  -->  {(1 + %start)<nuw><nsw>,+,%step}<%loop> U: [1,122) S: [1,122)
-; CHECK:  %iv.2 = add i32 %iv, 2
-; CHECK-NEXT:  -->  {(2 + %start)<nuw><nsw>,+,%step}<%loop> U: [2,123) S: [2,123)
-; CHECK:  %iv.3 = add i32 %iv, 3
-; CHECK-NEXT:  -->  {(3 + %start)<nuw><nsw>,+,%step}<%loop> U: [3,124) S: [3,124)
-; CHECK:  %iv.4 = add i32 %iv, 4
-; CHECK-NEXT:  -->  {(4 + %start)<nuw><nsw>,+,%step}<%loop> U: [4,125) S: [4,125)
-; CHECK:  %iv.5 = add i32 %iv, 5
-; CHECK-NEXT:  -->  {(5 + %start)<nuw><nsw>,+,%step}<%loop> U: [5,126) S: [5,126)
-; CHECK:  %iv.6 = add i32 %iv, 6
-; CHECK-NEXT:  -->  {(6 + %start)<nuw><nsw>,+,%step}<%loop> U: [6,127) S: [6,127)
-; CHECK:  %iv.7 = add i32 %iv, 7
-; CHECK-NEXT:  -->  {(7 + %start)<nuw><nsw>,+,%step}<%loop> U: [7,128) S: [7,128)
-
-  %iv.1 = add i32 %iv, 1
-  %iv.2 = add i32 %iv, 2
-  %iv.3 = add i32 %iv, 3
-  %iv.4 = add i32 %iv, 4
-  %iv.5 = add i32 %iv, 5
-  %iv.6 = add i32 %iv, 6
-  %iv.7 = add i32 %iv, 7
-
-; CHECK:  %iv.m1 = sub i32 %iv, 1
-; CHECK-NEXT:  -->  {(-1 + %start)<nsw>,+,%step}<%loop> U: [-1,120) S: [-1,120)
-; CHECK:  %iv.m2 = sub i32 %iv, 2
-; CHECK-NEXT:  -->  {(-2 + %start)<nsw>,+,%step}<%loop> U: [-2,119) S: [-2,119)
-; CHECK:  %iv.m3 = sub i32 %iv, 3
-; CHECK-NEXT:  -->  {(-3 + %start)<nsw>,+,%step}<%loop> U: [-3,118) S: [-3,118)
-; CHECK:  %iv.m4 = sub i32 %iv, 4
-; CHECK-NEXT:  -->  {(-4 + %start)<nsw>,+,%step}<%loop> U: [-4,117) S: [-4,117)
-; CHECK:  %iv.m5 = sub i32 %iv, 5
-; CHECK-NEXT:  -->  {(-5 + %start)<nsw>,+,%step}<%loop> U: [-5,116) S: [-5,116)
-; CHECK:  %iv.m6 = sub i32 %iv, 6
-; CHECK-NEXT:  -->  {(-6 + %start)<nsw>,+,%step}<%loop> U: [-6,115) S: [-6,115)
-; CHECK:  %iv.m7 = sub i32 %iv, 7
-; CHECK-NEXT:  -->  {(-7 + %start)<nsw>,+,%step}<%loop> U: [-7,114) S: [-7,114)
-
-  %iv.m1 = sub i32 %iv, 1
-  %iv.m2 = sub i32 %iv, 2
-  %iv.m3 = sub i32 %iv, 3
-  %iv.m4 = sub i32 %iv, 4
-  %iv.m5 = sub i32 %iv, 5
-  %iv.m6 = sub i32 %iv, 6
-  %iv.m7 = sub i32 %iv, 7
-
-  %iv.next = add i32 %iv, %step
-  %loop.iv.inc = add i32 %loop.iv, 1
-  %be.cond = icmp sgt i32 %loop.iv, 14
-  br i1 %be.cond, label %leave, label %loop
-
-leave:
-  ret void
-}

Copied: llvm/trunk/test/Analysis/ScalarEvolution/increasing-or-decreasing-iv.ll (from r262638, llvm/trunk/test/Analysis/ScalarEvolution/increasing-and-decreasing-range.ll)
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Analysis/ScalarEvolution/increasing-or-decreasing-iv.ll?p2=llvm/trunk/test/Analysis/ScalarEvolution/increasing-or-decreasing-iv.ll&p1=llvm/trunk/test/Analysis/ScalarEvolution/increasing-and-decreasing-range.ll&r1=262638&r2=262639&rev=262639&view=diff
==============================================================================
--- llvm/trunk/test/Analysis/ScalarEvolution/increasing-and-decreasing-range.ll (original)
+++ llvm/trunk/test/Analysis/ScalarEvolution/increasing-or-decreasing-iv.ll Thu Mar  3 12:31:29 2016
@@ -86,3 +86,54 @@ loop:
 leave:
   ret void
 }
+
+define void @f2(i1 %c) {
+; CHECK-LABEL: Classifying expressions for: @f2
+entry:
+  %start = select i1 %c, i32 127, i32 0
+  %step  = select i1 %c, i32 -1,  i32 1
+  br label %loop
+
+loop:
+  %loop.iv = phi i32 [ 0, %entry ], [ %loop.iv.inc, %loop ]
+  %iv = phi i32 [ %start, %entry ], [ %iv.next, %loop ]
+  %iv.sext = sext i32 %iv to i64
+  %iv.next = add i32 %iv, %step
+; CHECK:  %iv.sext = sext i32 %iv to i64
+; CHECK-NEXT:  -->  {(sext i32 %start to i64),+,(sext i32 %step to i64)}<nsw><%loop>
+  %loop.iv.inc = add i32 %loop.iv, 1
+  %be.cond = icmp ne i32 %loop.iv.inc, 128
+  br i1 %be.cond, label %loop, label %leave
+
+leave:
+  ret void
+}
+
+define void @f3(i1 %c) {
+; CHECK-LABEL: Classifying expressions for: @f3
+entry:
+
+; NB! the i16 type (as opposed to i32), the choice of the constant 509
+; and the trip count are all related and not arbitrary.  We want an
+; add recurrence that will look like it can unsign-overflow *unless*
+; SCEV is able to see the correlation between the two selects feeding
+; into the initial value and the step increment.
+
+  %start = select i1 %c, i16 1000, i16 0
+  %step  = select i1 %c, i16 1,  i16 509
+  br label %loop
+
+loop:
+  %loop.iv = phi i16 [ 0, %entry ], [ %loop.iv.inc, %loop ]
+  %iv = phi i16 [ %start, %entry ], [ %iv.next, %loop ]
+  %iv.zext = zext i16 %iv to i64
+; CHECK:  %iv.zext = zext i16 %iv to i64
+; CHECK-NEXT:  -->  {(zext i16 %start to i64),+,(zext i16 %step to i64)}<nuw><%loop>
+  %iv.next = add i16 %iv, %step
+  %loop.iv.inc = add i16 %loop.iv, 1
+  %be.cond = icmp ne i16 %loop.iv.inc, 128
+  br i1 %be.cond, label %loop, label %leave
+
+leave:
+  ret void
+}




More information about the llvm-commits mailing list