-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[DA] Add overflow check in ExactSIV #157086
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-llvm-analysis Author: Ryotaro Kasuga (kasuga-fj) ChangesThis patch removes base pointers from subscripts when delinearization fails. Previously, in such cases, the pointer type SCEVs were used instead of offset SCEVs derived from them. For example, here is a portion of the debug output when analyzing
As shown above, the This change is necessary for #157086, since Full diff: https://github.com/llvm/llvm-project/pull/157086.diff 2 Files Affected:
diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp
index 0f77a1410e83b..6e576e866b310 100644
--- a/llvm/lib/Analysis/DependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/DependenceAnalysis.cpp
@@ -1170,6 +1170,15 @@ const SCEVConstant *DependenceInfo::collectConstantUpperBound(const Loop *L,
return nullptr;
}
+/// Returns \p A - \p B if it guaranteed not to signed wrap. Otherwise returns
+/// nullptr. \p A and \p B must have the same integer type.
+static const SCEV *minusSCEVNoSignedOverflow(const SCEV *A, const SCEV *B,
+ ScalarEvolution &SE) {
+ if (SE.willNotOverflow(Instruction::Sub, /*Signed=*/true, A, B))
+ return SE.getMinusSCEV(A, B);
+ return nullptr;
+}
+
// testZIV -
// When we have a pair of subscripts of the form [c1] and [c2],
// where c1 and c2 are both loop invariant, we attack it using
@@ -1626,7 +1635,9 @@ bool DependenceInfo::exactSIVtest(const SCEV *SrcCoeff, const SCEV *DstCoeff,
assert(0 < Level && Level <= CommonLevels && "Level out of range");
Level--;
Result.Consistent = false;
- const SCEV *Delta = SE->getMinusSCEV(DstConst, SrcConst);
+ const SCEV *Delta = minusSCEVNoSignedOverflow(DstConst, SrcConst, *SE);
+ if (!Delta)
+ return false;
LLVM_DEBUG(dbgs() << "\t Delta = " << *Delta << "\n");
NewConstraint.setLine(SrcCoeff, SE->getNegativeSCEV(DstCoeff), Delta,
CurLoop);
@@ -1716,6 +1727,7 @@ bool DependenceInfo::exactSIVtest(const SCEV *SrcCoeff, const SCEV *DstCoeff,
// explore directions
unsigned NewDirection = Dependence::DVEntry::NONE;
APInt LowerDistance, UpperDistance;
+ // TODO: Overflow check may be needed.
if (TA.sgt(TB)) {
LowerDistance = (TY - TX) + (TA - TB) * TL;
UpperDistance = (TY - TX) + (TA - TB) * TU;
diff --git a/llvm/test/Analysis/DependenceAnalysis/ExactSIV.ll b/llvm/test/Analysis/DependenceAnalysis/ExactSIV.ll
index 97b58c06303e6..5a8a60a6833ae 100644
--- a/llvm/test/Analysis/DependenceAnalysis/ExactSIV.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/ExactSIV.ll
@@ -834,7 +834,7 @@ define void @exact14(ptr %A) {
; CHECK-SIV-ONLY-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 0, ptr %idx.0, align 1
; CHECK-SIV-ONLY-NEXT: da analyze - none!
; CHECK-SIV-ONLY-NEXT: Src: store i8 0, ptr %idx.0, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
-; CHECK-SIV-ONLY-NEXT: da analyze - none!
+; CHECK-SIV-ONLY-NEXT: da analyze - output [*|<]!
; CHECK-SIV-ONLY-NEXT: Src: store i8 1, ptr %idx.1, align 1 --> Dst: store i8 1, ptr %idx.1, align 1
; CHECK-SIV-ONLY-NEXT: da analyze - none!
;
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now, I've added the minimal necessary checks, but it’s unclear whether similar checks are also needed elsewhere in this function. Apparently, such checks aren't necessary for GCD computation (ref). However, I'm not sure whether they are needed in subsequent steps. It might be safer to include it for now, just in case, until we can prove it's unnecessary?
// explore directions | ||
unsigned NewDirection = Dependence::DVEntry::NONE; | ||
APInt LowerDistance, UpperDistance; | ||
// TODO: Overflow check may be needed. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suspect this part could cause overflows, but not entirely sure...
5aec6d1
to
9d8c452
Compare
7678c02
to
94b1849
Compare
9d8c452
to
8377460
Compare
94b1849
to
06b81a6
Compare
8377460
to
059708d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
This patch removes base pointers from subscripts when delinearization fails. Previously, in such cases, the pointer type SCEVs were used instead of offset SCEVs derived from them. For example, here is a portion of the debug output when analyzing `strong0` in `test/Analysis/DependenceAnalysis/StrongSIV.ll`: ``` testing subscript 0, SIV src = {(8 + %A),+,4}<nuw><%for.body> dst = {(8 + %A),+,4}<nuw><%for.body> Strong SIV test Coeff = 4, i64 SrcConst = (8 + %A), ptr DstConst = (8 + %A), ptr Delta = 0, i64 UpperBound = (-1 + %n), i64 Distance = 0 Remainder = 0 ``` As shown above, the `SrcConst` and `DstConst` are pointer values rather than integer offsets. `%A` should be removed. This change is necessary for #157086, since `ScalarEvolution::willNotOverflow` expects integer type SCEVs as arguments. This change alone alone should not affect the analysis results.
059708d
to
6a3a5fc
Compare
06b81a6
to
a34c320
Compare
;; There exists dependency between `A[-6*i + INT64_MAX]` and `A[3*i - 2]`. | ||
;; For example, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unintended change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is intentional. I think it's non-trivial that the dependency exists between them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to be the same change as in 32203e6, before my request to adjust the comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I only meant to remove the FIXME assuming this PR would fix the bug. But after thinking it through, it only addresses part of the issue, and the result is still incorrect. You're right, I've reverted the comment change. Thanks!
This patch removes base pointers from subscripts when delinearization fails. Previously, in such cases, the pointer type SCEVs were used instead of offset SCEVs derived from them. For example, here is a portion of the debug output when analyzing `strong0` in `test/Analysis/DependenceAnalysis/StrongSIV.ll`: ``` testing subscript 0, SIV src = {(8 + %A),+,4}<nuw><%for.body> dst = {(8 + %A),+,4}<nuw><%for.body> Strong SIV test Coeff = 4, i64 SrcConst = (8 + %A), ptr DstConst = (8 + %A), ptr Delta = 0, i64 UpperBound = (-1 + %n), i64 Distance = 0 Remainder = 0 ``` As shown above, the `SrcConst` and `DstConst` are pointer values rather than integer offsets. `%A` should be removed. This change is necessary for llvm#157086, since `ScalarEvolution::willNotOverflow` expects integer type SCEVs as arguments. This change alone alone should not affect the analysis results.
This reverts commit a4f0f1f.
a34c320
to
146b38e
Compare
This patch removes base pointers from subscripts when delinearization fails. Previously, in such cases, the pointer type SCEVs were used instead of offset SCEVs derived from them. For example, here is a portion of the debug output when analyzing `strong0` in `test/Analysis/DependenceAnalysis/StrongSIV.ll`: ``` testing subscript 0, SIV src = {(8 + %A),+,4}<nuw><%for.body> dst = {(8 + %A),+,4}<nuw><%for.body> Strong SIV test Coeff = 4, i64 SrcConst = (8 + %A), ptr DstConst = (8 + %A), ptr Delta = 0, i64 UpperBound = (-1 + %n), i64 Distance = 0 Remainder = 0 ``` As shown above, the `SrcConst` and `DstConst` are pointer values rather than integer offsets. `%A` should be removed. This change is necessary for llvm#157086, since `ScalarEvolution::willNotOverflow` expects integer type SCEVs as arguments. This change alone alone should not affect the analysis results.
This patch removes base pointers from subscripts when delinearization fails. Previously, in such cases, the pointer type SCEVs were used instead of offset SCEVs derived from them. For example, here is a portion of the debug output when analyzing `strong0` in `test/Analysis/DependenceAnalysis/StrongSIV.ll`: ``` testing subscript 0, SIV src = {(8 + %A),+,4}<nuw><%for.body> dst = {(8 + %A),+,4}<nuw><%for.body> Strong SIV test Coeff = 4, i64 SrcConst = (8 + %A), ptr DstConst = (8 + %A), ptr Delta = 0, i64 UpperBound = (-1 + %n), i64 Distance = 0 Remainder = 0 ``` As shown above, the `SrcConst` and `DstConst` are pointer values rather than integer offsets. `%A` should be removed. This change is necessary for llvm#157086, since `ScalarEvolution::willNotOverflow` expects integer type SCEVs as arguments. This change alone alone should not affect the analysis results.
This patch adds an overflow check to the `exactSIVtest` function to fix the issue demonstrated in the test case added in llvm#157085. This patch only fixes one of the routines. To fully resolve the test case, the other functions need to be addressed as well.
This patch adds an overflow check to the `exactSIVtest` function to fix the issue demonstrated in the test case added in llvm#157085. This patch only fixes one of the routines. To fully resolve the test case, the other functions need to be addressed as well.
This patch adds an overflow check to the
exactSIVtest
function to fix the issue demonstrated in the test case added in #157085. This patch only fixes one of the routines. To fully resolve the test case, the other functions need to be addressed as well.