[llvm] e08f989 - [SCEV] Preserve NSW for AddRec multiplied by -1 if it cannot be signed minimum
Dmitry Makogon via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 14 05:37:35 PDT 2023
Author: Dmitry Makogon
Date: 2023-04-14T19:36:56+07:00
New Revision: e08f9894ec8ca5ea600d2d2acafdd4b6c2aa5d29
URL: https://github.com/llvm/llvm-project/commit/e08f9894ec8ca5ea600d2d2acafdd4b6c2aa5d29
DIFF: https://github.com/llvm/llvm-project/commit/e08f9894ec8ca5ea600d2d2acafdd4b6c2aa5d29.diff
LOG: [SCEV] Preserve NSW for AddRec multiplied by -1 if it cannot be signed minimum
This preserves NSW flag for AddRecs multiplied by -1 if we can prove
via constant ranges that the AddRec cannot be signed minimum.
An explanation:
Let M be signed minimum. If AddRec's range contains M, then M * (-1) will
stay M and (M + 1) * (-1) will be signed maximum, so we get a signed overflow.
In all other cases if an AddRec didn't signed overflow,
then AddRec * (-1) wouldn't too.
Differential Revision: https://reviews.llvm.org/D148084
Added:
Modified:
llvm/lib/Analysis/ScalarEvolution.cpp
llvm/test/Analysis/ScalarEvolution/addrec-sub-nsw.ll
llvm/test/Analysis/ScalarEvolution/decrementing_addrecs.ll
llvm/test/Analysis/ScalarEvolution/different-loops-recs.ll
llvm/test/Analysis/ScalarEvolution/sext-iv-2.ll
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index 4ee6d249e953..dfe16fff4389 100644
--- a/llvm/lib/Analysis/ScalarEvolution.cpp
+++ b/llvm/lib/Analysis/ScalarEvolution.cpp
@@ -3192,9 +3192,20 @@ const SCEV *ScalarEvolution::getMulExpr(SmallVectorImpl<const SCEV *> &Ops,
for (const SCEV *AddRecOp : AddRec->operands())
Operands.push_back(getMulExpr(Ops[0], AddRecOp, SCEV::FlagAnyWrap,
Depth + 1));
-
+ // Let M be the minimum representable signed value. AddRec with nsw
+ // multiplied by -1 can have signed overflow if and only if it takes a
+ // value of M: M * (-1) would stay M and (M + 1) * (-1) would be the
+ // maximum signed value. In all other cases signed overflow is
+ // impossible.
+ auto FlagsMask = SCEV::FlagNW;
+ if (hasFlags(AddRec->getNoWrapFlags(), SCEV::FlagNSW)) {
+ auto MinInt =
+ APInt::getSignedMinValue(getTypeSizeInBits(AddRec->getType()));
+ if (getSignedRangeMin(AddRec) != MinInt)
+ FlagsMask = setFlags(FlagsMask, SCEV::FlagNSW);
+ }
return getAddRecExpr(Operands, AddRec->getLoop(),
- AddRec->getNoWrapFlags(SCEV::FlagNW));
+ AddRec->getNoWrapFlags(FlagsMask));
}
}
}
diff --git a/llvm/test/Analysis/ScalarEvolution/addrec-sub-nsw.ll b/llvm/test/Analysis/ScalarEvolution/addrec-sub-nsw.ll
index 18ed99cbcba4..032aaa4a7010 100644
--- a/llvm/test/Analysis/ScalarEvolution/addrec-sub-nsw.ll
+++ b/llvm/test/Analysis/ScalarEvolution/addrec-sub-nsw.ll
@@ -44,7 +44,7 @@ define i32 @test_2_non_positive(i32 %n) {
; CHECK-NEXT: %i = phi i32 [ 0, %entry ], [ %i.next, %loop ]
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop> U: [0,2147483647) S: [0,2147483647) Exits: (-1 + (1 smax %n))<nsw> LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %minus.i = mul i32 %i, -1
-; CHECK-NEXT: --> {0,+,-1}<nw><%loop> U: [-2147483646,1) S: [-2147483646,1) Exits: (1 + (-1 * (1 smax %n))<nsw>)<nsw> LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: --> {0,+,-1}<nsw><%loop> U: [-2147483646,1) S: [-2147483646,1) Exits: (1 + (-1 * (1 smax %n))<nsw>)<nsw> LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %a = sub i32 %minus.n, %minus.i
; CHECK-NEXT: --> {(-1 * %n),+,1}<nw><%loop> U: full-set S: full-set Exits: (-1 + (-1 * %n) + (1 smax %n)) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %i.next = add nuw nsw i32 %i, 1
diff --git a/llvm/test/Analysis/ScalarEvolution/decrementing_addrecs.ll b/llvm/test/Analysis/ScalarEvolution/decrementing_addrecs.ll
index 3757ffc693a9..9ca82061dc49 100644
--- a/llvm/test/Analysis/ScalarEvolution/decrementing_addrecs.ll
+++ b/llvm/test/Analysis/ScalarEvolution/decrementing_addrecs.ll
@@ -40,7 +40,7 @@ define i32 @test_step_1_flags(i32 %n) {
; DEFAULT-NEXT: %b = sub i32 %n.minus.1, %i
; DEFAULT-NEXT: --> {(-1 + %n),+,-1}<nsw><%loop> U: full-set S: full-set Exits: 0 LoopDispositions: { %loop: Computable }
; DEFAULT-NEXT: %c = sub i32 2147483647, %i
-; DEFAULT-NEXT: --> {2147483647,+,-1}<nw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: (-2147483648 + (-1 * %n)) LoopDispositions: { %loop: Computable }
+; DEFAULT-NEXT: --> {2147483647,+,-1}<nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: (-2147483648 + (-1 * %n)) LoopDispositions: { %loop: Computable }
; DEFAULT-NEXT: %i.next = add nuw nsw i32 %i, 1
; DEFAULT-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %n LoopDispositions: { %loop: Computable }
; DEFAULT-NEXT: %j.next = add nsw i32 %j, -1
@@ -66,7 +66,7 @@ define i32 @test_step_1_flags(i32 %n) {
; EXPENSIVE_SHARPENING-NEXT: %b = sub i32 %n.minus.1, %i
; EXPENSIVE_SHARPENING-NEXT: --> {(-1 + %n),+,-1}<nsw><%loop> U: [0,2147483647) S: [0,2147483647) Exits: 0 LoopDispositions: { %loop: Computable }
; EXPENSIVE_SHARPENING-NEXT: %c = sub i32 2147483647, %i
-; EXPENSIVE_SHARPENING-NEXT: --> {2147483647,+,-1}<nw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: (-2147483648 + (-1 * %n)) LoopDispositions: { %loop: Computable }
+; EXPENSIVE_SHARPENING-NEXT: --> {2147483647,+,-1}<nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: (-2147483648 + (-1 * %n)) LoopDispositions: { %loop: Computable }
; EXPENSIVE_SHARPENING-NEXT: %i.next = add nuw nsw i32 %i, 1
; EXPENSIVE_SHARPENING-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: %n LoopDispositions: { %loop: Computable }
; EXPENSIVE_SHARPENING-NEXT: %j.next = add nsw i32 %j, -1
diff --git a/llvm/test/Analysis/ScalarEvolution/
diff erent-loops-recs.ll b/llvm/test/Analysis/ScalarEvolution/
diff erent-loops-recs.ll
index 5d5b8ca53de8..349c6bde6991 100644
--- a/llvm/test/Analysis/ScalarEvolution/
diff erent-loops-recs.ll
+++ b/llvm/test/Analysis/ScalarEvolution/
diff erent-loops-recs.ll
@@ -275,7 +275,7 @@ define void @test_04() {
; CHECK: %tmp9 = sext i8 %tmp8 to i64
; CHECK-NEXT: --> (sext i8 %tmp8 to i64) U: [-128,128) S: [-128,128)
; CHECK: %tmp10 = sub i64 %tmp9, %tmp7
-; CHECK-NEXT: --> ((sext i8 %tmp8 to i64) + {-2,+,-1}<nw><%loop2>) U: [9223372036854775682,126) S: [9223372036854775682,126)
+; CHECK-NEXT: --> ((sext i8 %tmp8 to i64) + {-2,+,-1}<nsw><%loop2>) U: [9223372036854775682,126) S: [9223372036854775682,126)
; CHECK: %tmp11 = add i64 %tmp10, undef
; CHECK-NEXT: --> ((sext i8 %tmp8 to i64) + {(-2 + undef),+,-1}<nw><%loop2>)
; CHECK: %tmp13 = trunc i64 %tmp11 to i32
diff --git a/llvm/test/Analysis/ScalarEvolution/sext-iv-2.ll b/llvm/test/Analysis/ScalarEvolution/sext-iv-2.ll
index ce7d3b7d6c65..f372847d2e39 100644
--- a/llvm/test/Analysis/ScalarEvolution/sext-iv-2.ll
+++ b/llvm/test/Analysis/ScalarEvolution/sext-iv-2.ll
@@ -3,7 +3,7 @@
; CHECK: %tmp3 = sext i8 %tmp2 to i32
; CHECK: --> (sext i8 {0,+,1}<%bb1> to i32) U: [-128,128) S: [-128,128) Exits: -1
; CHECK: %tmp4 = mul i32 %tmp3, %i.02
-; CHECK: --> ((sext i8 {0,+,1}<%bb1> to i32) * {0,+,1}<nuw><nsw><%bb>) U: [-3968,3938) S: [-3968,3938) Exits: {0,+,-1}<nw><%bb>
+; CHECK: --> ((sext i8 {0,+,1}<%bb1> to i32) * {0,+,1}<nuw><nsw><%bb>) U: [-3968,3938) S: [-3968,3938) Exits: {0,+,-1}<nsw><%bb>
; These sexts are not foldable.
More information about the llvm-commits
mailing list