Skip to content

Commit ae224f4

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

File tree

5 files changed

+111
-74
lines changed

5 files changed

+111
-74
lines changed

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5101,6 +5101,37 @@ 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+
return Result;
5117+
5118+
auto *WTy = SE.getWiderType(AR->getType(), BTC->getType());
5119+
// If AR's type is wider than BTC, we can zero extend BTC, otherwise bail out.
5120+
if (WTy != AR->getType())
5121+
return Result;
5122+
5123+
// AR has a step of 1, it is NUW/NSW if Start + BTC >= Start.
5124+
auto *Add = SE.getAddExpr(AR->getStart(), SE.getNoopOrZeroExtend(BTC, WTy));
5125+
if (!AR->hasNoUnsignedWrap() &&
5126+
SE.isKnownPredicate(CmpInst::ICMP_UGE, Add, AR->getStart()))
5127+
Result = ScalarEvolution::setFlags(Result, SCEV::FlagNUW);
5128+
if (!AR->hasNoSignedWrap() &&
5129+
SE.isKnownPredicate(CmpInst::ICMP_SGE, Add, AR->getStart()))
5130+
Result = ScalarEvolution::setFlags(Result, SCEV::FlagNSW);
5131+
5132+
return Result;
5133+
}
5134+
51045135
SCEV::NoWrapFlags
51055136
ScalarEvolution::proveNoSignedWrapViaInduction(const SCEVAddRecExpr *AR) {
51065137
SCEV::NoWrapFlags Result = AR->getNoWrapFlags();
@@ -5761,6 +5792,9 @@ const SCEV *ScalarEvolution::createSimpleAffineAddRec(PHINode *PN,
57615792
setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR),
57625793
(SCEV::NoWrapFlags)(AR->getNoWrapFlags() |
57635794
proveNoWrapViaConstantRanges(AR)));
5795+
setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR),
5796+
(SCEV::NoWrapFlags)(AR->getNoWrapFlags() |
5797+
proveNoWrapViaBTC(AR, *this)));
57645798
}
57655799

57665800
// We can add Flags to the post-inc expression only if we
@@ -5892,6 +5926,9 @@ const SCEV *ScalarEvolution::createAddRecFromPHI(PHINode *PN) {
58925926
setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR),
58935927
(SCEV::NoWrapFlags)(AR->getNoWrapFlags() |
58945928
proveNoWrapViaConstantRanges(AR)));
5929+
setNoWrapFlags(const_cast<SCEVAddRecExpr *>(AR),
5930+
(SCEV::NoWrapFlags)(AR->getNoWrapFlags() |
5931+
proveNoWrapViaBTC(AR, *this)));
58955932
}
58965933

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

llvm/test/Analysis/ScalarEvolution/addrec-computed-during-addrec-calculation.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ define void @test(ptr %p) {
2020
; CHECK-NEXT: %iv2.ext = sext i32 %iv2 to i64
2121
; CHECK-NEXT: --> (sext i32 {%iv,+,1}<%loop2> to i64) U: [-2147483648,2147483648) S: [-2147483648,2147483648) Exits: <<Unknown>> LoopDispositions: { %loop.header: Variant, %loop2: Computable, %loop3: Invariant }
2222
; CHECK-NEXT: %iv3 = phi i64 [ %iv2.ext, %loop2.end ], [ %iv3.next, %loop3 ]
23-
; CHECK-NEXT: --> {(sext i32 {%iv,+,1}<%loop2> to i64),+,1}<nsw><%loop3> U: [-2147483648,2147483648) S: [-2147483648,2147483648) Exits: (sext i32 {%iv,+,1}<%loop2> to i64) LoopDispositions: { %loop3: Computable, %loop.header: Variant }
23+
; CHECK-NEXT: --> {(sext i32 {%iv,+,1}<%loop2> to i64),+,1}<nuw><nsw><%loop3> U: [-2147483648,2147483648) S: [-2147483648,2147483648) Exits: (sext i32 {%iv,+,1}<%loop2> to i64) LoopDispositions: { %loop3: Computable, %loop.header: Variant }
2424
; CHECK-NEXT: %iv3.next = add nsw i64 %iv3, 1
2525
; CHECK-NEXT: --> {(1 + (sext i32 {%iv,+,1}<%loop2> to i64))<nsw>,+,1}<nsw><%loop3> U: [-2147483647,2147483649) S: [-2147483647,2147483649) Exits: (1 + (sext i32 {%iv,+,1}<%loop2> to i64))<nsw> LoopDispositions: { %loop3: Computable, %loop.header: Variant }
2626
; CHECK-NEXT: %iv.next = trunc i64 %iv3 to i32

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

Lines changed: 13 additions & 13 deletions
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)