[llvm] a6342c2 - [SCEV] accurate range for addrecexpr with nuw flag

Zheng Chen via llvm-commits llvm-commits at lists.llvm.org
Sun Jan 12 17:26:05 PST 2020


Author: Zheng Chen
Date: 2020-01-12T20:22:37-05:00
New Revision: a6342c247a17fb270e0385bd1deb463b7309a43b

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

LOG: [SCEV] accurate range for addrecexpr with nuw flag

If addrecexpr has nuw flag, the value should never be less than its
start value and start value does not required to be SCEVConstant.

Reviewed By: nikic, sanjoy

Differential Revision: https://reviews.llvm.org/D71690

Added: 
    

Modified: 
    llvm/lib/Analysis/ScalarEvolution.cpp
    llvm/test/Analysis/ScalarEvolution/range_nw_flag.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index f8d23c40e0c9..648412a63a0e 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -5672,11 +5672,12 @@ ScalarEvolution::getRangeRef(const SCEV *S,
   if (const SCEVAddRecExpr *AddRec = dyn_cast<SCEVAddRecExpr>(S)) {
     // If there's no unsigned wrap, the value will never be less than its
     // initial value.
-    if (AddRec->hasNoUnsignedWrap())
-      if (const SCEVConstant *C = dyn_cast<SCEVConstant>(AddRec->getStart()))
-        if (!C->getValue()->isZero())
-          ConservativeResult = ConservativeResult.intersectWith(
-              ConstantRange(C->getAPInt(), APInt(BitWidth, 0)), RangeType);
+    if (AddRec->hasNoUnsignedWrap()) {
+      APInt UnsignedMinValue = getUnsignedRangeMin(AddRec->getStart());
+      if (!UnsignedMinValue.isNullValue())
+        ConservativeResult = ConservativeResult.intersectWith(
+            ConstantRange(UnsignedMinValue, APInt(BitWidth, 0)), RangeType);
+    }
 
     // If there's no signed wrap, and all the operands except initial value have
     // the same sign or zero, the value won't ever be:

diff  --git a/llvm/test/Analysis/ScalarEvolution/range_nw_flag.ll b/llvm/test/Analysis/ScalarEvolution/range_nw_flag.ll
index ae447dcdfa57..0a0b5fb5eb8c 100644
--- a/llvm/test/Analysis/ScalarEvolution/range_nw_flag.ll
+++ b/llvm/test/Analysis/ScalarEvolution/range_nw_flag.ll
@@ -2,7 +2,7 @@
 
 ; copied from flags-from-poison.ll
 ; CHECK-LABEL: @test-add-nuw
-; CHECK: -->  {(1 + %offset)<nuw>,+,1}<nuw><%loop> U: full-set S: full-set
+; CHECK: -->  {(1 + %offset)<nuw>,+,1}<nuw><%loop> U: [1,0) S: [1,0)
 define void @test-add-nuw(float* %input, i32 %offset, i32 %numIterations) {
 entry:
   br label %loop
@@ -20,7 +20,7 @@ exit:
 }
 
 ; CHECK-LABEL: @test-addrec-nuw
-; CHECK: -->  {(1 + (10 smax %offset))<nuw>,+,1}<nuw><%loop> U: full-set S: full-set 
+; CHECK: -->  {(1 + (10 smax %offset))<nuw>,+,1}<nuw><%loop> U: [11,0) S: [11,0)
 define void @test-addrec-nuw(float* %input, i32 %offset, i32 %numIterations) {
 entry:
   %cmp = icmp sgt i32 %offset, 10


        


More information about the llvm-commits mailing list