[llvm] [InstCombine] Fold `umax(nuw_shl(C0, x), nuw_shl(C0, y)) -> nuw_shl(C0, umax(x, y))` and `umin(nuw_shl(C0, x), nuw_shl(C0, y)) -> nuw_shl(C0, umin(x, y))` (PR #131076)

via llvm-commits llvm-commits at lists.llvm.org
Thu Mar 13 00:15:51 PDT 2025


https://github.com/el-ev updated https://github.com/llvm/llvm-project/pull/131076

>From 3ea75f4f4aad38cbef547467265ca3d67c5245a6 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Thu, 13 Mar 2025 11:55:01 +0800
Subject: [PATCH 1/4] [InstCombine] Add pre-commit tests

---
 .../Transforms/InstCombine/shift-uminmax.ll   | 240 ++++++++++++++++++
 1 file changed, 240 insertions(+)
 create mode 100644 llvm/test/Transforms/InstCombine/shift-uminmax.ll

diff --git a/llvm/test/Transforms/InstCombine/shift-uminmax.ll b/llvm/test/Transforms/InstCombine/shift-uminmax.ll
new file mode 100644
index 0000000000000..9e61f2f054867
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/shift-uminmax.ll
@@ -0,0 +1,240 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+; For the following patterns:
+; umax(nuw_shl(C0, x), nuw_shl(C0, y)) -> nuw_shl(C0, umax(x, y))
+; umin(nuw_shl(C0, x), nuw_shl(C0, y)) -> nuw_shl(C0, umin(x, y))
+
+define i32 @test_umax_shl_const1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umax_shl_const1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    ret i32 [[MAX]]
+;
+  %shl_x = shl nuw i32 1, %x
+  %shl_y = shl nuw i32 1, %y
+  %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
+  ret i32 %max
+}
+
+define i32 @test_umin_shl_const1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umin_shl_const1(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    ret i32 [[MIN]]
+;
+  %shl_x = shl nuw i32 1, %x
+  %shl_y = shl nuw i32 1, %y
+  %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+  ret i32 %min
+}
+
+define i32 @test_umax_shl_const5(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umax_shl_const5(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 5, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 5, [[Y]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    ret i32 [[MAX]]
+;
+  %shl_x = shl nuw i32 5, %x
+  %shl_y = shl nuw i32 5, %y
+  %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
+  ret i32 %max
+}
+
+define i32 @test_umin_shl_const5(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umin_shl_const5(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 5, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 5, [[Y]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    ret i32 [[MIN]]
+;
+  %shl_x = shl nuw i32 5, %x
+  %shl_y = shl nuw i32 5, %y
+  %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+  ret i32 %min
+}
+
+declare void @use(i8)
+
+define i32 @test_umax_shl_const1_multi_use(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umax_shl_const1_multi_use(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
+; CHECK-NEXT:    call void @use(i32 [[SHL_X]])
+; CHECK-NEXT:    call void @use(i32 [[SHL_Y]])
+; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    ret i32 [[MAX]]
+;
+  %shl_x = shl nuw i32 1, %x
+  %shl_y = shl nuw i32 1, %y
+  call void @use(i32 %shl_x)
+  call void @use(i32 %shl_y)
+  %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
+  ret i32 %max
+}
+
+define i32 @test_umin_shl_const1_multi_use(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umin_shl_const1_multi_use(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
+; CHECK-NEXT:    call void @use(i32 [[SHL_X]])
+; CHECK-NEXT:    call void @use(i32 [[SHL_Y]])
+; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    ret i32 [[MIN]]
+;
+  %shl_x = shl nuw i32 1, %x
+  %shl_y = shl nuw i32 1, %y
+  call void @use(i32 %shl_x)
+  call void @use(i32 %shl_y)
+  %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+  ret i32 %min
+}
+
+define i32 @test_umax_shl_const1_commuted(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umax_shl_const1_commuted(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_Y]], i32 [[SHL_X]])
+; CHECK-NEXT:    ret i32 [[MAX]]
+;
+  %shl_x = shl nuw i32 1, %x
+  %shl_y = shl nuw i32 1, %y
+  %max = call i32 @llvm.umax.i32(i32 %shl_y, i32 %shl_x)
+  ret i32 %max
+}
+
+define i32 @test_umin_shl_const1_commuted(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umin_shl_const1_commuted(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_Y]], i32 [[SHL_X]])
+; CHECK-NEXT:    ret i32 [[MIN]]
+;
+  %shl_x = shl nuw i32 1, %x
+  %shl_y = shl nuw i32 1, %y
+  %min = call i32 @llvm.umin.i32(i32 %shl_y, i32 %shl_x)
+  ret i32 %min
+}
+
+define <2 x i32> @test_umax_shl_vector_splat(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @test_umax_shl_vector_splat(
+; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[Y]]
+; CHECK-NEXT:    [[MAX:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    ret <2 x i32> [[MAX]]
+;
+  %shl_x = shl nuw <2 x i32> <i32 1, i32 1>, %x
+  %shl_y = shl nuw <2 x i32> <i32 1, i32 1>, %y
+  %max = call <2 x i32> @llvm.umax.v2i32(<2 x i32> %shl_x, <2 x i32> %shl_y)
+  ret <2 x i32> %max
+}
+
+define <2 x i32> @test_umin_shl_vector_splat(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @test_umin_shl_vector_splat(
+; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[Y]]
+; CHECK-NEXT:    [[MIN:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    ret <2 x i32> [[MIN]]
+;
+  %shl_x = shl nuw <2 x i32> <i32 1, i32 1>, %x
+  %shl_y = shl nuw <2 x i32> <i32 1, i32 1>, %y
+  %min = call <2 x i32> @llvm.umin.v2i32(<2 x i32> %shl_x, <2 x i32> %shl_y)
+  ret <2 x i32> %min
+}
+
+define <2 x i32> @test_umax_shl_vector_non_splat(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @test_umax_shl_vector_non_splat(
+; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 2>, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 2>, [[Y]]
+; CHECK-NEXT:    [[MAX:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    ret <2 x i32> [[MAX]]
+;
+  %shl_x = shl nuw <2 x i32> <i32 1, i32 2>, %x
+  %shl_y = shl nuw <2 x i32> <i32 1, i32 2>, %y
+  %max = call <2 x i32> @llvm.umax.v2i32(<2 x i32> %shl_x, <2 x i32> %shl_y)
+  ret <2 x i32> %max
+}
+
+define <2 x i32> @test_umin_shl_vector_non_splat(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @test_umin_shl_vector_non_splat(
+; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 2>, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 2>, [[Y]]
+; CHECK-NEXT:    [[MIN:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    ret <2 x i32> [[MIN]]
+;
+  %shl_x = shl nuw <2 x i32> <i32 1, i32 2>, %x
+  %shl_y = shl nuw <2 x i32> <i32 1, i32 2>, %y
+  %min = call <2 x i32> @llvm.umin.v2i32(<2 x i32> %shl_x, <2 x i32> %shl_y)
+  ret <2 x i32> %min
+}
+
+define i32 @test_umax_shl_different_base(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umax_shl_different_base(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 2, [[Y]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    ret i32 [[MAX]]
+;
+  %shl_x = shl nuw i32 1, %x
+  %shl_y = shl nuw i32 2, %y
+  %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
+  ret i32 %max
+}
+
+define i32 @test_umin_shl_different_base(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umin_shl_different_base(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 2, [[Y]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    ret i32 [[MIN]]
+;
+  %shl_x = shl nuw i32 1, %x
+  %shl_y = shl nuw i32 2, %y
+  %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+  ret i32 %min
+}
+
+define i32 @test_umax_shl_no_nuw_flag(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umax_shl_no_nuw_flag(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl i32 2, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl i32 2, [[Y]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    ret i32 [[MAX]]
+;
+  %shl_x = shl i32 2, %x
+  %shl_y = shl i32 2, %y
+  %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
+  ret i32 %max
+}
+
+define i32 @test_umin_shl_no_nuw_flag(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umin_shl_no_nuw_flag(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl i32 2, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl i32 2, [[Y]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    ret i32 [[MIN]]
+;
+  %shl_x = shl i32 2, %x
+  %shl_y = shl i32 2, %y
+  %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+  ret i32 %min
+}

>From a11d23df4220cb181ac9a3aef181895d67b6fed9 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Thu, 13 Mar 2025 12:05:29 +0800
Subject: [PATCH 2/4] [InstCombine] Fold ` umax(nuw_shl(C0, x), nuw_shl(C0, y))
 -> nuw_shl(C0, umax(x, y))` and `umin(nuw_shl(C0, x), nuw_shl(C0, y)) ->
 nuw_shl(C0, umin(x, y))`

---
 .../InstCombine/InstCombineCalls.cpp          | 13 ++++++
 .../Transforms/InstCombine/shift-uminmax.ll   | 40 ++++++++-----------
 2 files changed, 29 insertions(+), 24 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 63f2fd0a733ce..a36f01c98b900 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1887,6 +1887,19 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
       if (Instruction *I = foldMaxMulShift(I1, I0))
         return I;
     }
+
+    // umax(nuw_shl(C0, x), nuw_shl(C0, y)) -> nuw_shl(C0, umax(x, y))
+    // umin(nuw_shl(C0, x), nuw_shl(C0, y)) -> nuw_shl(C0, umin(x, y))
+    const APInt *C1, *C2;
+    if (match(I0, m_OneUse(m_NUWShl(m_APInt(C1), m_Value()))) &&
+        match(I1, m_OneUse(m_NUWShl(m_APInt(C2), m_Value()))) && *C1 == *C2) {
+      Value *X = cast<ShlOperator>(I0)->getOperand(1);
+      Value *Y = cast<ShlOperator>(I1)->getOperand(1);
+      Value *MaxMin = Builder.CreateBinaryIntrinsic(IID, X, Y);
+      return BinaryOperator::CreateNUWShl(ConstantInt::get(I0->getType(), *C1),
+                                          MaxMin);
+    }
+
     // If both operands of unsigned min/max are sign-extended, it is still ok
     // to narrow the operation.
     [[fallthrough]];
diff --git a/llvm/test/Transforms/InstCombine/shift-uminmax.ll b/llvm/test/Transforms/InstCombine/shift-uminmax.ll
index 9e61f2f054867..14c600579999d 100644
--- a/llvm/test/Transforms/InstCombine/shift-uminmax.ll
+++ b/llvm/test/Transforms/InstCombine/shift-uminmax.ll
@@ -8,9 +8,8 @@
 define i32 @test_umax_shl_const1(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umax_shl_const1(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    [[MAX:%.*]] = shl nuw i32 1, [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[MAX]]
 ;
   %shl_x = shl nuw i32 1, %x
@@ -22,9 +21,8 @@ define i32 @test_umax_shl_const1(i32 %x, i32 %y) {
 define i32 @test_umin_shl_const1(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umin_shl_const1(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    [[MIN:%.*]] = shl nuw i32 1, [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[MIN]]
 ;
   %shl_x = shl nuw i32 1, %x
@@ -36,9 +34,8 @@ define i32 @test_umin_shl_const1(i32 %x, i32 %y) {
 define i32 @test_umax_shl_const5(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umax_shl_const5(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 5, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 5, [[Y]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    [[MAX:%.*]] = shl nuw i32 5, [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[MAX]]
 ;
   %shl_x = shl nuw i32 5, %x
@@ -50,9 +47,8 @@ define i32 @test_umax_shl_const5(i32 %x, i32 %y) {
 define i32 @test_umin_shl_const5(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umin_shl_const5(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 5, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 5, [[Y]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    [[MIN:%.*]] = shl nuw i32 5, [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[MIN]]
 ;
   %shl_x = shl nuw i32 5, %x
@@ -102,9 +98,8 @@ define i32 @test_umin_shl_const1_multi_use(i32 %x, i32 %y) {
 define i32 @test_umax_shl_const1_commuted(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umax_shl_const1_commuted(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_Y]], i32 [[SHL_X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[Y]], i32 [[X]])
+; CHECK-NEXT:    [[MAX:%.*]] = shl nuw i32 1, [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[MAX]]
 ;
   %shl_x = shl nuw i32 1, %x
@@ -116,9 +111,8 @@ define i32 @test_umax_shl_const1_commuted(i32 %x, i32 %y) {
 define i32 @test_umin_shl_const1_commuted(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umin_shl_const1_commuted(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_Y]], i32 [[SHL_X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[Y]], i32 [[X]])
+; CHECK-NEXT:    [[MIN:%.*]] = shl nuw i32 1, [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[MIN]]
 ;
   %shl_x = shl nuw i32 1, %x
@@ -130,9 +124,8 @@ define i32 @test_umin_shl_const1_commuted(i32 %x, i32 %y) {
 define <2 x i32> @test_umax_shl_vector_splat(<2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: define <2 x i32> @test_umax_shl_vector_splat(
 ; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[Y]]
-; CHECK-NEXT:    [[MAX:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[X]], <2 x i32> [[Y]])
+; CHECK-NEXT:    [[MAX:%.*]] = shl nuw <2 x i32> splat (i32 1), [[TMP1]]
 ; CHECK-NEXT:    ret <2 x i32> [[MAX]]
 ;
   %shl_x = shl nuw <2 x i32> <i32 1, i32 1>, %x
@@ -144,9 +137,8 @@ define <2 x i32> @test_umax_shl_vector_splat(<2 x i32> %x, <2 x i32> %y) {
 define <2 x i32> @test_umin_shl_vector_splat(<2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: define <2 x i32> @test_umin_shl_vector_splat(
 ; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[Y]]
-; CHECK-NEXT:    [[MIN:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[X]], <2 x i32> [[Y]])
+; CHECK-NEXT:    [[MIN:%.*]] = shl nuw <2 x i32> splat (i32 1), [[TMP1]]
 ; CHECK-NEXT:    ret <2 x i32> [[MIN]]
 ;
   %shl_x = shl nuw <2 x i32> <i32 1, i32 1>, %x

>From ed5a722376609b619f08aa87e325ec9ae2c46527 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Thu, 13 Mar 2025 15:11:02 +0800
Subject: [PATCH 3/4] adjust test for variables as base

---
 .../Transforms/InstCombine/shift-uminmax.ll   | 200 +++++++++++++-----
 1 file changed, 146 insertions(+), 54 deletions(-)

diff --git a/llvm/test/Transforms/InstCombine/shift-uminmax.ll b/llvm/test/Transforms/InstCombine/shift-uminmax.ll
index 14c600579999d..cfec5cd606dbf 100644
--- a/llvm/test/Transforms/InstCombine/shift-uminmax.ll
+++ b/llvm/test/Transforms/InstCombine/shift-uminmax.ll
@@ -2,14 +2,43 @@
 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
 
 ; For the following patterns:
-; umax(nuw_shl(C0, x), nuw_shl(C0, y)) -> nuw_shl(C0, umax(x, y))
-; umin(nuw_shl(C0, x), nuw_shl(C0, y)) -> nuw_shl(C0, umin(x, y))
+; umax(nuw_shl(base, x), nuw_shl(base, y)) -> nuw_shl(base, umax(x, y))
+; umin(nuw_shl(base, x), nuw_shl(base, y)) -> nuw_shl(base, umin(x, y))
+
+define i32 @test_umax_shl(i32 %base, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umax_shl(
+; CHECK-SAME: i32 [[BASE:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 [[BASE]], [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 [[BASE]], [[Y]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    ret i32 [[MAX]]
+;
+  %shl_x = shl nuw i32 %base, %x
+  %shl_y = shl nuw i32 %base, %y
+  %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
+  ret i32 %max
+}
+
+define i32 @test_umin_shl(i32 %base, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umin_shl(
+; CHECK-SAME: i32 [[BASE:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 [[BASE]], [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 [[BASE]], [[Y]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    ret i32 [[MIN]]
+;
+  %shl_x = shl nuw i32 %base, %x
+  %shl_y = shl nuw i32 %base, %y
+  %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+  ret i32 %min
+}
 
 define i32 @test_umax_shl_const1(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umax_shl_const1(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y]])
-; CHECK-NEXT:    [[MAX:%.*]] = shl nuw i32 1, [[TMP1]]
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
 ; CHECK-NEXT:    ret i32 [[MAX]]
 ;
   %shl_x = shl nuw i32 1, %x
@@ -21,8 +50,9 @@ define i32 @test_umax_shl_const1(i32 %x, i32 %y) {
 define i32 @test_umin_shl_const1(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umin_shl_const1(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y]])
-; CHECK-NEXT:    [[MIN:%.*]] = shl nuw i32 1, [[TMP1]]
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
 ; CHECK-NEXT:    ret i32 [[MIN]]
 ;
   %shl_x = shl nuw i32 1, %x
@@ -34,8 +64,9 @@ define i32 @test_umin_shl_const1(i32 %x, i32 %y) {
 define i32 @test_umax_shl_const5(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umax_shl_const5(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y]])
-; CHECK-NEXT:    [[MAX:%.*]] = shl nuw i32 5, [[TMP1]]
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 5, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 5, [[Y]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
 ; CHECK-NEXT:    ret i32 [[MAX]]
 ;
   %shl_x = shl nuw i32 5, %x
@@ -47,8 +78,9 @@ define i32 @test_umax_shl_const5(i32 %x, i32 %y) {
 define i32 @test_umin_shl_const5(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umin_shl_const5(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y]])
-; CHECK-NEXT:    [[MIN:%.*]] = shl nuw i32 5, [[TMP1]]
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 5, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 5, [[Y]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
 ; CHECK-NEXT:    ret i32 [[MIN]]
 ;
   %shl_x = shl nuw i32 5, %x
@@ -59,73 +91,104 @@ define i32 @test_umin_shl_const5(i32 %x, i32 %y) {
 
 declare void @use(i8)
 
-define i32 @test_umax_shl_const1_multi_use(i32 %x, i32 %y) {
-; CHECK-LABEL: define i32 @test_umax_shl_const1_multi_use(
-; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
+define i32 @test_umax_shl_multi_use(i32 %base, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umax_shl_multi_use(
+; CHECK-SAME: i32 [[BASE:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 [[BASE]], [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 [[BASE]], [[Y]]
 ; CHECK-NEXT:    call void @use(i32 [[SHL_X]])
 ; CHECK-NEXT:    call void @use(i32 [[SHL_Y]])
 ; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
 ; CHECK-NEXT:    ret i32 [[MAX]]
 ;
-  %shl_x = shl nuw i32 1, %x
-  %shl_y = shl nuw i32 1, %y
+  %shl_x = shl nuw i32 %base, %x
+  %shl_y = shl nuw i32 %base, %y
   call void @use(i32 %shl_x)
   call void @use(i32 %shl_y)
   %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
   ret i32 %max
 }
 
-define i32 @test_umin_shl_const1_multi_use(i32 %x, i32 %y) {
-; CHECK-LABEL: define i32 @test_umin_shl_const1_multi_use(
-; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
+define i32 @test_umin_shl_multi_use(i32 %base, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umin_shl_multi_use(
+; CHECK-SAME: i32 [[BASE:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 [[BASE]], [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 [[BASE]], [[Y]]
 ; CHECK-NEXT:    call void @use(i32 [[SHL_X]])
 ; CHECK-NEXT:    call void @use(i32 [[SHL_Y]])
 ; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
 ; CHECK-NEXT:    ret i32 [[MIN]]
 ;
-  %shl_x = shl nuw i32 1, %x
-  %shl_y = shl nuw i32 1, %y
+  %shl_x = shl nuw i32 %base, %x
+  %shl_y = shl nuw i32 %base, %y
   call void @use(i32 %shl_x)
   call void @use(i32 %shl_y)
   %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
   ret i32 %min
 }
 
-define i32 @test_umax_shl_const1_commuted(i32 %x, i32 %y) {
-; CHECK-LABEL: define i32 @test_umax_shl_const1_commuted(
-; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[Y]], i32 [[X]])
-; CHECK-NEXT:    [[MAX:%.*]] = shl nuw i32 1, [[TMP1]]
+define i32 @test_umax_shl_commuted(i32 %base, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umax_shl_commuted(
+; CHECK-SAME: i32 [[BASE:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 [[BASE]], [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 [[BASE]], [[Y]]
+; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_Y]], i32 [[SHL_X]])
 ; CHECK-NEXT:    ret i32 [[MAX]]
 ;
-  %shl_x = shl nuw i32 1, %x
-  %shl_y = shl nuw i32 1, %y
+  %shl_x = shl nuw i32 %base, %x
+  %shl_y = shl nuw i32 %base, %y
   %max = call i32 @llvm.umax.i32(i32 %shl_y, i32 %shl_x)
   ret i32 %max
 }
 
-define i32 @test_umin_shl_const1_commuted(i32 %x, i32 %y) {
-; CHECK-LABEL: define i32 @test_umin_shl_const1_commuted(
-; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[Y]], i32 [[X]])
-; CHECK-NEXT:    [[MIN:%.*]] = shl nuw i32 1, [[TMP1]]
+define i32 @test_umin_shl_commuted(i32 %base, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @test_umin_shl_commuted(
+; CHECK-SAME: i32 [[BASE:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 [[BASE]], [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 [[BASE]], [[Y]]
+; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_Y]], i32 [[SHL_X]])
 ; CHECK-NEXT:    ret i32 [[MIN]]
 ;
-  %shl_x = shl nuw i32 1, %x
-  %shl_y = shl nuw i32 1, %y
+  %shl_x = shl nuw i32 %base, %x
+  %shl_y = shl nuw i32 %base, %y
   %min = call i32 @llvm.umin.i32(i32 %shl_y, i32 %shl_x)
   ret i32 %min
 }
 
+define <2 x i32> @test_umax_shl_vector(<2 x i32> %base, <2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @test_umax_shl_vector(
+; CHECK-SAME: <2 x i32> [[BASE:%.*]], <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> [[BASE]], [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> [[BASE]], [[Y]]
+; CHECK-NEXT:    [[MAX:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    ret <2 x i32> [[MAX]]
+;
+  %shl_x = shl nuw <2 x i32> %base, %x
+  %shl_y = shl nuw <2 x i32> %base, %y
+  %max = call <2 x i32> @llvm.umax.v2i32(<2 x i32> %shl_x, <2 x i32> %shl_y)
+  ret <2 x i32> %max
+}
+
+define <2 x i32> @test_umin_shl_vector(<2 x i32> %base, <2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @test_umin_shl_vector(
+; CHECK-SAME: <2 x i32> [[BASE:%.*]], <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> [[BASE]], [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> [[BASE]], [[Y]]
+; CHECK-NEXT:    [[MIN:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    ret <2 x i32> [[MIN]]
+;
+  %shl_x = shl nuw <2 x i32> %base, %x
+  %shl_y = shl nuw <2 x i32> %base, %y
+  %min = call <2 x i32> @llvm.umin.v2i32(<2 x i32> %shl_x, <2 x i32> %shl_y)
+  ret <2 x i32> %min
+}
+
 define <2 x i32> @test_umax_shl_vector_splat(<2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: define <2 x i32> @test_umax_shl_vector_splat(
 ; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[X]], <2 x i32> [[Y]])
-; CHECK-NEXT:    [[MAX:%.*]] = shl nuw <2 x i32> splat (i32 1), [[TMP1]]
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[Y]]
+; CHECK-NEXT:    [[MAX:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
 ; CHECK-NEXT:    ret <2 x i32> [[MAX]]
 ;
   %shl_x = shl nuw <2 x i32> <i32 1, i32 1>, %x
@@ -137,8 +200,9 @@ define <2 x i32> @test_umax_shl_vector_splat(<2 x i32> %x, <2 x i32> %y) {
 define <2 x i32> @test_umin_shl_vector_splat(<2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: define <2 x i32> @test_umin_shl_vector_splat(
 ; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
-; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[X]], <2 x i32> [[Y]])
-; CHECK-NEXT:    [[MIN:%.*]] = shl nuw <2 x i32> splat (i32 1), [[TMP1]]
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[Y]]
+; CHECK-NEXT:    [[MIN:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
 ; CHECK-NEXT:    ret <2 x i32> [[MIN]]
 ;
   %shl_x = shl nuw <2 x i32> <i32 1, i32 1>, %x
@@ -147,6 +211,34 @@ define <2 x i32> @test_umin_shl_vector_splat(<2 x i32> %x, <2 x i32> %y) {
   ret <2 x i32> %min
 }
 
+define <2 x i32> @test_umax_shl_vector_splat_poison(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @test_umax_shl_vector_splat_poison(
+; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 poison>, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 poison>, [[Y]]
+; CHECK-NEXT:    [[MAX:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    ret <2 x i32> [[MAX]]
+;
+  %shl_x = shl nuw <2 x i32> <i32 1, i32 poison>, %x
+  %shl_y = shl nuw <2 x i32> <i32 1, i32 poison>, %y
+  %max = call <2 x i32> @llvm.umax.v2i32(<2 x i32> %shl_x, <2 x i32> %shl_y)
+  ret <2 x i32> %max
+}
+
+define <2 x i32> @test_umin_shl_vector_splat_poison(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @test_umin_shl_vector_splat_poison(
+; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 poison>, [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 poison>, [[Y]]
+; CHECK-NEXT:    [[MIN:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    ret <2 x i32> [[MIN]]
+;
+  %shl_x = shl nuw <2 x i32> <i32 1, i32 poison>, %x
+  %shl_y = shl nuw <2 x i32> <i32 1, i32 poison>, %y
+  %min = call <2 x i32> @llvm.umin.v2i32(<2 x i32> %shl_x, <2 x i32> %shl_y)
+  ret <2 x i32> %min
+}
+
 define <2 x i32> @test_umax_shl_vector_non_splat(<2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: define <2 x i32> @test_umax_shl_vector_non_splat(
 ; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
@@ -175,30 +267,30 @@ define <2 x i32> @test_umin_shl_vector_non_splat(<2 x i32> %x, <2 x i32> %y) {
   ret <2 x i32> %min
 }
 
-define i32 @test_umax_shl_different_base(i32 %x, i32 %y) {
+define i32 @test_umax_shl_different_base(i32 %base1, i32 %base2, i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umax_shl_different_base(
-; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 2, [[Y]]
+; CHECK-SAME: i32 [[BASE1:%.*]], i32 [[BASE2:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 [[BASE1]], [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 [[BASE2]], [[Y]]
 ; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
 ; CHECK-NEXT:    ret i32 [[MAX]]
 ;
-  %shl_x = shl nuw i32 1, %x
-  %shl_y = shl nuw i32 2, %y
+  %shl_x = shl nuw i32 %base1, %x
+  %shl_y = shl nuw i32 %base2, %y
   %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
   ret i32 %max
 }
 
-define i32 @test_umin_shl_different_base(i32 %x, i32 %y) {
+define i32 @test_umin_shl_different_base(i32 %base1, i32 %base2, i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umin_shl_different_base(
-; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 2, [[Y]]
+; CHECK-SAME: i32 [[BASE1:%.*]], i32 [[BASE2:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 [[BASE1]], [[X]]
+; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 [[BASE2]], [[Y]]
 ; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
 ; CHECK-NEXT:    ret i32 [[MIN]]
 ;
-  %shl_x = shl nuw i32 1, %x
-  %shl_y = shl nuw i32 2, %y
+  %shl_x = shl nuw i32 %base1, %x
+  %shl_y = shl nuw i32 %base2, %y
   %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
   ret i32 %min
 }

>From e09c615dead93dd606ee54d658168877e7488ec2 Mon Sep 17 00:00:00 2001
From: Iris Shi <0.0 at owo.li>
Date: Thu, 13 Mar 2025 15:15:10 +0800
Subject: [PATCH 4/4] adjust transformation for variables as base

---
 .../InstCombine/InstCombineCalls.cpp          | 18 ++---
 .../Transforms/InstCombine/shift-uminmax.ll   | 80 ++++++++-----------
 2 files changed, 40 insertions(+), 58 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index a36f01c98b900..5a7eb848199e6 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1888,16 +1888,14 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
         return I;
     }
 
-    // umax(nuw_shl(C0, x), nuw_shl(C0, y)) -> nuw_shl(C0, umax(x, y))
-    // umin(nuw_shl(C0, x), nuw_shl(C0, y)) -> nuw_shl(C0, umin(x, y))
-    const APInt *C1, *C2;
-    if (match(I0, m_OneUse(m_NUWShl(m_APInt(C1), m_Value()))) &&
-        match(I1, m_OneUse(m_NUWShl(m_APInt(C2), m_Value()))) && *C1 == *C2) {
-      Value *X = cast<ShlOperator>(I0)->getOperand(1);
-      Value *Y = cast<ShlOperator>(I1)->getOperand(1);
-      Value *MaxMin = Builder.CreateBinaryIntrinsic(IID, X, Y);
-      return BinaryOperator::CreateNUWShl(ConstantInt::get(I0->getType(), *C1),
-                                          MaxMin);
+    // umax(nuw_shl(base, x), nuw_shl(base, y)) -> nuw_shl(base, umax(x, y))
+    // umin(nuw_shl(base, x), nuw_shl(base, y)) -> nuw_shl(base, umin(x, y))
+    Value *Base;
+    Value *Shamt1, *Shamt2;
+    if (match(I0, m_OneUse(m_NUWShl(m_Value(Base), m_Value(Shamt1)))) &&
+        match(I1, m_OneUse(m_NUWShl(m_Deferred(Base), m_Value(Shamt2))))) {
+      Value *MaxMin = Builder.CreateBinaryIntrinsic(IID, Shamt1, Shamt2);
+      return BinaryOperator::CreateNUWShl(Base, MaxMin);
     }
 
     // If both operands of unsigned min/max are sign-extended, it is still ok
diff --git a/llvm/test/Transforms/InstCombine/shift-uminmax.ll b/llvm/test/Transforms/InstCombine/shift-uminmax.ll
index cfec5cd606dbf..1aecbc1a3edfd 100644
--- a/llvm/test/Transforms/InstCombine/shift-uminmax.ll
+++ b/llvm/test/Transforms/InstCombine/shift-uminmax.ll
@@ -8,9 +8,8 @@
 define i32 @test_umax_shl(i32 %base, i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umax_shl(
 ; CHECK-SAME: i32 [[BASE:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 [[BASE]], [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 [[BASE]], [[Y]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    [[MAX:%.*]] = shl nuw i32 [[BASE]], [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[MAX]]
 ;
   %shl_x = shl nuw i32 %base, %x
@@ -22,9 +21,8 @@ define i32 @test_umax_shl(i32 %base, i32 %x, i32 %y) {
 define i32 @test_umin_shl(i32 %base, i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umin_shl(
 ; CHECK-SAME: i32 [[BASE:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 [[BASE]], [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 [[BASE]], [[Y]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    [[MIN:%.*]] = shl nuw i32 [[BASE]], [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[MIN]]
 ;
   %shl_x = shl nuw i32 %base, %x
@@ -36,9 +34,8 @@ define i32 @test_umin_shl(i32 %base, i32 %x, i32 %y) {
 define i32 @test_umax_shl_const1(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umax_shl_const1(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    [[MAX:%.*]] = shl nuw i32 1, [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[MAX]]
 ;
   %shl_x = shl nuw i32 1, %x
@@ -50,9 +47,8 @@ define i32 @test_umax_shl_const1(i32 %x, i32 %y) {
 define i32 @test_umin_shl_const1(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umin_shl_const1(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 1, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 1, [[Y]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    [[MIN:%.*]] = shl nuw i32 1, [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[MIN]]
 ;
   %shl_x = shl nuw i32 1, %x
@@ -64,9 +60,8 @@ define i32 @test_umin_shl_const1(i32 %x, i32 %y) {
 define i32 @test_umax_shl_const5(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umax_shl_const5(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 5, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 5, [[Y]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    [[MAX:%.*]] = shl nuw i32 5, [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[MAX]]
 ;
   %shl_x = shl nuw i32 5, %x
@@ -78,9 +73,8 @@ define i32 @test_umax_shl_const5(i32 %x, i32 %y) {
 define i32 @test_umin_shl_const5(i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umin_shl_const5(
 ; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 5, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 5, [[Y]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT:    [[MIN:%.*]] = shl nuw i32 5, [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[MIN]]
 ;
   %shl_x = shl nuw i32 5, %x
@@ -130,9 +124,8 @@ define i32 @test_umin_shl_multi_use(i32 %base, i32 %x, i32 %y) {
 define i32 @test_umax_shl_commuted(i32 %base, i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umax_shl_commuted(
 ; CHECK-SAME: i32 [[BASE:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 [[BASE]], [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 [[BASE]], [[Y]]
-; CHECK-NEXT:    [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_Y]], i32 [[SHL_X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[Y]], i32 [[X]])
+; CHECK-NEXT:    [[MAX:%.*]] = shl nuw i32 [[BASE]], [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[MAX]]
 ;
   %shl_x = shl nuw i32 %base, %x
@@ -144,9 +137,8 @@ define i32 @test_umax_shl_commuted(i32 %base, i32 %x, i32 %y) {
 define i32 @test_umin_shl_commuted(i32 %base, i32 %x, i32 %y) {
 ; CHECK-LABEL: define i32 @test_umin_shl_commuted(
 ; CHECK-SAME: i32 [[BASE:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw i32 [[BASE]], [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw i32 [[BASE]], [[Y]]
-; CHECK-NEXT:    [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_Y]], i32 [[SHL_X]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[Y]], i32 [[X]])
+; CHECK-NEXT:    [[MIN:%.*]] = shl nuw i32 [[BASE]], [[TMP1]]
 ; CHECK-NEXT:    ret i32 [[MIN]]
 ;
   %shl_x = shl nuw i32 %base, %x
@@ -158,9 +150,8 @@ define i32 @test_umin_shl_commuted(i32 %base, i32 %x, i32 %y) {
 define <2 x i32> @test_umax_shl_vector(<2 x i32> %base, <2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: define <2 x i32> @test_umax_shl_vector(
 ; CHECK-SAME: <2 x i32> [[BASE:%.*]], <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> [[BASE]], [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> [[BASE]], [[Y]]
-; CHECK-NEXT:    [[MAX:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[X]], <2 x i32> [[Y]])
+; CHECK-NEXT:    [[MAX:%.*]] = shl nuw <2 x i32> [[BASE]], [[TMP1]]
 ; CHECK-NEXT:    ret <2 x i32> [[MAX]]
 ;
   %shl_x = shl nuw <2 x i32> %base, %x
@@ -172,9 +163,8 @@ define <2 x i32> @test_umax_shl_vector(<2 x i32> %base, <2 x i32> %x, <2 x i32>
 define <2 x i32> @test_umin_shl_vector(<2 x i32> %base, <2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: define <2 x i32> @test_umin_shl_vector(
 ; CHECK-SAME: <2 x i32> [[BASE:%.*]], <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> [[BASE]], [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> [[BASE]], [[Y]]
-; CHECK-NEXT:    [[MIN:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[X]], <2 x i32> [[Y]])
+; CHECK-NEXT:    [[MIN:%.*]] = shl nuw <2 x i32> [[BASE]], [[TMP1]]
 ; CHECK-NEXT:    ret <2 x i32> [[MIN]]
 ;
   %shl_x = shl nuw <2 x i32> %base, %x
@@ -186,9 +176,8 @@ define <2 x i32> @test_umin_shl_vector(<2 x i32> %base, <2 x i32> %x, <2 x i32>
 define <2 x i32> @test_umax_shl_vector_splat(<2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: define <2 x i32> @test_umax_shl_vector_splat(
 ; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[Y]]
-; CHECK-NEXT:    [[MAX:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[X]], <2 x i32> [[Y]])
+; CHECK-NEXT:    [[MAX:%.*]] = shl nuw <2 x i32> splat (i32 1), [[TMP1]]
 ; CHECK-NEXT:    ret <2 x i32> [[MAX]]
 ;
   %shl_x = shl nuw <2 x i32> <i32 1, i32 1>, %x
@@ -200,9 +189,8 @@ define <2 x i32> @test_umax_shl_vector_splat(<2 x i32> %x, <2 x i32> %y) {
 define <2 x i32> @test_umin_shl_vector_splat(<2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: define <2 x i32> @test_umin_shl_vector_splat(
 ; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 1>, [[Y]]
-; CHECK-NEXT:    [[MIN:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[X]], <2 x i32> [[Y]])
+; CHECK-NEXT:    [[MIN:%.*]] = shl nuw <2 x i32> splat (i32 1), [[TMP1]]
 ; CHECK-NEXT:    ret <2 x i32> [[MIN]]
 ;
   %shl_x = shl nuw <2 x i32> <i32 1, i32 1>, %x
@@ -214,9 +202,8 @@ define <2 x i32> @test_umin_shl_vector_splat(<2 x i32> %x, <2 x i32> %y) {
 define <2 x i32> @test_umax_shl_vector_splat_poison(<2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: define <2 x i32> @test_umax_shl_vector_splat_poison(
 ; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 poison>, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 poison>, [[Y]]
-; CHECK-NEXT:    [[MAX:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[X]], <2 x i32> [[Y]])
+; CHECK-NEXT:    [[MAX:%.*]] = shl nuw <2 x i32> <i32 1, i32 poison>, [[TMP1]]
 ; CHECK-NEXT:    ret <2 x i32> [[MAX]]
 ;
   %shl_x = shl nuw <2 x i32> <i32 1, i32 poison>, %x
@@ -228,9 +215,8 @@ define <2 x i32> @test_umax_shl_vector_splat_poison(<2 x i32> %x, <2 x i32> %y)
 define <2 x i32> @test_umin_shl_vector_splat_poison(<2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: define <2 x i32> @test_umin_shl_vector_splat_poison(
 ; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 poison>, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 poison>, [[Y]]
-; CHECK-NEXT:    [[MIN:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[X]], <2 x i32> [[Y]])
+; CHECK-NEXT:    [[MIN:%.*]] = shl nuw <2 x i32> <i32 1, i32 poison>, [[TMP1]]
 ; CHECK-NEXT:    ret <2 x i32> [[MIN]]
 ;
   %shl_x = shl nuw <2 x i32> <i32 1, i32 poison>, %x
@@ -242,9 +228,8 @@ define <2 x i32> @test_umin_shl_vector_splat_poison(<2 x i32> %x, <2 x i32> %y)
 define <2 x i32> @test_umax_shl_vector_non_splat(<2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: define <2 x i32> @test_umax_shl_vector_non_splat(
 ; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 2>, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 2>, [[Y]]
-; CHECK-NEXT:    [[MAX:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.umax.v2i32(<2 x i32> [[X]], <2 x i32> [[Y]])
+; CHECK-NEXT:    [[MAX:%.*]] = shl nuw <2 x i32> <i32 1, i32 2>, [[TMP1]]
 ; CHECK-NEXT:    ret <2 x i32> [[MAX]]
 ;
   %shl_x = shl nuw <2 x i32> <i32 1, i32 2>, %x
@@ -256,9 +241,8 @@ define <2 x i32> @test_umax_shl_vector_non_splat(<2 x i32> %x, <2 x i32> %y) {
 define <2 x i32> @test_umin_shl_vector_non_splat(<2 x i32> %x, <2 x i32> %y) {
 ; CHECK-LABEL: define <2 x i32> @test_umin_shl_vector_non_splat(
 ; CHECK-SAME: <2 x i32> [[X:%.*]], <2 x i32> [[Y:%.*]]) {
-; CHECK-NEXT:    [[SHL_X:%.*]] = shl nuw <2 x i32> <i32 1, i32 2>, [[X]]
-; CHECK-NEXT:    [[SHL_Y:%.*]] = shl nuw <2 x i32> <i32 1, i32 2>, [[Y]]
-; CHECK-NEXT:    [[MIN:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[SHL_X]], <2 x i32> [[SHL_Y]])
+; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x i32> @llvm.umin.v2i32(<2 x i32> [[X]], <2 x i32> [[Y]])
+; CHECK-NEXT:    [[MIN:%.*]] = shl nuw <2 x i32> <i32 1, i32 2>, [[TMP1]]
 ; CHECK-NEXT:    ret <2 x i32> [[MIN]]
 ;
   %shl_x = shl nuw <2 x i32> <i32 1, i32 2>, %x



More information about the llvm-commits mailing list