[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