Skip to content

Commit 3c2cee8

Browse files
committed
[SCEV] Try to prove no-wrap for AddRecs via BTC
1 parent 06cb7b1 commit 3c2cee8

File tree

4 files changed

+106
-73
lines changed

4 files changed

+106
-73
lines changed

llvm/lib/Analysis/ScalarEvolution.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -5101,6 +5101,33 @@ ScalarEvolution::proveNoWrapViaConstantRanges(const SCEVAddRecExpr *AR) {
51015101
return Result;
51025102
}
51035103

5104+
/// Return true if \p AR is known to not wrap via the loop's backedge-taken
5105+
/// count.
5106+
static SCEV::NoWrapFlags proveNoWrapViaBTC(const SCEVAddRecExpr *AR,
5107+
ScalarEvolution &SE) {
5108+
SCEV::NoWrapFlags Result = SCEV::FlagAnyWrap;
5109+
if (AR->hasNoUnsignedWrap() && AR->hasNoSignedWrap())
5110+
return Result;
5111+
5112+
const Loop *L = AR->getLoop();
5113+
const SCEV *BTC = SE.getBackedgeTakenCount(L);
5114+
if (isa<SCEVCouldNotCompute>(BTC) ||
5115+
!match(AR->getStepRecurrence(SE), m_scev_One()) ||
5116+
AR->getType() != BTC->getType())
5117+
return Result;
5118+
5119+
// AR has a step of 1, it is NUW/NSW if Start + BTC >= Start.
5120+
auto *Add = SE.getAddExpr(AR->getStart(), BTC);
5121+
if (!AR->hasNoUnsignedWrap() &&
5122+
SE.isKnownPredicate(CmpInst::ICMP_UGE, Add, AR->getStart()))
5123+
Result = ScalarEvolution::setFlags(Result, SCEV::FlagNUW);
5124+
if (!AR->hasNoSignedWrap() &&
5125+
SE.isKnownPredicate(CmpInst::ICMP_SGE, Add, AR->getStart()))
5126+
Result = ScalarEvolution::setFlags(Result, SCEV::FlagNSW);
5127+
5128+
return Result;
5129+
}
5130+
51045131
SCEV::NoWrapFlags
51055132
ScalarEvolution::proveNoSignedWrapViaInduction(const SCEVAddRecExpr *AR) {
51065133
SCEV::NoWrapFlags Result = AR->getNoWrapFlags();
@@ -5761,6 +5788,9 @@ const SCEV *ScalarEvolution::createSimpleAffineAddRec(PHINode *PN,
57615788
setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR),
57625789
(SCEV::NoWrapFlags)(AR->getNoWrapFlags() |
57635790
proveNoWrapViaConstantRanges(AR)));
5791+
setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR),
5792+
(SCEV::NoWrapFlags)(AR->getNoWrapFlags() |
5793+
proveNoWrapViaBTC(AR, *this)));
57645794
}
57655795

57665796
// We can add Flags to the post-inc expression only if we
@@ -5892,6 +5922,9 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
58925922
setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR),
58935923
(SCEV::NoWrapFlags)(AR->getNoWrapFlags() |
58945924
proveNoWrapViaConstantRanges(AR)));
5925+
setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR),
5926+
(SCEV::NoWrapFlags)(AR->getNoWrapFlags() |
5927+
proveNoWrapViaBTC(AR, *this)));
58955928
}
58965929

58975930
// We can add Flags to the post-inc expression only if we

llvm/test/Analysis/ScalarEvolution/different-loops-recs.ll

+13-13
Original file line numberDiff line numberDiff line change
@@ -332,21 +332,21 @@ define void @test_03(i32 %a, i32 %b, i32 %c, ptr %p) {
332332
; CHECK-LABEL: 'test_03'
333333
; CHECK-NEXT: Classifying expressions for: @test_03
334334
; CHECK-NEXT: %phi1 = phi i32 [ %a, %entry ], [ %phi1.inc, %loop1 ]
335-
; CHECK-NEXT: --> {%a,+,1}<%loop1> U: full-set S: full-set Exits: (%a umax %c) LoopDispositions: { %loop1: Computable }
335+
; CHECK-NEXT: --> {%a,+,1}<nuw><%loop1> U: full-set S: full-set Exits: (%a umax %c) LoopDispositions: { %loop1: Computable }
336336
; CHECK-NEXT: %phi1.inc = add i32 %phi1, 1
337-
; CHECK-NEXT: --> {(1 + %a),+,1}<%loop1> U: full-set S: full-set Exits: (1 + (%a umax %c)) LoopDispositions: { %loop1: Computable }
337+
; CHECK-NEXT: --> {(1 + %a),+,1}<nw><%loop1> U: full-set S: full-set Exits: (1 + (%a umax %c)) LoopDispositions: { %loop1: Computable }
338338
; CHECK-NEXT: %phi2 = phi i32 [ %a, %loop1 ], [ %phi2.inc, %loop2 ]
339339
; CHECK-NEXT: --> {%a,+,2}<%loop2> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop2: Computable }
340340
; CHECK-NEXT: %phi2.inc = add i32 %phi2, 2
341341
; CHECK-NEXT: --> {(2 + %a),+,2}<%loop2> U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop2: Computable }
342342
; CHECK-NEXT: %v1 = load i32, ptr %p, align 4
343343
; CHECK-NEXT: --> %v1 U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop2: Variant }
344344
; CHECK-NEXT: %s1 = add i32 %phi1, %v1
345-
; CHECK-NEXT: --> ({%a,+,1}<%loop1> + %v1) U: full-set S: full-set --> ((%a umax %c) + %v1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop2: Variant }
345+
; CHECK-NEXT: --> ({%a,+,1}<nuw><%loop1> + %v1) U: full-set S: full-set --> ((%a umax %c) + %v1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop2: Variant }
346346
; CHECK-NEXT: %s2 = add i32 %s1, %b
347-
; CHECK-NEXT: --> ({(%a + %b),+,1}<%loop1> + %v1) U: full-set S: full-set --> ((%a umax %c) + %b + %v1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop2: Variant }
347+
; CHECK-NEXT: --> ({(%a + %b),+,1}<nw><%loop1> + %v1) U: full-set S: full-set --> ((%a umax %c) + %b + %v1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop2: Variant }
348348
; CHECK-NEXT: %s3 = add i32 %s2, %phi2
349-
; CHECK-NEXT: --> ({{\{\{}}((2 * %a) + %b),+,1}<%loop1>,+,2}<%loop2> + %v1) U: full-set S: full-set --> ({((%a umax %c) + %a + %b),+,2}<%loop2> + %v1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop2: Variant }
349+
; CHECK-NEXT: --> ({{\{\{}}((2 * %a) + %b),+,1}<nw><%loop1>,+,2}<%loop2> + %v1) U: full-set S: full-set --> ({((%a umax %c) + %a + %b),+,2}<%loop2> + %v1) U: full-set S: full-set Exits: <<Unknown>> LoopDispositions: { %loop2: Variant }
350350
; CHECK-NEXT: Determining loop execution counts for: @test_03
351351
; CHECK-NEXT: Loop %loop2: Unpredictable backedge-taken count.
352352
; CHECK-NEXT: Loop %loop2: Unpredictable constant max backedge-taken count.
@@ -757,13 +757,13 @@ define i64 @test_09(i32 %param) {
757757
; CHECK-NEXT: %iv1.next = add nuw nsw i64 %iv1, 1
758758
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop1> U: [1,4) S: [1,4) Exits: 3 LoopDispositions: { %loop1: Computable }
759759
; CHECK-NEXT: %iv2 = phi i32 [ %iv2.next, %loop2 ], [ %param, %loop2.preheader ]
760-
; CHECK-NEXT: --> {%param,+,1}<%loop2> U: full-set S: full-set Exits: (2 smax %param) LoopDispositions: { %loop2: Computable }
760+
; CHECK-NEXT: --> {%param,+,1}<nsw><%loop2> U: full-set S: full-set Exits: (2 smax %param) LoopDispositions: { %loop2: Computable }
761761
; CHECK-NEXT: %iv2.next = add i32 %iv2, 1
762-
; CHECK-NEXT: --> {(1 + %param),+,1}<%loop2> U: full-set S: full-set Exits: (1 + (2 smax %param))<nuw> LoopDispositions: { %loop2: Computable }
762+
; CHECK-NEXT: --> {(1 + %param),+,1}<nw><%loop2> U: full-set S: full-set Exits: (1 + (2 smax %param))<nuw> LoopDispositions: { %loop2: Computable }
763763
; CHECK-NEXT: %iv2.ext = sext i32 %iv2.next to i64
764-
; CHECK-NEXT: --> (sext i32 {(1 + %param),+,1}<%loop2> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) --> (sext i32 (1 + (2 smax %param))<nuw> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
764+
; CHECK-NEXT: --> (sext i32 {(1 + %param),+,1}<nw><%loop2> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) --> (sext i32 (1 + (2 smax %param))<nuw> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
765765
; CHECK-NEXT: %ret = mul i64 %iv1, %iv2.ext
766-
; CHECK-NEXT: --> ((sext i32 {(1 + %param),+,1}<%loop2> to i64) * {0,+,1}<nuw><nsw><%loop1>) U: [-4294967296,4294967295) S: [-4294967296,4294967295) --> (2 * (sext i32 (1 + (2 smax %param))<nuw> to i64))<nsw> U: [0,-1) S: [-4294967296,4294967295)
766+
; CHECK-NEXT: --> ((sext i32 {(1 + %param),+,1}<nw><%loop2> to i64) * {0,+,1}<nuw><nsw><%loop1>) U: [-4294967296,4294967295) S: [-4294967296,4294967295) --> (2 * (sext i32 (1 + (2 smax %param))<nuw> to i64))<nsw> U: [0,-1) S: [-4294967296,4294967295)
767767
; CHECK-NEXT: Determining loop execution counts for: @test_09
768768
; CHECK-NEXT: Loop %loop2: backedge-taken count is ((-1 * %param) + (2 smax %param))
769769
; CHECK-NEXT: Loop %loop2: constant max backedge-taken count is i32 -2147483646
@@ -828,13 +828,13 @@ define i64 @test_10(i32 %param) {
828828
; CHECK-NEXT: %uncle.outer.next = add i64 %uncle, 1
829829
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%uncle.loop> U: [1,2) S: [1,2) Exits: <<Unknown>> LoopDispositions: { %uncle.loop: Computable, %loop1: Invariant }
830830
; CHECK-NEXT: %iv2 = phi i32 [ %iv2.next, %loop2 ], [ %param, %loop2.preheader ]
831-
; CHECK-NEXT: --> {%param,+,1}<%loop2> U: full-set S: full-set Exits: (2 smax %param) LoopDispositions: { %loop2: Computable }
831+
; CHECK-NEXT: --> {%param,+,1}<nsw><%loop2> U: full-set S: full-set Exits: (2 smax %param) LoopDispositions: { %loop2: Computable }
832832
; CHECK-NEXT: %iv2.next = add i32 %iv2, 1
833-
; CHECK-NEXT: --> {(1 + %param),+,1}<%loop2> U: full-set S: full-set Exits: (1 + (2 smax %param))<nuw> LoopDispositions: { %loop2: Computable }
833+
; CHECK-NEXT: --> {(1 + %param),+,1}<nw><%loop2> U: full-set S: full-set Exits: (1 + (2 smax %param))<nuw> LoopDispositions: { %loop2: Computable }
834834
; CHECK-NEXT: %iv2.ext = sext i32 %iv2.next to i64
835-
; CHECK-NEXT: --> (sext i32 {(1 + %param),+,1}<%loop2> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) --> (sext i32 (1 + (2 smax %param))<nuw> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
835+
; CHECK-NEXT: --> (sext i32 {(1 + %param),+,1}<nw><%loop2> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) --> (sext i32 (1 + (2 smax %param))<nuw> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648)
836836
; CHECK-NEXT: %ret = mul i64 %iv1, %iv2.ext
837-
; CHECK-NEXT: --> ((sext i32 {(1 + %param),+,1}<%loop2> to i64) * {0,+,1}<nuw><nsw><%loop1>) U: [-4294967296,4294967295) S: [-4294967296,4294967295) --> (2 * (sext i32 (1 + (2 smax %param))<nuw> to i64))<nsw> U: [0,-1) S: [-4294967296,4294967295)
837+
; CHECK-NEXT: --> ((sext i32 {(1 + %param),+,1}<nw><%loop2> to i64) * {0,+,1}<nuw><nsw><%loop1>) U: [-4294967296,4294967295) S: [-4294967296,4294967295) --> (2 * (sext i32 (1 + (2 smax %param))<nuw> to i64))<nsw> U: [0,-1) S: [-4294967296,4294967295)
838838
; CHECK-NEXT: Determining loop execution counts for: @test_10
839839
; CHECK-NEXT: Loop %loop2: backedge-taken count is ((-1 * %param) + (2 smax %param))
840840
; CHECK-NEXT: Loop %loop2: constant max backedge-taken count is i32 -2147483646

0 commit comments

Comments
 (0)