[llvm] [InstCombine] Use context in select-to-umin nonzero check (PR #225381)
Nopileos Isemados via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 22 05:14:45 PDT 2026
https://github.com/134ARG created https://github.com/llvm/llvm-project/pull/225381
foldSelectICmpMinMax() queries whether W is nonzero without an instruction context, missing facts from a preceding llvm.assume or dominating branch. Querying at the comparison enables the existing select-to-umin fold.
Fix #225345
>From 94d38e697d4ef010516e8b4b22824e45b1cb2ab5 Mon Sep 17 00:00:00 2001
From: 134ARG <xen134 at outlook.com>
Date: Tue, 22 Sep 2026 17:31:02 +0800
Subject: [PATCH] [InstCombine] Use context in select-to-umin nonzero check
Query the decrement operand at the comparison so the existing fold can use a dominating assume or branch fact. Cover both positive contexts and the no-fact case in minmax-fold.ll.
---
.../InstCombine/InstCombineSelect.cpp | 2 +-
.../Transforms/InstCombine/minmax-fold.ll | 48 +++++++++++++++++++
2 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index a4061bbd60770..39564744aec33 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -732,7 +732,7 @@ static Value *foldSelectICmpMinMax(const ICmpInst *Cmp, Value *TVal,
// canonicalized to "add %x, -1" discarding the nuw flag.
if (Pred == CmpInst::ICMP_ULT &&
match(FVal, m_Add(m_Specific(CmpRHS), m_AllOnes())) &&
- isKnownNonZero(CmpRHS, SQ)) {
+ isKnownNonZero(CmpRHS, SQ.getWithInstruction(Cmp))) {
cast<Instruction>(FVal)->setHasNoSignedWrap(false);
cast<Instruction>(FVal)->setHasNoUnsignedWrap(false);
return Builder.CreateBinaryIntrinsic(Intrinsic::umin, TVal, FVal);
diff --git a/llvm/test/Transforms/InstCombine/minmax-fold.ll b/llvm/test/Transforms/InstCombine/minmax-fold.ll
index 3234ed5055f80..b6ef57286472b 100644
--- a/llvm/test/Transforms/InstCombine/minmax-fold.ll
+++ b/llvm/test/Transforms/InstCombine/minmax-fold.ll
@@ -1647,6 +1647,54 @@ define i32 @test_umin_sub1_nuw(i32 %x, i32 range(i32 1, 0) %w) {
ret i32 %r
}
+declare void @llvm.assume(i1)
+
+define i32 @test_umin_sub1_assume_nonzero(i32 %x, i32 %w) {
+; CHECK-LABEL: @test_umin_sub1_assume_nonzero(
+; CHECK: call void @llvm.assume(i1
+; CHECK: [[SUB:%.*]] = add i32 [[W:%.*]], -1
+; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.umin.i32(i32 [[X:%.*]], i32 [[SUB]])
+; CHECK-NEXT: ret i32 [[R]]
+ %nonzero = icmp ne i32 %w, 0
+ call void @llvm.assume(i1 %nonzero)
+ %cmp = icmp ult i32 %x, %w
+ %sub = add i32 %w, -1
+ %r = select i1 %cmp, i32 %x, i32 %sub
+ ret i32 %r
+}
+
+define i32 @test_umin_sub1_guard_nonzero(i32 %x, i32 %w) {
+; CHECK-LABEL: @test_umin_sub1_guard_nonzero(
+; CHECK: use:
+; CHECK: [[SUB:%.*]] = add i32 [[W:%.*]], -1
+; CHECK-NEXT: [[R:%.*]] = call i32 @llvm.umin.i32(i32 [[X:%.*]], i32 [[SUB]])
+; CHECK-NEXT: ret i32 [[R]]
+entry:
+ %zero = icmp eq i32 %w, 0
+ br i1 %zero, label %zero.bb, label %use
+
+zero.bb:
+ ret i32 0
+
+use:
+ %cmp = icmp ult i32 %x, %w
+ %sub = add i32 %w, -1
+ %r = select i1 %cmp, i32 %x, i32 %sub
+ ret i32 %r
+}
+
+define i32 @test_umin_sub1_unknown_nonzero(i32 %x, i32 %w) {
+; CHECK-LABEL: @test_umin_sub1_unknown_nonzero(
+; CHECK: [[CMP:%.*]] = icmp ult i32 [[X:%.*]], [[W:%.*]]
+; CHECK-NEXT: [[SUB:%.*]] = add i32 [[W]], -1
+; CHECK-NEXT: [[R:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[SUB]]
+; CHECK-NEXT: ret i32 [[R]]
+ %cmp = icmp ult i32 %x, %w
+ %sub = add i32 %w, -1
+ %r = select i1 %cmp, i32 %x, i32 %sub
+ ret i32 %r
+}
+
define i32 @test_smin_sub1_nsw_swapped(i32 %x, i32 %w) {
; CHECK-LABEL: @test_smin_sub1_nsw_swapped(
; CHECK-NEXT: [[SUB:%.*]] = add nsw i32 [[W:%.*]], -1
More information about the llvm-commits
mailing list