[llvm] [DA] Add tests for nsw doesn't hold on entier iteration (PR #162281)
Ryotaro Kasuga via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 7 08:46:51 PST 2025
https://github.com/kasuga-fj updated https://github.com/llvm/llvm-project/pull/162281
>From 774a2392fb390f9e78bf7ede1c9a50051205a132 Mon Sep 17 00:00:00 2001
From: Ryotaro Kasuga <kasuga.ryotaro at fujitsu.com>
Date: Tue, 7 Oct 2025 12:56:14 +0000
Subject: [PATCH 1/2] [DA] Add tests for nsw doesn't hold on entier iteration
---
.../monotonicity-loop-guard.ll | 141 ++++++++++++++++++
1 file changed, 141 insertions(+)
create mode 100644 llvm/test/Analysis/DependenceAnalysis/monotonicity-loop-guard.ll
diff --git a/llvm/test/Analysis/DependenceAnalysis/monotonicity-loop-guard.ll b/llvm/test/Analysis/DependenceAnalysis/monotonicity-loop-guard.ll
new file mode 100644
index 0000000000000..72d881b3b0664
--- /dev/null
+++ b/llvm/test/Analysis/DependenceAnalysis/monotonicity-loop-guard.ll
@@ -0,0 +1,141 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --version 6
+; RUN: opt < %s -disable-output -passes="print<da>" -da-dump-monotonicity-report \
+; RUN: -da-enable-monotonicity-check 2>&1 | FileCheck %s
+
+; for (i = 0; i < INT64_MAX - 1; i++)
+; if (i < 1000)
+; for (j = 0; j < 2000; j++)
+; a[i + j] = 0;
+;
+; FIXME: This is not monotonic. The nsw flag is valid under
+; the condition i < 1000, not for all i.
+define void @nsw_under_loop_guard0(ptr %a) {
+; CHECK-LABEL: 'nsw_under_loop_guard0'
+; CHECK-NEXT: Monotonicity check:
+; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
+; CHECK-NEXT: Expr: {{\{\{}}0,+,1}<nuw><nsw><%loop.i.header>,+,1}<nuw><nsw><%loop.j>
+; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
+; CHECK-EMPTY:
+; 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.i.header
+
+loop.i.header:
+ %i = phi i64 [ 0 , %entry ], [ %i.next, %loop.i.latch ]
+ br label %loop.j.pr
+
+loop.j.pr:
+ %guard.j = icmp slt i64 %i, 1000
+ br i1 %guard.j, label %loop.j, label %exit
+
+loop.j:
+ %j = phi i64 [ 0, %loop.j.pr ], [ %j.next, %loop.j ]
+ %offset = add nsw i64 %i, %j
+ %idx = getelementptr inbounds i8, ptr %a, i64 %offset
+ store i8 0, ptr %idx
+ %j.next = add nsw i64 %j, 1
+ %exitcond.j = icmp eq i64 %j.next, 2000
+ br i1 %exitcond.j, label %loop.i.latch, label %loop.j
+
+loop.i.latch:
+ %i.next = add nsw i64 %i, 1
+ %exitcond.i = icmp eq i64 %i.next, 9223372036854775807
+ br i1 %exitcond.i, label %exit, label %loop.i.header
+
+exit:
+ ret void
+}
+
+; for (i = 0; i < 100; i++)
+; if (i < 1000)
+; for (j = 0; j < 100; j++)
+; a[i + j] = 0;
+;
+; The loop guard is always true, so the nsw flag is valid for all i.
+define void @nsw_under_loop_guard1(ptr %a) {
+; CHECK-LABEL: 'nsw_under_loop_guard1'
+; CHECK-NEXT: Monotonicity check:
+; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
+; CHECK-NEXT: Expr: {{\{\{}}0,+,1}<nuw><nsw><%loop.i.header>,+,1}<nuw><nsw><%loop.j>
+; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
+; CHECK-EMPTY:
+; 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.i.header
+
+loop.i.header:
+ %i = phi i64 [ 0 , %entry ], [ %i.next, %loop.i.latch ]
+ br label %loop.j.pr
+
+loop.j.pr:
+ %guard.j = icmp slt i64 %i, 1000
+ br i1 %guard.j, label %loop.j, label %exit
+
+loop.j:
+ %j = phi i64 [ 0, %loop.j.pr ], [ %j.next, %loop.j ]
+ %val = phi i64 [ %i, %loop.j.pr ], [ %val.next, %loop.j ]
+ %j.next = add nsw i64 %j, 1
+ %idx = getelementptr inbounds i8, ptr %a, i64 %val
+ store i8 0, ptr %idx
+ %val.next = add nsw i64 %val, 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 nsw i64 %i, 1
+ %exitcond.i = icmp eq i64 %i.next, 100
+ br i1 %exitcond.i, label %exit, label %loop.i.header
+
+exit:
+ ret void
+}
+
+; for (i = 0; i < n; i++)
+; if (i < m)
+; for (j = 0; j < k; j++)
+; a[i + j] = 0;
+;
+; The nsw flag may valid under the condition i < k.
+define void @nsw_under_loop_guard2(ptr %a, i64 %n, i64 %m, i64 %k) {
+; CHECK-LABEL: 'nsw_under_loop_guard2'
+; CHECK-NEXT: Monotonicity check:
+; CHECK-NEXT: Inst: store i8 0, ptr %idx, align 1
+; CHECK-NEXT: Expr: {{\{\{}}0,+,1}<nuw><nsw><%loop.i.header>,+,1}<nuw><nsw><%loop.j>
+; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
+; CHECK-EMPTY:
+; 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.i.header
+
+loop.i.header:
+ %i = phi i64 [ 0 , %entry ], [ %i.next, %loop.i.latch ]
+ br label %loop.j.pr
+
+loop.j.pr:
+ %guard.j = icmp slt i64 %i, %m
+ br i1 %guard.j, label %loop.j, label %exit
+
+loop.j:
+ %j = phi i64 [ 0, %loop.j.pr ], [ %j.next, %loop.j ]
+ %val = phi i64 [ %i, %loop.j.pr ], [ %val.next, %loop.j ]
+ %j.next = add nsw i64 %j, 1
+ %idx = getelementptr inbounds i8, ptr %a, i64 %val
+ store i8 0, ptr %idx
+ %val.next = add nsw i64 %val, 1
+ %exitcond.j = icmp eq i64 %j.next, %k
+ br i1 %exitcond.j, label %loop.i.latch, label %loop.j
+
+loop.i.latch:
+ %i.next = add nsw i64 %i, 1
+ %exitcond.i = icmp eq i64 %i.next, %n
+ br i1 %exitcond.i, label %exit, label %loop.i.header
+
+exit:
+ ret void
+}
>From 243205136b53edc1327f73f9e63e368d9a650f0b Mon Sep 17 00:00:00 2001
From: Ryotaro Kasuga <kasuga.ryotaro at fujitsu.com>
Date: Sat, 8 Nov 2025 01:46:26 +0900
Subject: [PATCH 2/2] fix the br argument
---
.../Analysis/DependenceAnalysis/monotonicity-loop-guard.ll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/test/Analysis/DependenceAnalysis/monotonicity-loop-guard.ll b/llvm/test/Analysis/DependenceAnalysis/monotonicity-loop-guard.ll
index 72d881b3b0664..5358ff442b8e3 100644
--- a/llvm/test/Analysis/DependenceAnalysis/monotonicity-loop-guard.ll
+++ b/llvm/test/Analysis/DependenceAnalysis/monotonicity-loop-guard.ll
@@ -17,7 +17,7 @@ define void @nsw_under_loop_guard0(ptr %a) {
; CHECK-NEXT: Monotonicity: MultivariateSignedMonotonic
; CHECK-EMPTY:
; CHECK-NEXT: Src: store i8 0, ptr %idx, align 1 --> Dst: store i8 0, ptr %idx, align 1
-; CHECK-NEXT: da analyze - output [* *]!
+; CHECK-NEXT: da analyze - none!
;
entry:
br label %loop.i.header
@@ -28,7 +28,7 @@ loop.i.header:
loop.j.pr:
%guard.j = icmp slt i64 %i, 1000
- br i1 %guard.j, label %loop.j, label %exit
+ br i1 %guard.j, label %loop.j, label %loop.i.latch
loop.j:
%j = phi i64 [ 0, %loop.j.pr ], [ %j.next, %loop.j ]
More information about the llvm-commits
mailing list