[PATCH] D148322: [SCEV] Infer NSW when subtracting expressions with the same signs
Dmitry Makogon via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Fri Apr 14 03:32:25 PDT 2023
dmakogon created this revision.
dmakogon added reviewers: mkazantsev, nikic, fhahn, aleksandr.popov.
Herald added subscribers: StephenFan, javed.absar, hiraditya.
Herald added a project: All.
dmakogon requested review of this revision.
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.
When creating a SCEV for `X - Y` infer NSW for the resulting expression if X and Y are either both non-positive or non-negative.
In these cases there can be no signed overflow.
https://reviews.llvm.org/D148322
Files:
llvm/lib/Analysis/ScalarEvolution.cpp
llvm/test/Analysis/ScalarEvolution/addrec-sub-nsw.ll
llvm/test/Analysis/ScalarEvolution/decrementing_addrecs.ll
Index: llvm/test/Analysis/ScalarEvolution/decrementing_addrecs.ll
===================================================================
--- llvm/test/Analysis/ScalarEvolution/decrementing_addrecs.ll
+++ llvm/test/Analysis/ScalarEvolution/decrementing_addrecs.ll
@@ -36,7 +36,7 @@
; DEFAULT-NEXT: %j = phi i32 [ %n.minus.1, %entry ], [ %j.next, %loop ]
; DEFAULT-NEXT: --> {(-1 + %n),+,-1}<nsw><%loop> U: full-set S: full-set Exits: 0 LoopDispositions: { %loop: Computable }
; DEFAULT-NEXT: %a = sub i32 %n, %i
-; DEFAULT-NEXT: --> {%n,+,-1}<nw><%loop> U: full-set S: full-set Exits: 1 LoopDispositions: { %loop: Computable }
+; DEFAULT-NEXT: --> {%n,+,-1}<nsw><%loop> U: full-set S: full-set Exits: 1 LoopDispositions: { %loop: Computable }
; 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
@@ -62,7 +62,7 @@
; EXPENSIVE_SHARPENING-NEXT: %j = phi i32 [ %n.minus.1, %entry ], [ %j.next, %loop ]
; EXPENSIVE_SHARPENING-NEXT: --> {(-1 + %n),+,-1}<nsw><%loop> U: [0,2147483647) S: [0,2147483647) Exits: 0 LoopDispositions: { %loop: Computable }
; EXPENSIVE_SHARPENING-NEXT: %a = sub i32 %n, %i
-; EXPENSIVE_SHARPENING-NEXT: --> {%n,+,-1}<nw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: 1 LoopDispositions: { %loop: Computable }
+; EXPENSIVE_SHARPENING-NEXT: --> {%n,+,-1}<nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: 1 LoopDispositions: { %loop: Computable }
; 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
Index: llvm/test/Analysis/ScalarEvolution/addrec-sub-nsw.ll
===================================================================
--- llvm/test/Analysis/ScalarEvolution/addrec-sub-nsw.ll
+++ llvm/test/Analysis/ScalarEvolution/addrec-sub-nsw.ll
@@ -7,7 +7,7 @@
; 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: %a = sub i32 %n, %i
-; CHECK-NEXT: --> {%n,+,-1}<nw><%loop> U: full-set S: full-set Exits: (1 + (-1 * (1 smax %n))<nsw> + %n) LoopDispositions: { %loop: Computable }
+; CHECK-NEXT: --> {%n,+,-1}<nsw><%loop> U: full-set S: full-set Exits: (1 + (-1 * (1 smax %n))<nsw> + %n) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: %i.next = add nuw nsw i32 %i, 1
; CHECK-NEXT: --> {1,+,1}<nuw><nsw><%loop> U: [1,-2147483648) S: [1,-2147483648) Exits: (1 smax %n) LoopDispositions: { %loop: Computable }
; CHECK-NEXT: Determining loop execution counts for: @test_1_non_negative
@@ -44,7 +44,7 @@
; 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}<nsw><%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
Index: llvm/lib/Analysis/ScalarEvolution.cpp
===================================================================
--- llvm/lib/Analysis/ScalarEvolution.cpp
+++ llvm/lib/Analysis/ScalarEvolution.cpp
@@ -116,6 +116,7 @@
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/Utils/LoopUtils.h"
#include <algorithm>
#include <cassert>
#include <climits>
@@ -7712,6 +7713,35 @@
Flags = getNoWrapFlagsFromUB(BO->Op);
LHS = getSCEV(BO->LHS);
RHS = getSCEV(BO->RHS);
+
+ // Try to prove NSW based on operands signs. Subtracting non-negative
+ // values cannot overflow, as well as subtracting non-positives ones.
+ if (!hasFlags(Flags, SCEV::FlagNSW)) {
+ // If one of the operands is an AddRec, then the resulting expression
+ // makes sense only in the loop of that AddRec, so we can safely use the
+ // loop as context to get facts about operands signs.
+ const Loop *L = nullptr;
+ if (auto *AR = dyn_cast<SCEVAddRecExpr>(LHS))
+ L = AR->getLoop();
+ if (!L)
+ if (auto *AR = dyn_cast<SCEVAddRecExpr>(RHS))
+ L = AR->getLoop();
+ enum class SCEVExprSign { NonNegative, NonPositive, Unknown };
+ auto GetExprSign = [&](const SCEV *S) -> SCEVExprSign {
+ if (isKnownNonNegative(S) ||
+ (L && isKnownNonNegativeInLoop(S, L, *this)))
+ return SCEVExprSign::NonNegative;
+ if (isKnownNonPositive(S) ||
+ (L && isKnownNonPositiveInLoop(S, L, *this)))
+ return SCEVExprSign::NonPositive;
+ return SCEVExprSign::Unknown;
+ };
+ auto LHSSign = GetExprSign(LHS);
+ auto RHSSign = GetExprSign(RHS);
+ if (LHSSign != SCEVExprSign::Unknown && LHSSign == RHSSign)
+ Flags = setFlags(Flags, SCEV::FlagNSW);
+ }
+
return getMinusSCEV(LHS, RHS, Flags);
}
case Instruction::And:
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D148322.513519.patch
Type: text/x-patch
Size: 5803 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20230414/245f4735/attachment.bin>
More information about the llvm-commits
mailing list