-
Notifications
You must be signed in to change notification settings - Fork 14.5k
[DA] Add check for base pointer invariance #148241
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
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-llvm-analysis Author: Ryotaro Kasuga (kasuga-fj) ChangesFull diff: https://github.com/llvm/llvm-project/pull/148241.diff 2 Files Affected:
diff --git a/llvm/lib/Analysis/DependenceAnalysis.cpp b/llvm/lib/Analysis/DependenceAnalysis.cpp
index 428342f51ad2e..07bf560772c8c 100644
--- a/llvm/lib/Analysis/DependenceAnalysis.cpp
+++ b/llvm/lib/Analysis/DependenceAnalysis.cpp
@@ -3383,6 +3383,10 @@ bool DependenceInfo::tryDelinearize(Instruction *Src, Instruction *Dst,
SrcSubscripts, DstSubscripts))
return false;
+ assert(isLoopInvariant(SrcBase, SrcLoop) &&
+ isLoopInvariant(DstBase, DstLoop) &&
+ "Expected SrcBase and DstBase to be loop invariant");
+
int Size = SrcSubscripts.size();
LLVM_DEBUG({
dbgs() << "\nSrcSubscripts: ";
@@ -3666,6 +3670,18 @@ DependenceInfo::depends(Instruction *Src, Instruction *Dst,
SCEVUnionPredicate(Assume, *SE));
}
+ // Even if the base pointers are the same, they may not be loop-invariant. It
+ // could lead to incorrect results, as we're analyzing loop-carried
+ // dependencies.
+ Loop *SrcLoop = LI->getLoopFor(Src->getParent());
+ Loop *DstLoop = LI->getLoopFor(Dst->getParent());
+ if (!isLoopInvariant(SrcBase, SrcLoop) ||
+ !isLoopInvariant(DstBase, DstLoop)) {
+ LLVM_DEBUG(dbgs() << "The base pointer is not loop invariant.\n");
+ return std::make_unique<Dependence>(Src, Dst,
+ SCEVUnionPredicate(Assume, *SE));
+ }
+
uint64_t EltSize = SrcLoc.Size.toRaw();
const SCEV *SrcEv = SE->getMinusSCEV(SrcSCEV, SrcBase);
const SCEV *DstEv = SE->getMinusSCEV(DstSCEV, DstBase);
diff --git a/llvm/test/Analysis/DependenceAnalysis/FlipFlopBaseAddress.ll b/llvm/test/Analysis/DependenceAnalysis/FlipFlopBaseAddress.ll
index 843c18a6e0d1e..a357018563be1 100644
--- a/llvm/test/Analysis/DependenceAnalysis/FlipFlopBaseAddress.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/FlipFlopBaseAddress.ll
@@ -8,11 +8,11 @@
define float @bug41488_test1(float %f) {
; CHECK-LABEL: 'bug41488_test1'
; CHECK-NEXT: Src: %0 = load float, ptr %p, align 4 --> Dst: %0 = load float, ptr %p, align 4
-; CHECK-NEXT: da analyze - input [*]!
+; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: %0 = load float, ptr %p, align 4 --> Dst: store float %f, ptr %q, align 4
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: store float %f, ptr %q, align 4 --> Dst: store float %f, ptr %q, align 4
-; CHECK-NEXT: da analyze - output [*]!
+; CHECK-NEXT: da analyze - confused!
;
entry:
%g = alloca float, align 4
@@ -34,11 +34,11 @@ for.cond.cleanup:
define void @bug41488_test2(i32 %n) {
; CHECK-LABEL: 'bug41488_test2'
; CHECK-NEXT: Src: %0 = load float, ptr %p, align 4 --> Dst: %0 = load float, ptr %p, align 4
-; CHECK-NEXT: da analyze - input [*]!
+; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: %0 = load float, ptr %p, align 4 --> Dst: store float 0.000000e+00, ptr %q, align 4
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: store float 0.000000e+00, ptr %q, align 4 --> Dst: store float 0.000000e+00, ptr %q, align 4
-; CHECK-NEXT: da analyze - output [*]!
+; CHECK-NEXT: da analyze - confused!
;
entry:
%g = alloca float, align 4
@@ -68,7 +68,7 @@ define void @bug53942_foo(i32 noundef %n, ptr noalias nocapture noundef writeonl
; CHECK-NEXT: Src: %.pre = load double, ptr %B, align 8 --> Dst: store double %.pre, ptr %arrayidx2, align 8
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: store double %.pre, ptr %arrayidx2, align 8 --> Dst: store double %.pre, ptr %arrayidx2, align 8
-; CHECK-NEXT: da analyze - output [*]!
+; CHECK-NEXT: da analyze - confused!
;
entry:
%cmp8 = icmp sgt i32 %n, 1
@@ -99,11 +99,11 @@ for.body: ; preds = %for.body.preheader,
define void @bug53942_bar(i32 noundef %n, ptr noalias noundef %A, ptr noalias noundef %B) {
; CHECK-LABEL: 'bug53942_bar'
; CHECK-NEXT: Src: %0 = load double, ptr %arrayidx, align 8 --> Dst: %0 = load double, ptr %arrayidx, align 8
-; CHECK-NEXT: da analyze - input [*]!
+; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: %0 = load double, ptr %arrayidx, align 8 --> Dst: store double %0, ptr %arrayidx8, align 8
; CHECK-NEXT: da analyze - confused!
; CHECK-NEXT: Src: store double %0, ptr %arrayidx8, align 8 --> Dst: store double %0, ptr %arrayidx8, align 8
-; CHECK-NEXT: da analyze - output [*]!
+; CHECK-NEXT: da analyze - confused!
;
entry:
br label %for.cond
@@ -173,7 +173,7 @@ for.end: ; preds = %for.cond.cleanup
define void @non_invariant_baseptr_with_identical_obj(ptr %A) {
; CHECK-LABEL: 'non_invariant_baseptr_with_identical_obj'
; CHECK-NEXT: Src: store i32 1, ptr %idx, align 4 --> Dst: store i32 1, ptr %idx, align 4
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - confused!
;
entry:
br label %loop.i.header
@@ -222,7 +222,7 @@ exit:
define void @non_invariant_baseptr_with_identical_underlying_obj2(ptr %A) {
; CHECK-LABEL: 'non_invariant_baseptr_with_identical_underlying_obj2'
; CHECK-NEXT: Src: store i32 1, ptr %idx, align 4 --> Dst: store i32 1, ptr %idx, align 4
-; CHECK-NEXT: da analyze - none!
+; CHECK-NEXT: da analyze - confused!
;
entry:
br label %loop.i.header
|
0b6d75d
to
00e9a7d
Compare
3596b17
to
d914ea5
Compare
@@ -113,7 +113,7 @@ define void @banerjee1(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { | |||
; CHECK-NEXT: Src: %2 = load i64, ptr %arrayidx6, align 8 --> Dst: store i64 %2, ptr %B.addr.12, align 8 | |||
; CHECK-NEXT: da analyze - confused! | |||
; CHECK-NEXT: Src: store i64 %2, ptr %B.addr.12, align 8 --> Dst: store i64 %2, ptr %B.addr.12, align 8 | |||
; CHECK-NEXT: da analyze - output [* *]! |
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.
All the test changes except for FlipFlopBaseAddress.ll are related to dependencies between memory accesses of the form *B++
.
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.
*B++
should be fine though, right? Should the condition possibly be loop invariant or addrec for the appropriate loop?
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.
*B++
should be fine though, right?
Yes, I think.
Should the condition possibly be loop invariant or addrec for the appropriate loop?
Probably yes, but I'm not quite sure what qualifies as an "appropriate loop". In this case, the SCEV value for %B.addr.12
is {%B.addr.06,+,8}<nuw><%for.body3>
rather than something like {{%B,+,(8 * %m)}<%for.cond1.preheader>,+,8}<%for.body3>
. Can we infer anything from the former SCEV representation?
Add test cases where DA yields incorrect results because it makes an assumption that the base pointer is loop-invariant, which doesn't hold in these cases. Will be fixed by #148241.
b10a5ab
to
4977f6f
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.
Does the remaining issue occur only with an access having a dependence on itself?
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.
Does the remaining issue occur only with an access having a dependence on itself?
Added another test in 1df731b. Are you considering cases like this? If so, then the answer is YES. The dependencies between two distinct stores can be missed as well (godbolt: https://godbolt.org/z/7Mhb9rzGc).
@@ -113,7 +113,7 @@ define void @banerjee1(ptr %A, ptr %B, i64 %m, i64 %n) nounwind uwtable ssp { | |||
; CHECK-NEXT: Src: %2 = load i64, ptr %arrayidx6, align 8 --> Dst: store i64 %2, ptr %B.addr.12, align 8 | |||
; CHECK-NEXT: da analyze - confused! | |||
; CHECK-NEXT: Src: store i64 %2, ptr %B.addr.12, align 8 --> Dst: store i64 %2, ptr %B.addr.12, align 8 | |||
; CHECK-NEXT: da analyze - output [* *]! |
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.
*B++
should be fine though, right?
Yes, I think.
Should the condition possibly be loop invariant or addrec for the appropriate loop?
Probably yes, but I'm not quite sure what qualifies as an "appropriate loop". In this case, the SCEV value for %B.addr.12
is {%B.addr.06,+,8}<nuw><%for.body3>
rather than something like {{%B,+,(8 * %m)}<%for.cond1.preheader>,+,8}<%for.body3>
. Can we infer anything from the former SCEV representation?
As specified in #53942, DA assumes base pointer invariance in its process. Some cases were fixed by #116628. However, that PR only addressed the parts related to AliasAnalysis, so the original issue persists in later stages, especially when the AliasAnalysis results in
MustAlias
.This patch insert an explicit loop-invariant checks for the base pointer and skips analysis when it is not loop-invariant.
Fix the cases added in #148240.