From 774a2392fb390f9e78bf7ede1c9a50051205a132 Mon Sep 17 00:00:00 2001 From: Ryotaro Kasuga 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-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}<%loop.i.header>,+,1}<%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}<%loop.i.header>,+,1}<%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}<%loop.i.header>,+,1}<%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 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 ]