[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
- Previous message: [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)
- Next message: [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)
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
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
- Previous message: [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)
- Next message: [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)
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the llvm-commits
mailing list