[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