Skip to content

Conversation

@kasuga-fj
Copy link
Contributor

@kasuga-fj kasuga-fj commented Jul 11, 2025

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.

@llvmbot llvmbot added the llvm:analysis Includes value tracking, cost tables and constant folding label Jul 11, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 11, 2025

@llvm/pr-subscribers-llvm-analysis

Author: Ryotaro Kasuga (kasuga-fj)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/148240.diff

1 Files Affected:

  • (modified) llvm/test/Analysis/DependenceAnalysis/FlipFlopBaseAddress.ll (+102)
diff --git a/llvm/test/Analysis/DependenceAnalysis/FlipFlopBaseAddress.ll b/llvm/test/Analysis/DependenceAnalysis/FlipFlopBaseAddress.ll
index 7fad0328fdaeb..843c18a6e0d1e 100644
--- a/llvm/test/Analysis/DependenceAnalysis/FlipFlopBaseAddress.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/FlipFlopBaseAddress.ll
@@ -157,3 +157,105 @@ for.inc:                                          ; preds = %cond.end5
 for.end:                                          ; preds = %for.cond.cleanup
   ret void
 }
+
+; Pseudo-code for the following IR:
+;
+; void f(int A[][42]) {
+;   for (int i = 0; i < 100; i++)
+;     for (int j = 0; j < 41; j++)
+;       (j % 2 == 0 ? A[i][j] : A[i][j+1]) = 1;
+; }
+;
+; FIXME: There are loop-carried dependencies between the store instruction. For
+; example, the value of %ptr0 when (i, j) = (0, 1) is %A+8, which is the same
+; as when (i, j) = (0, 2).
+
+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!
+;
+entry:
+  br label %loop.i.header
+
+loop.i.header:
+  %i = phi i32 [ 0, %entry ], [ %i.inc, %loop.i.latch ]
+  %A1 = getelementptr i32, ptr %A, i32 1
+  br label %loop.j
+
+loop.j:
+  %j = phi i32 [ 0, %loop.i.header ], [ %j.inc, %loop.j ]
+  %ptr0 = phi ptr [ %A, %loop.i.header ], [ %ptr1, %loop.j ]
+  %ptr1 = phi ptr [ %A1, %loop.i.header ], [ %ptr0, %loop.j ]
+  %idx = getelementptr [42 x i32], ptr %ptr0, i32 %i, i32 %j
+  store i32 1, ptr %idx
+  %j.inc = add i32 %j, 1
+  %cmp.j = icmp slt i32 %j.inc, 41
+  br i1 %cmp.j, label %loop.j, label %loop.i.latch
+
+loop.i.latch:
+  %i.inc = add i32 %i, 1
+  %cmp.i = icmp slt i32 %i.inc, 100
+  br i1 %cmp.i, label %loop.i.header, label %exit
+
+exit:
+  ret void
+}
+
+; Pseudo-code for the following IR:
+;
+; void f(int A[][42][42]) {
+;   for (int i = 0; i < 100; i++)
+;     for (int j = 0; j < 41; j++) {
+;       int *ptr0 = (j % 2 == 0 ? A[i][j] : A[i][j+1]);
+;       for (int k = 0; k < 42; k++)
+;         ptr0[k] = 1;
+;     }
+; }
+;
+; Similar to the above case, but ptr0 is loop-invariant with respsect to the
+; k-loop.
+;
+; FIXME: Same as the above case, there are loop-carried dependencies between
+; the store.
+
+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!
+;
+entry:
+  br label %loop.i.header
+
+loop.i.header:
+  %i = phi i32 [ 0, %entry ], [ %i.inc, %loop.i.latch ]
+  %A1 = getelementptr i32, ptr %A, i32 1
+  br label %loop.j.header
+
+loop.j.header:
+  %j = phi i32 [ 0, %loop.i.header ], [ %j.inc, %loop.j.latch ]
+  %ptr0 = phi ptr [ %A, %loop.i.header ], [ %ptr1, %loop.j.latch ]
+  %ptr1 = phi ptr [ %A1, %loop.i.header ], [ %ptr0, %loop.j.latch ]
+  br label %loop.k
+
+loop.k:
+  %k = phi i32 [ 0, %loop.j.header ], [ %k.inc, %loop.k ]
+  %idx = getelementptr [42 x [42 x i32]], ptr %ptr0, i32 %i, i32 %k, i32 %j
+  store i32 1, ptr %idx
+  %k.inc = add i32 %k, 1
+  %cmp.k = icmp slt i32 %k.inc, 42
+  br i1 %cmp.k, label %loop.k, label %loop.j.latch
+
+loop.j.latch:
+  %j.inc = add i32 %j, 1
+  %cmp.j = icmp slt i32 %j.inc, 41
+  br i1 %cmp.j, label %loop.j.header, label %loop.i.latch
+
+loop.i.latch:
+  %i.inc = add i32 %i, 1
+  %cmp.i = icmp slt i32 %i.inc, 100
+  br i1 %cmp.i, label %loop.i.header, label %exit
+
+exit:
+  ret void
+}

@kasuga-fj kasuga-fj merged commit 16534d1 into main Jul 14, 2025
9 checks passed
@kasuga-fj kasuga-fj deleted the users/kasuga-fj/da-check-baseptr-0 branch July 14, 2025 01:51
kasuga-fj added a commit that referenced this pull request Jul 25, 2025
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.
mahesh-attarde pushed a commit to mahesh-attarde/llvm-project that referenced this pull request Jul 28, 2025
As specified in llvm#53942, DA assumes base pointer invariance in its
process. Some cases were fixed by llvm#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 llvm#148240.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

llvm:analysis Includes value tracking, cost tables and constant folding

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants