[llvm] [InstCombine] Fold npos select around umin (PR #202748)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 12 11:49:50 PDT 2026


https://github.com/robertvirany updated https://github.com/llvm/llvm-project/pull/202748

>From 6e3a0c266fcaa68987e7087d2856cb7eaac0d7de Mon Sep 17 00:00:00 2001
From: Robert Virany <robertvirany at gmail.com>
Date: Tue, 9 Jun 2026 15:28:14 -0400
Subject: [PATCH] [InstCombine] Fold npos select around umin

---
 llvm/lib/Analysis/InstructionSimplify.cpp     | 23 +++++++
 llvm/test/Transforms/InstCombine/umin-icmp.ll | 61 +++++++++++++++++++
 2 files changed, 84 insertions(+)

diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp
index 81debece796b1..12db58be4d224 100644
--- a/llvm/lib/Analysis/InstructionSimplify.cpp
+++ b/llvm/lib/Analysis/InstructionSimplify.cpp
@@ -4526,6 +4526,29 @@ static Value *simplifyWithOpsReplaced(Value *V,
 
         return ConstantInt::get(I->getType(), 0);
       }
+
+      // umin(-1, x) -> x
+      // umin(x, -1) -> x
+      if (auto *MMI = dyn_cast<MinMaxIntrinsic>(II)) {
+        if (MMI->getIntrinsicID() == Intrinsic::umin) {
+          Value *Result = nullptr;
+          if (match(NewOps[0], m_AllOnes()))
+            Result = NewOps[1];
+          else if (match(NewOps[1], m_AllOnes()))
+            Result = NewOps[0];
+
+          if (Result) {
+            if (II->hasPoisonGeneratingAnnotations()) {
+              if (!DropFlags)
+                return nullptr;
+
+              DropFlags->push_back(II);
+            }
+
+            return Result;
+          }
+        }
+      }
     }
 
     if (isa<GetElementPtrInst>(I)) {
diff --git a/llvm/test/Transforms/InstCombine/umin-icmp.ll b/llvm/test/Transforms/InstCombine/umin-icmp.ll
index cb23b2f00d292..7a1591e098b2b 100644
--- a/llvm/test/Transforms/InstCombine/umin-icmp.ll
+++ b/llvm/test/Transforms/InstCombine/umin-icmp.ll
@@ -805,3 +805,64 @@ end:
 }
 
 declare i32 @llvm.umin.i32(i32, i32)
+declare i64 @llvm.umin.i64(i64, i64)
+declare i64 @llvm.umax.i64(i64, i64)
+
+define i64 @select_npos_umin(i64 %pos, i64 %len) {
+; CHECK-LABEL: @select_npos_umin(
+; CHECK-NEXT:    [[CLAMPED:%.*]] = call i64 @llvm.umin.i64(i64 [[POS:%.*]], i64 [[LEN:%.*]])
+; CHECK-NEXT:    ret i64 [[CLAMPED]]
+;
+  %is_npos = icmp eq i64 %pos, -1
+  %clamped = call i64 @llvm.umin.i64(i64 %pos, i64 %len)
+  %out = select i1 %is_npos, i64 %len, i64 %clamped
+  ret i64 %out
+}
+
+define i64 @select_not_npos_umin(i64 %pos, i64 %len) {
+; CHECK-LABEL: @select_not_npos_umin(
+; CHECK-NEXT:    [[CLAMPED:%.*]] = call i64 @llvm.umin.i64(i64 [[POS:%.*]], i64 [[LEN:%.*]])
+; CHECK-NEXT:    ret i64 [[CLAMPED]]
+;
+  %is_not_npos = icmp ne i64 %pos, -1
+  %clamped = call i64 @llvm.umin.i64(i64 %pos, i64 %len)
+  %out = select i1 %is_not_npos, i64 %clamped, i64 %len
+  ret i64 %out
+}
+
+define i64 @select_npos_umin_commuted(i64 %pos, i64 %len) {
+; CHECK-LABEL: @select_npos_umin_commuted(
+; CHECK-NEXT:    [[CLAMPED:%.*]] = call i64 @llvm.umin.i64(i64 [[LEN:%.*]], i64 [[POS:%.*]])
+; CHECK-NEXT:    ret i64 [[CLAMPED]]
+;
+  %is_npos = icmp eq i64 %pos, -1
+  %clamped = call i64 @llvm.umin.i64(i64 %len, i64 %pos)
+  %out = select i1 %is_npos, i64 %len, i64 %clamped
+  ret i64 %out
+}
+
+define i64 @select_npos_umax_negative(i64 %pos, i64 %len) {
+; CHECK-LABEL: @select_npos_umax_negative(
+; CHECK-NEXT:    [[IS_NPOS:%.*]] = icmp eq i64 [[POS:%.*]], -1
+; CHECK-NEXT:    [[CLAMPED:%.*]] = call i64 @llvm.umax.i64(i64 [[POS]], i64 [[LEN:%.*]])
+; CHECK-NEXT:    [[OUT:%.*]] = select i1 [[IS_NPOS]], i64 [[LEN]], i64 [[CLAMPED]]
+; CHECK-NEXT:    ret i64 [[OUT]]
+;
+  %is_npos = icmp eq i64 %pos, -1
+  %clamped = call i64 @llvm.umax.i64(i64 %pos, i64 %len)
+  %out = select i1 %is_npos, i64 %len, i64 %clamped
+  ret i64 %out
+}
+
+define i64 @select_npos_wrong_bound_negative(i64 %pos, i64 %len, i64 %other) {
+; CHECK-LABEL: @select_npos_wrong_bound_negative(
+; CHECK-NEXT:    [[IS_NPOS:%.*]] = icmp eq i64 [[POS:%.*]], -1
+; CHECK-NEXT:    [[CLAMPED:%.*]] = call i64 @llvm.umin.i64(i64 [[POS]], i64 [[LEN:%.*]])
+; CHECK-NEXT:    [[OUT:%.*]] = select i1 [[IS_NPOS]], i64 [[OTHER:%.*]], i64 [[CLAMPED]]
+; CHECK-NEXT:    ret i64 [[OUT]]
+;
+  %is_npos = icmp eq i64 %pos, -1
+  %clamped = call i64 @llvm.umin.i64(i64 %pos, i64 %len)
+  %out = select i1 %is_npos, i64 %other, i64 %clamped
+  ret i64 %out
+}



More information about the llvm-commits mailing list