[llvm] [IndVarSimplify][NFC] Add precommit test for umax subset ule folding (PR #213295)
Aleksandr Popov via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 31 08:38:39 PDT 2026
https://github.com/aleks-tmb created https://github.com/llvm/llvm-project/pull/213295
Adds test coverage for the case where umax(a, b) u<= umax(a, b, c) is trivially true and IndVarSimplify folds the header exit branch, along with a negative test that must be preserved.
See https://github.com/llvm/llvm-project/issues/213291
>From 3f91601bb6dd42d88ea083f1eda55a39a28ce748 Mon Sep 17 00:00:00 2001
From: Aleksandr Popov <apopov at azul.com>
Date: Fri, 31 Jul 2026 14:39:59 +0000
Subject: [PATCH] [IndVarSimplify][NFC] Add precommit test for umax subset ule
folding
Adds test coverage for the case where umax(a, b) u<= umax(a, b, c) is
trivially true and IndVarSimplify folds the header exit branch, along
with a negative test that must be preserved.
See https://github.com/llvm/llvm-project/issues/213291
---
.../IndVarSimplify/umax-subset-ule.ll | 80 +++++++++++++++++++
1 file changed, 80 insertions(+)
create mode 100644 llvm/test/Transforms/IndVarSimplify/umax-subset-ule.ll
diff --git a/llvm/test/Transforms/IndVarSimplify/umax-subset-ule.ll b/llvm/test/Transforms/IndVarSimplify/umax-subset-ule.ll
new file mode 100644
index 0000000000000..f20f7ad7e9876
--- /dev/null
+++ b/llvm/test/Transforms/IndVarSimplify/umax-subset-ule.ll
@@ -0,0 +1,80 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt -passes=indvars -S < %s | FileCheck %s
+
+declare void @side_effect()
+
+; TODO: umax(a, b) u<= umax(a, b, c) is trivially true, so the header exit is
+; unreachable and IndVarSimplify replaces its branch condition with true.
+define void @umax_subset_ule_folded(i32 %n, i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @umax_subset_ule_folded(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
+; CHECK-NEXT: [[M1:%.*]] = call i32 @llvm.umax.i32(i32 [[A:%.*]], i32 [[B:%.*]])
+; CHECK-NEXT: [[TMP:%.*]] = call i32 @llvm.umax.i32(i32 [[A]], i32 [[C:%.*]])
+; CHECK-NEXT: [[M2:%.*]] = call i32 @llvm.umax.i32(i32 [[TMP]], i32 [[B]])
+; CHECK-NEXT: [[INV_COND:%.*]] = icmp ule i32 [[M1]], [[M2]]
+; CHECK-NEXT: br i1 [[INV_COND]], label [[LATCH]], label [[EXIT:%.*]]
+; CHECK: latch:
+; CHECK-NEXT: call void @side_effect()
+; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 1
+; CHECK-NEXT: [[EXIT_CMP:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]]
+; CHECK-NEXT: br i1 [[EXIT_CMP]], label [[LOOP]], label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %loop
+loop:
+ %iv = phi i32 [ 0, %entry ], [ %iv.next, %latch ]
+ %m1 = call i32 @llvm.umax.i32(i32 %a, i32 %b)
+ %tmp = call i32 @llvm.umax.i32(i32 %a, i32 %c)
+ %m2 = call i32 @llvm.umax.i32(i32 %tmp, i32 %b)
+ %inv.cond = icmp ule i32 %m1, %m2
+ br i1 %inv.cond, label %latch, label %exit
+latch:
+ call void @side_effect()
+ %iv.next = add nuw i32 %iv, 1
+ %exit.cmp = icmp ult i32 %iv.next, %n
+ br i1 %exit.cmp, label %loop, label %exit
+exit:
+ ret void
+}
+
+; Negative test: umax(a, c) is NOT a subset of umax(a, b), so the compare must
+; remain and the exit branch is preserved.
+define void @umax_not_subset_ule_kept(i32 %n, i32 %a, i32 %b, i32 %c) {
+; CHECK-LABEL: @umax_not_subset_ule_kept(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[M1:%.*]] = call i32 @llvm.umax.i32(i32 [[A:%.*]], i32 [[C:%.*]])
+; CHECK-NEXT: [[M2:%.*]] = call i32 @llvm.umax.i32(i32 [[A]], i32 [[B:%.*]])
+; CHECK-NEXT: [[INV_COND:%.*]] = icmp ule i32 [[M1]], [[M2]]
+; CHECK-NEXT: br label [[LOOP:%.*]]
+; CHECK: loop:
+; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LATCH:%.*]] ]
+; CHECK-NEXT: br i1 [[INV_COND]], label [[LATCH]], label [[EXIT:%.*]]
+; CHECK: latch:
+; CHECK-NEXT: call void @side_effect()
+; CHECK-NEXT: [[IV_NEXT]] = add nuw i32 [[IV]], 1
+; CHECK-NEXT: [[EXIT_CMP:%.*]] = icmp ult i32 [[IV_NEXT]], [[N:%.*]]
+; CHECK-NEXT: br i1 [[EXIT_CMP]], label [[LOOP]], label [[EXIT]]
+; CHECK: exit:
+; CHECK-NEXT: ret void
+;
+entry:
+ %m1 = call i32 @llvm.umax.i32(i32 %a, i32 %c)
+ %m2 = call i32 @llvm.umax.i32(i32 %a, i32 %b)
+ %inv.cond = icmp ule i32 %m1, %m2
+ br label %loop
+loop:
+ %iv = phi i32 [ 0, %entry ], [ %iv.next, %latch ]
+ br i1 %inv.cond, label %latch, label %exit
+latch:
+ call void @side_effect()
+ %iv.next = add nuw i32 %iv, 1
+ %exit.cmp = icmp ult i32 %iv.next, %n
+ br i1 %exit.cmp, label %loop, label %exit
+exit:
+ ret void
+}
More information about the llvm-commits
mailing list