[llvm] [IndVarSimplify][NFC] Add precommit test for umax subset ule folding (PR #213295)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 31 08:39:23 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Aleksandr Popov (aleks-tmb)

<details>
<summary>Changes</summary>

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

---
Full diff: https://github.com/llvm/llvm-project/pull/213295.diff


1 Files Affected:

- (added) llvm/test/Transforms/IndVarSimplify/umax-subset-ule.ll (+80) 


``````````diff
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
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/213295


More information about the llvm-commits mailing list