[llvm] [DependenceAnalysis] Prevent non-AddRec expressions from reaching testSIV (PR #154980)

Sebastian Pop via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 25 12:57:54 PST 2025


https://github.com/sebpop updated https://github.com/llvm/llvm-project/pull/154980

>From 0ae1000a9b86f4b253a6eced860420c89ebaaf8c Mon Sep 17 00:00:00 2001
From: Sebastian Pop <spop at nvidia.com>
Date: Tue, 25 Nov 2025 15:56:39 -0500
Subject: [PATCH] [DA] add testcases for bug #148435

---
 .../Analysis/DependenceAnalysis/PR148435.ll   | 86 +++++++++++++++++++
 .../DependenceAnalysis/bounds-check.ll        | 27 ++++++
 .../DependenceAnalysis/wrapping-addrec-1.ll   | 35 ++++++++
 .../DependenceAnalysis/wrapping-addrec.ll     | 33 +++++++
 4 files changed, 181 insertions(+)
 create mode 100644 llvm/test/Analysis/DependenceAnalysis/PR148435.ll
 create mode 100644 llvm/test/Analysis/DependenceAnalysis/bounds-check.ll
 create mode 100644 llvm/test/Analysis/DependenceAnalysis/wrapping-addrec-1.ll
 create mode 100644 llvm/test/Analysis/DependenceAnalysis/wrapping-addrec.ll

diff --git a/llvm/test/Analysis/DependenceAnalysis/PR148435.ll b/llvm/test/Analysis/DependenceAnalysis/PR148435.ll
new file mode 100644
index 0000000000000..54aa9c9399985
--- /dev/null
+++ b/llvm/test/Analysis/DependenceAnalysis/PR148435.ll
@@ -0,0 +1,86 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -disable-output "-passes=print<da>" 2>&1 | FileCheck %s
+
+define void @_Z1cb(ptr %a) {
+; CHECK-LABEL: '_Z1cb'
+; CHECK-NEXT:  Src: store i8 0, ptr %arrayidx9, align 1 --> Dst: store i8 0, ptr %arrayidx9, align 1
+; CHECK-NEXT:    da analyze - output [*]!
+;
+entry:
+  br label %for.body
+
+for.cond.cleanup.loopexit:                        ; preds = %for.body
+  ret void
+
+for.body:                                         ; preds = %for.body, %entry
+  %indvars.iv23 = phi i64 [ 0, %entry ], [ %indvars.iv.next24, %for.body ]
+  %idxprom = and i64 %indvars.iv23, 1
+  %arrayidx9 = getelementptr inbounds [0 x [12 x [12 x i8]]], ptr %a, i64 0, i64 %idxprom, i64 0, i64 %indvars.iv23
+  store i8 0, ptr %arrayidx9, align 1
+  %indvars.iv.next24 = add i64 %indvars.iv23, 1
+  %exitcond.not = icmp eq i64 %indvars.iv.next24, 0
+  br i1 %exitcond.not, label %for.cond.cleanup.loopexit, label %for.body
+}
+
+ at a = external global [0 x [12 x [12 x i8]]], align 1
+
+define void @test_siv_no_addrec(i1 %d, i32 %b) {
+; CHECK-LABEL: 'test_siv_no_addrec'
+; CHECK-NEXT:  Src: store i8 0, ptr %arrayidx7, align 1 --> Dst: store i8 0, ptr %arrayidx7, align 1
+; CHECK-NEXT:    da analyze - output [* *]!
+;
+entry:
+  %conv.val = select i1 %d, i16 1, i16 0
+  br label %for.cond
+
+for.cond:                                         ; preds = %for.inc8, %entry
+  %e.0 = phi i32 [ %b, %entry ], [ %inc9, %for.inc8 ]
+  %cmp = icmp ult i32 %e.0, 10
+  br i1 %cmp, label %for.cond1, label %for.end10
+
+for.cond1:                                        ; preds = %for.inc, %for.cond
+  %f.0 = phi i16 [ %conv.val, %for.cond ], [ %add, %for.inc ]
+  %cmp2 = icmp slt i16 %f.0, 10
+  br i1 %cmp2, label %for.body4, label %for.inc8
+
+for.body4:                                        ; preds = %for.cond1
+  %sub = add i32 %e.0, -3
+  %idxprom = zext i32 %sub to i64
+  %idxprom5 = sext i16 %f.0 to i64
+  %idxprom6 = zext i32 %e.0 to i64
+  %arrayidx7 = getelementptr inbounds [0 x [12 x [12 x i8]]], ptr @a, i64 0, i64 %idxprom, i64 %idxprom5, i64 %idxprom6
+  store i8 0, ptr %arrayidx7, align 1
+  br label %for.inc
+
+for.inc:                                          ; preds = %for.body4
+  %add = add i16 %f.0, 2
+  br label %for.cond1
+
+for.inc8:                                         ; preds = %for.cond1
+  %inc9 = add i32 %e.0, 1
+  br label %for.cond
+
+for.end10:                                        ; preds = %for.cond
+  ret void
+}
+
+define void @f1(ptr %a) {
+; CHECK-LABEL: 'f1'
+; CHECK-NEXT:  Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
+; CHECK-NEXT:    da analyze - output [*]!
+;
+entry:
+  br label %loop
+
+loop:
+  %i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
+  %and = and i64 %i, 1
+  %idx = getelementptr inbounds [4 x [4 x i8]], ptr %a, i64 0, i64 %and, i64 %and
+  store i8 0, ptr %idx
+  %i.next = add i64 %i, 1
+  %exitcond.not = icmp slt i64 %i.next, 8
+  br i1 %exitcond.not, label %loop, label %exit
+
+exit:
+  ret void
+}
diff --git a/llvm/test/Analysis/DependenceAnalysis/bounds-check.ll b/llvm/test/Analysis/DependenceAnalysis/bounds-check.ll
new file mode 100644
index 0000000000000..86086f77d2a47
--- /dev/null
+++ b/llvm/test/Analysis/DependenceAnalysis/bounds-check.ll
@@ -0,0 +1,27 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -disable-output "-passes=print<da>" 2>&1 | FileCheck %s
+
+; Test case for SmallBitVector bounds checking bug in DependenceAnalysis.
+; This test ensures that loop index mapping functions don't cause out-of-bounds
+; access to SmallBitVector when loop depths exceed MaxLevels.
+
+define void @bounds_check_test(ptr %a) {
+; CHECK-LABEL: 'bounds_check_test'
+; CHECK-NEXT:  Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
+; CHECK-NEXT:    da analyze - output [*]!
+;
+entry:
+  br label %loop
+
+loop:
+  %i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
+  %and = and i64 %i, 1  ; Creates index 0 or 1
+  %idx = getelementptr inbounds [4 x [4 x i8]], ptr %a, i64 0, i64 %and, i64 %i
+  store i8 0, ptr %idx
+  %i.next = add i64 %i, 1
+  %exitcond.not = icmp slt i64 %i.next, 4
+  br i1 %exitcond.not, label %loop, label %exit
+
+exit:
+  ret void
+}
diff --git a/llvm/test/Analysis/DependenceAnalysis/wrapping-addrec-1.ll b/llvm/test/Analysis/DependenceAnalysis/wrapping-addrec-1.ll
new file mode 100644
index 0000000000000..00ce2e91809c5
--- /dev/null
+++ b/llvm/test/Analysis/DependenceAnalysis/wrapping-addrec-1.ll
@@ -0,0 +1,35 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -disable-output "-passes=print<da>" 2>&1 | FileCheck %s
+
+; Test case for bug #148435 - SIV test assertion failure
+
+define void @f(ptr %a) {
+; CHECK-LABEL: 'f'
+; CHECK-NEXT:  Src: store i8 42, ptr %idx, align 1 --> Dst: store i8 42, ptr %idx, align 1
+; CHECK-NEXT:    da analyze - output [* *]!
+;
+entry:
+  br label %loop.i.header
+
+loop.i.header:
+  %i = phi i64 [ 0, %entry ], [ %i.next, %loop.i.latch ]
+  %and.i = and i64 %i, 1
+  br label %loop.j
+
+loop.j:
+  %j = phi i64 [ 0, %loop.i.header ], [ %j.next, %loop.j ]
+  %and.j = and i64 %j, 1
+  %idx = getelementptr [2 x [2 x i8]], ptr %a, i64 0, i64 %and.i, i64 %and.j
+  store i8 42, ptr %idx
+  %j.next = add i64 %j, 1
+  %exitcond.j = icmp eq i64 %j.next, 100
+ br i1 %exitcond.j, label %loop.i.latch, label %loop.j
+
+loop.i.latch:
+  %i.next = add i64 %i, 1
+  %exitcond.i = icmp eq i64 %i.next, 100
+  br i1 %exitcond.i, label %exit, label %loop.i.header
+
+exit:
+  ret void
+}
diff --git a/llvm/test/Analysis/DependenceAnalysis/wrapping-addrec.ll b/llvm/test/Analysis/DependenceAnalysis/wrapping-addrec.ll
new file mode 100644
index 0000000000000..a1693e9d66575
--- /dev/null
+++ b/llvm/test/Analysis/DependenceAnalysis/wrapping-addrec.ll
@@ -0,0 +1,33 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -disable-output "-passes=print<da>" 2>&1 | FileCheck %s
+
+; Test case for wrapping AddRec detection in DependenceAnalysis.
+; This ensures that AddRec expressions that wrap (creating cyclic rather than
+; linear patterns) are rejected from SIV analysis and treated conservatively.
+
+; This test case has a clear dependence pattern that was incorrectly reported as "none!"
+; The issue: {false,+,true} in i1 arithmetic creates pattern (0,1,0,1,0,1,...).
+; - i=0: a[0][0][0], i=1: a[0][1][1], i=2: a[0][0][0], i=3: a[0][1][1], ...
+; - Clear dependencies at distances 2, 4, 6 between iterations accessing same locations.
+; - Strong SIV test was missing these due to treating wrapping pattern as linear.
+
+define void @test_wrapping_i1_addrec(ptr %a) {
+; CHECK-LABEL: 'test_wrapping_i1_addrec'
+; CHECK-NEXT:  Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
+; CHECK-NEXT:    da analyze - output [*]!
+;
+entry:
+  br label %loop
+
+loop:
+  %i = phi i64 [ 0, %entry ], [ %i.next, %loop ]
+  %and = and i64 %i, 1
+  %idx = getelementptr inbounds [4 x [4 x i8]], ptr %a, i64 0, i64 %and, i64 %and
+  store i8 0, ptr %idx
+  %i.next = add i64 %i, 1
+  %exitcond.not = icmp slt i64 %i.next, 8
+  br i1 %exitcond.not, label %loop, label %exit
+
+exit:
+  ret void
+}



More information about the llvm-commits mailing list