[llvm] 1762f16 - [InstCombine] Fold `umax/umin(nuw_shl(z, x), nuw_shl(z, y)) -> nuw_shl(z, umax/umin(x, y))` and `umax/umin(nuw_shl(x, z), nuw_shl(y, z)) -> nuw_shl(umax/umin(x, y), z)` (#131076)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 14 22:40:39 PDT 2025
Author: Iris
Date: 2025-03-15T13:40:35+08:00
New Revision: 1762f16f6cc497255b5ba4e68372717db0448112
URL: https://github.com/llvm/llvm-project/commit/1762f16f6cc497255b5ba4e68372717db0448112
DIFF: https://github.com/llvm/llvm-project/commit/1762f16f6cc497255b5ba4e68372717db0448112.diff
LOG: [InstCombine] Fold `umax/umin(nuw_shl(z, x), nuw_shl(z, y)) -> nuw_shl(z, umax/umin(x, y))` and `umax/umin(nuw_shl(x, z), nuw_shl(y, z)) -> nuw_shl(umax/umin(x, y), z)` (#131076)
- Closes #129947
This PR introduces the following transformations:
1. `umax(nuw_shl(z, x), nuw_shl(z, y)) -> nuw_shl(z, umax(x, y))`
2. `umin(nuw_shl(z, x), nuw_shl(z, y)) -> nuw_shl(z, umin(x, y))`
3. `umax(nuw_shl(x, z), nuw_shl(y, z)) -> nuw_shl(umax(x, y),z)`
4. `umin(nuw_shl(x, z), nuw_shl(y, z)) -> nuw_shl(umin(x, y),z)`
Alive2 live proof:
- https://alive2.llvm.org/ce/z/6bM-p7 for 1 and 2
- https://alive2.llvm.org/ce/z/aqLRYA and
https://alive2.llvm.org/ce/z/twoVhb for 3 and 4 repectively
Added:
llvm/test/Transforms/InstCombine/shift-uminmax.ll
Modified:
llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
llvm/test/Transforms/InstCombine/div-shift.ll
llvm/test/Transforms/InstCombine/intrinsic-distributive.ll
Removed:
################################################################################
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 63f2fd0a733ce..12dd4cec85f59 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1554,7 +1554,11 @@ static bool leftDistributesOverRight(Instruction::BinaryOps LOp, bool HasNUW,
switch (ROp) {
case Intrinsic::umax:
case Intrinsic::umin:
- return HasNUW && LOp == Instruction::Add;
+ if (HasNUW && LOp == Instruction::Add)
+ return true;
+ if (HasNUW && LOp == Instruction::Shl)
+ return true;
+ return false;
case Intrinsic::smax:
case Intrinsic::smin:
return HasNSW && LOp == Instruction::Add;
@@ -1592,29 +1596,37 @@ foldIntrinsicUsingDistributiveLaws(IntrinsicInst *II,
if (!leftDistributesOverRight(InnerOpcode, HasNUW, HasNSW, TopLevelOpcode))
return nullptr;
- assert(II->isCommutative() && Op0->isCommutative() &&
- "Only inner and outer commutative op codes are supported.");
-
Value *A = Op0->getOperand(0);
Value *B = Op0->getOperand(1);
Value *C = Op1->getOperand(0);
Value *D = Op1->getOperand(1);
- // Attempts to swap variables such that A always equals C
- if (A != C && A != D)
- std::swap(A, B);
- if (A == C || A == D) {
- if (A != C)
+ // Attempts to swap variables such that A equals C or B equals D,
+ // if the inner operation is commutative.
+ if (Op0->isCommutative() && A != C && B != D) {
+ if (A == D || B == C)
std::swap(C, D);
+ else
+ return nullptr;
+ }
+
+ BinaryOperator *NewBinop;
+ if (A == C) {
Value *NewIntrinsic = Builder.CreateBinaryIntrinsic(TopLevelOpcode, B, D);
- BinaryOperator *NewBinop =
- cast<BinaryOperator>(Builder.CreateBinOp(InnerOpcode, NewIntrinsic, A));
- NewBinop->setHasNoSignedWrap(HasNSW);
- NewBinop->setHasNoUnsignedWrap(HasNUW);
- return NewBinop;
+ NewBinop =
+ cast<BinaryOperator>(Builder.CreateBinOp(InnerOpcode, A, NewIntrinsic));
+ } else if (B == D) {
+ Value *NewIntrinsic = Builder.CreateBinaryIntrinsic(TopLevelOpcode, A, C);
+ NewBinop =
+ cast<BinaryOperator>(Builder.CreateBinOp(InnerOpcode, NewIntrinsic, B));
+ } else {
+ return nullptr;
}
- return nullptr;
+ NewBinop->setHasNoUnsignedWrap(HasNUW);
+ NewBinop->setHasNoSignedWrap(HasNSW);
+
+ return NewBinop;
}
/// CallInst simplification. This mostly only handles folding of intrinsic
@@ -1887,6 +1899,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Instruction *I = foldMaxMulShift(I1, I0))
return I;
}
+
// 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/div-shift.ll b/llvm/test/Transforms/InstCombine/div-shift.ll
index af83f37011ba0..fd857b983a788 100644
--- a/llvm/test/Transforms/InstCombine/div-shift.ll
+++ b/llvm/test/Transforms/InstCombine/div-shift.ll
@@ -144,11 +144,9 @@ define i8 @udiv_umin_(i8 %x, i8 %y, i8 %z) {
; Negative test, extra use
define i8 @udiv_umin_extra_use(i8 %x, i8 %y, i8 %z) {
; CHECK-LABEL: @udiv_umin_extra_use(
-; CHECK-NEXT: [[Y2:%.*]] = shl nuw i8 1, [[Y:%.*]]
-; CHECK-NEXT: [[Z2:%.*]] = shl nuw i8 1, [[Z:%.*]]
-; CHECK-NEXT: [[M:%.*]] = call i8 @llvm.umin.i8(i8 [[Y2]], i8 [[Z2]])
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[Y:%.*]], i8 [[Z:%.*]])
+; CHECK-NEXT: [[M:%.*]] = shl nuw i8 1, [[TMP1]]
; CHECK-NEXT: call void @use(i8 [[M]])
-; CHECK-NEXT: [[TMP1:%.*]] = call range(i8 0, 9) i8 @llvm.cttz.i8(i8 [[M]], i1 true)
; CHECK-NEXT: [[D:%.*]] = lshr i8 [[X:%.*]], [[TMP1]]
; CHECK-NEXT: ret i8 [[D]]
;
diff --git a/llvm/test/Transforms/InstCombine/intrinsic-distributive.ll b/llvm/test/Transforms/InstCombine/intrinsic-distributive.ll
index 2284e3f6c174b..630d4ee4d4221 100644
--- a/llvm/test/Transforms/InstCombine/intrinsic-distributive.ll
+++ b/llvm/test/Transforms/InstCombine/intrinsic-distributive.ll
@@ -2,8 +2,8 @@
; RUN: opt -S -passes=instcombine < %s 2>&1 | FileCheck %s
-define i8 @umax_of_add_nuw(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @umax_of_add_nuw(
+define i8 @umax_of_add_nuw_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MAX:%.*]] = add nuw i8 [[TMP1]], [[A]]
@@ -15,6 +15,19 @@ define i8 @umax_of_add_nuw(i8 %a, i8 %b, i8 %c) {
ret i8 %max
}
+define i8 @umax_of_add_nuw_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw_l(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT: [[MAX:%.*]] = add nuw i8 [[A]], [[TMP1]]
+; CHECK-NEXT: ret i8 [[MAX]]
+;
+ %add1 = add nuw i8 %a, %b
+ %add2 = add nuw i8 %a, %c
+ %max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
+ ret i8 %max
+}
+
define i8 @umax_of_add_nuw_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: define i8 @umax_of_add_nuw_comm(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
@@ -22,14 +35,14 @@ define i8 @umax_of_add_nuw_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-NEXT: [[MAX:%.*]] = add nuw i8 [[TMP1]], [[A]]
; CHECK-NEXT: ret i8 [[MAX]]
;
- %add1 = add nuw i8 %a, %b
+ %add1 = add nuw i8 %b, %a
%add2 = add nuw i8 %a, %c
%max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
ret i8 %max
}
-define i8 @umax_of_add_nuw_nsw_lhs(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_lhs(
+define i8 @umax_of_add_nuw_nsw_lhs_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_lhs_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MAX:%.*]] = add nuw i8 [[TMP1]], [[A]]
@@ -41,21 +54,34 @@ define i8 @umax_of_add_nuw_nsw_lhs(i8 %a, i8 %b, i8 %c) {
ret i8 %max
}
+define i8 @umax_of_add_nuw_nsw_lhs_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_lhs_l(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT: [[MAX:%.*]] = add nuw i8 [[A]], [[TMP1]]
+; CHECK-NEXT: ret i8 [[MAX]]
+;
+ %add1 = add nuw nsw i8 %a, %b
+ %add2 = add nuw i8 %a, %c
+ %max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
+ ret i8 %max
+}
+
define i8 @umax_of_add_nuw_nsw_lhs_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_lhs_comm(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
-; CHECK-NEXT: [[MAX:%.*]] = add nuw i8 [[TMP1]], [[A]]
+; CHECK-NEXT: [[MAX:%.*]] = add nuw i8 [[A]], [[TMP1]]
; CHECK-NEXT: ret i8 [[MAX]]
;
%add1 = add nuw nsw i8 %a, %b
- %add2 = add nuw i8 %a, %c
+ %add2 = add nuw i8 %c, %a
%max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
ret i8 %max
}
-define i8 @umax_of_add_nuw_nsw_rhs(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_rhs(
+define i8 @umax_of_add_nuw_nsw_rhs_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_rhs_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MAX:%.*]] = add nuw i8 [[TMP1]], [[A]]
@@ -67,6 +93,19 @@ define i8 @umax_of_add_nuw_nsw_rhs(i8 %a, i8 %b, i8 %c) {
ret i8 %max
}
+define i8 @umax_of_add_nuw_nsw_rhs_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_rhs_l(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT: [[MAX:%.*]] = add nuw i8 [[A]], [[TMP1]]
+; CHECK-NEXT: ret i8 [[MAX]]
+;
+ %add1 = add nuw i8 %a, %b
+ %add2 = add nuw nsw i8 %a, %c
+ %max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
+ ret i8 %max
+}
+
define i8 @umax_of_add_nuw_nsw_rhs_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_rhs_comm(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
@@ -74,14 +113,14 @@ define i8 @umax_of_add_nuw_nsw_rhs_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-NEXT: [[MAX:%.*]] = add nuw i8 [[TMP1]], [[A]]
; CHECK-NEXT: ret i8 [[MAX]]
;
- %add1 = add nuw i8 %a, %b
+ %add1 = add nuw i8 %b, %a
%add2 = add nuw nsw i8 %a, %c
%max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
ret i8 %max
}
-define i8 @umax_of_add_nuw_nsw(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw(
+define i8 @umax_of_add_nuw_nsw_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MAX:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
@@ -93,15 +132,28 @@ define i8 @umax_of_add_nuw_nsw(i8 %a, i8 %b, i8 %c) {
ret i8 %max
}
+define i8 @umax_of_add_nuw_nsw_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_l(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT: [[MAX:%.*]] = add nuw nsw i8 [[A]], [[TMP1]]
+; CHECK-NEXT: ret i8 [[MAX]]
+;
+ %add1 = add nuw nsw i8 %a, %b
+ %add2 = add nuw nsw i8 %a, %c
+ %max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
+ ret i8 %max
+}
+
define i8 @umax_of_add_nuw_nsw_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: define i8 @umax_of_add_nuw_nsw_comm(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umax.i8(i8 [[B]], i8 [[C]])
-; CHECK-NEXT: [[MAX:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
+; CHECK-NEXT: [[MAX:%.*]] = add nuw nsw i8 [[A]], [[TMP1]]
; CHECK-NEXT: ret i8 [[MAX]]
;
%add1 = add nuw nsw i8 %a, %b
- %add2 = add nuw nsw i8 %a, %c
+ %add2 = add nuw nsw i8 %c, %a
%max = call i8 @llvm.umax.i8(i8 %add1, i8 %add2)
ret i8 %max
}
@@ -136,8 +188,8 @@ define i8 @umax_of_add(i8 %a, i8 %b, i8 %c) {
ret i8 %max
}
-define i8 @umin_of_add_nuw(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @umin_of_add_nuw(
+define i8 @umin_of_add_nuw_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MIN:%.*]] = add nuw i8 [[TMP1]], [[A]]
@@ -149,6 +201,19 @@ define i8 @umin_of_add_nuw(i8 %a, i8 %b, i8 %c) {
ret i8 %min
}
+define i8 @umin_of_add_nuw_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw_l(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT: [[MIN:%.*]] = add nuw i8 [[A]], [[TMP1]]
+; CHECK-NEXT: ret i8 [[MIN]]
+;
+ %add1 = add nuw i8 %a, %b
+ %add2 = add nuw i8 %a, %c
+ %min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
+ ret i8 %min
+}
+
define i8 @umin_of_add_nuw_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: define i8 @umin_of_add_nuw_comm(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
@@ -156,14 +221,14 @@ define i8 @umin_of_add_nuw_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-NEXT: [[MIN:%.*]] = add nuw i8 [[TMP1]], [[A]]
; CHECK-NEXT: ret i8 [[MIN]]
;
- %add1 = add nuw i8 %a, %b
+ %add1 = add nuw i8 %b, %a
%add2 = add nuw i8 %a, %c
%min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
ret i8 %min
}
-define i8 @umin_of_add_nuw_nsw_lhs(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_lhs(
+define i8 @umin_of_add_nuw_nsw_lhs_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_lhs_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MIN:%.*]] = add nuw i8 [[TMP1]], [[A]]
@@ -175,21 +240,34 @@ define i8 @umin_of_add_nuw_nsw_lhs(i8 %a, i8 %b, i8 %c) {
ret i8 %min
}
+define i8 @umin_of_add_nuw_nsw_lhs_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_lhs_l(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT: [[MIN:%.*]] = add nuw i8 [[A]], [[TMP1]]
+; CHECK-NEXT: ret i8 [[MIN]]
+;
+ %add1 = add nuw nsw i8 %a, %b
+ %add2 = add nuw i8 %a, %c
+ %min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
+ ret i8 %min
+}
+
define i8 @umin_of_add_nuw_nsw_lhs_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_lhs_comm(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
-; CHECK-NEXT: [[MIN:%.*]] = add nuw i8 [[TMP1]], [[A]]
+; CHECK-NEXT: [[MIN:%.*]] = add nuw i8 [[A]], [[TMP1]]
; CHECK-NEXT: ret i8 [[MIN]]
;
%add1 = add nuw nsw i8 %a, %b
- %add2 = add nuw i8 %a, %c
+ %add2 = add nuw i8 %c, %a
%min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
ret i8 %min
}
-define i8 @umin_of_add_nuw_nsw_rhs(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_rhs(
+define i8 @umin_of_add_nuw_nsw_rhs_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_rhs_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MIN:%.*]] = add nuw i8 [[TMP1]], [[A]]
@@ -201,6 +279,19 @@ define i8 @umin_of_add_nuw_nsw_rhs(i8 %a, i8 %b, i8 %c) {
ret i8 %min
}
+define i8 @umin_of_add_nuw_nsw_rhs_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_rhs_l(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT: [[MIN:%.*]] = add nuw i8 [[A]], [[TMP1]]
+; CHECK-NEXT: ret i8 [[MIN]]
+;
+ %add1 = add nuw i8 %a, %b
+ %add2 = add nuw nsw i8 %a, %c
+ %min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
+ ret i8 %min
+}
+
define i8 @umin_of_add_nuw_nsw_rhs_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_rhs_comm(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
@@ -208,14 +299,14 @@ define i8 @umin_of_add_nuw_nsw_rhs_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-NEXT: [[MIN:%.*]] = add nuw i8 [[TMP1]], [[A]]
; CHECK-NEXT: ret i8 [[MIN]]
;
- %add1 = add nuw i8 %a, %b
+ %add1 = add nuw i8 %b, %a
%add2 = add nuw nsw i8 %a, %c
%min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
ret i8 %min
}
-define i8 @umin_of_add_nuw_nsw(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw(
+define i8 @umin_of_add_nuw_nsw_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MIN:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
@@ -227,15 +318,28 @@ define i8 @umin_of_add_nuw_nsw(i8 %a, i8 %b, i8 %c) {
ret i8 %min
}
+define i8 @umin_of_add_nuw_nsw_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_l(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT: [[MIN:%.*]] = add nuw nsw i8 [[A]], [[TMP1]]
+; CHECK-NEXT: ret i8 [[MIN]]
+;
+ %add1 = add nuw nsw i8 %a, %b
+ %add2 = add nuw nsw i8 %a, %c
+ %min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
+ ret i8 %min
+}
+
define i8 @umin_of_add_nuw_nsw_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: define i8 @umin_of_add_nuw_nsw_comm(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.umin.i8(i8 [[B]], i8 [[C]])
-; CHECK-NEXT: [[MIN:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
+; CHECK-NEXT: [[MIN:%.*]] = add nuw nsw i8 [[A]], [[TMP1]]
; CHECK-NEXT: ret i8 [[MIN]]
;
%add1 = add nuw nsw i8 %a, %b
- %add2 = add nuw nsw i8 %a, %c
+ %add2 = add nuw nsw i8 %c, %a
%min = call i8 @llvm.umin.i8(i8 %add1, i8 %add2)
ret i8 %min
}
@@ -285,8 +389,8 @@ define i8 @smax_of_add_nuw(i8 %a, i8 %b, i8 %c) {
ret i8 %max
}
-define i8 @smax_of_add_nsw(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @smax_of_add_nsw(
+define i8 @smax_of_add_nsw_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MAX:%.*]] = add nsw i8 [[TMP1]], [[A]]
@@ -298,6 +402,19 @@ define i8 @smax_of_add_nsw(i8 %a, i8 %b, i8 %c) {
ret i8 %max
}
+define i8 @smax_of_add_nsw_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_l(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT: [[MAX:%.*]] = add nsw i8 [[A]], [[TMP1]]
+; CHECK-NEXT: ret i8 [[MAX]]
+;
+ %add1 = add nsw i8 %a, %b
+ %add2 = add nsw i8 %a, %c
+ %max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
+ ret i8 %max
+}
+
define i8 @smax_of_add_nsw_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: define i8 @smax_of_add_nsw_comm(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
@@ -305,14 +422,14 @@ define i8 @smax_of_add_nsw_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-NEXT: [[MAX:%.*]] = add nsw i8 [[TMP1]], [[A]]
; CHECK-NEXT: ret i8 [[MAX]]
;
- %add1 = add nsw i8 %a, %b
+ %add1 = add nsw i8 %b, %a
%add2 = add nsw i8 %a, %c
%max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
ret i8 %max
}
-define i8 @smax_of_add_nsw_nuw_lhs(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_lhs(
+define i8 @smax_of_add_nsw_nuw_lhs_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_lhs_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MAX:%.*]] = add nsw i8 [[TMP1]], [[A]]
@@ -324,11 +441,11 @@ define i8 @smax_of_add_nsw_nuw_lhs(i8 %a, i8 %b, i8 %c) {
ret i8 %max
}
-define i8 @smax_of_add_nsw_nuw_lhs_comm(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_lhs_comm(
+define i8 @smax_of_add_nsw_nuw_lhs_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_lhs_l(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
-; CHECK-NEXT: [[MAX:%.*]] = add nsw i8 [[TMP1]], [[A]]
+; CHECK-NEXT: [[MAX:%.*]] = add nsw i8 [[A]], [[TMP1]]
; CHECK-NEXT: ret i8 [[MAX]]
;
%add1 = add nsw nuw i8 %a, %b
@@ -337,8 +454,21 @@ define i8 @smax_of_add_nsw_nuw_lhs_comm(i8 %a, i8 %b, i8 %c) {
ret i8 %max
}
-define i8 @smax_of_add_nsw_nuw_rhs(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_rhs(
+define i8 @smax_of_add_nsw_nuw_lhs_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_lhs_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT: [[MAX:%.*]] = add nsw i8 [[A]], [[TMP1]]
+; CHECK-NEXT: ret i8 [[MAX]]
+;
+ %add1 = add nuw nsw i8 %a, %b
+ %add2 = add nsw i8 %c, %a
+ %max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
+ ret i8 %max
+}
+
+define i8 @smax_of_add_nsw_nuw_rhs_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_rhs_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MAX:%.*]] = add nsw i8 [[TMP1]], [[A]]
@@ -350,6 +480,19 @@ define i8 @smax_of_add_nsw_nuw_rhs(i8 %a, i8 %b, i8 %c) {
ret i8 %max
}
+define i8 @smax_of_add_nsw_nuw_rhs_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_rhs_l(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT: [[MAX:%.*]] = add nsw i8 [[A]], [[TMP1]]
+; CHECK-NEXT: ret i8 [[MAX]]
+;
+ %add1 = add nsw i8 %a, %b
+ %add2 = add nsw nuw i8 %a, %c
+ %max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
+ ret i8 %max
+}
+
define i8 @smax_of_add_nsw_nuw_rhs_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_rhs_comm(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
@@ -357,14 +500,14 @@ define i8 @smax_of_add_nsw_nuw_rhs_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-NEXT: [[MAX:%.*]] = add nsw i8 [[TMP1]], [[A]]
; CHECK-NEXT: ret i8 [[MAX]]
;
- %add1 = add nsw i8 %a, %b
+ %add1 = add nsw i8 %b, %a
%add2 = add nsw nuw i8 %a, %c
%max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
ret i8 %max
}
-define i8 @smax_of_add_nsw_nuw(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw(
+define i8 @smax_of_add_nsw_nuw_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MAX:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
@@ -376,15 +519,28 @@ define i8 @smax_of_add_nsw_nuw(i8 %a, i8 %b, i8 %c) {
ret i8 %max
}
+define i8 @smax_of_add_nsw_nuw_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_l(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT: [[MAX:%.*]] = add nuw nsw i8 [[A]], [[TMP1]]
+; CHECK-NEXT: ret i8 [[MAX]]
+;
+ %add1 = add nsw nuw i8 %a, %b
+ %add2 = add nsw nuw i8 %a, %c
+ %max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
+ ret i8 %max
+}
+
define i8 @smax_of_add_nsw_nuw_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: define i8 @smax_of_add_nsw_nuw_comm(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smax.i8(i8 [[B]], i8 [[C]])
-; CHECK-NEXT: [[MAX:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
+; CHECK-NEXT: [[MAX:%.*]] = add nuw nsw i8 [[A]], [[TMP1]]
; CHECK-NEXT: ret i8 [[MAX]]
;
%add1 = add nsw nuw i8 %a, %b
- %add2 = add nsw nuw i8 %a, %c
+ %add2 = add nsw nuw i8 %c, %a
%max = call i8 @llvm.smax.i8(i8 %add1, i8 %add2)
ret i8 %max
}
@@ -419,8 +575,8 @@ define i8 @smin_of_add_nuw(i8 %a, i8 %b, i8 %c) {
ret i8 %min
}
-define i8 @smin_of_add_nsw(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @smin_of_add_nsw(
+define i8 @smin_of_add_nsw_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MIN:%.*]] = add nsw i8 [[TMP1]], [[A]]
@@ -432,6 +588,19 @@ define i8 @smin_of_add_nsw(i8 %a, i8 %b, i8 %c) {
ret i8 %min
}
+define i8 @smin_of_add_nsw_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_l(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT: [[MIN:%.*]] = add nsw i8 [[A]], [[TMP1]]
+; CHECK-NEXT: ret i8 [[MIN]]
+;
+ %add1 = add nsw i8 %a, %b
+ %add2 = add nsw i8 %a, %c
+ %min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
+ ret i8 %min
+}
+
define i8 @smin_of_add_nsw_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: define i8 @smin_of_add_nsw_comm(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
@@ -439,14 +608,14 @@ define i8 @smin_of_add_nsw_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-NEXT: [[MIN:%.*]] = add nsw i8 [[TMP1]], [[A]]
; CHECK-NEXT: ret i8 [[MIN]]
;
- %add1 = add nsw i8 %a, %b
+ %add1 = add nsw i8 %b, %a
%add2 = add nsw i8 %a, %c
%min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
ret i8 %min
}
-define i8 @smin_of_add_nsw_nuw_lhs(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_lhs(
+define i8 @smin_of_add_nsw_nuw_lhs_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_lhs_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MIN:%.*]] = add nsw i8 [[TMP1]], [[A]]
@@ -458,11 +627,11 @@ define i8 @smin_of_add_nsw_nuw_lhs(i8 %a, i8 %b, i8 %c) {
ret i8 %min
}
-define i8 @smin_of_add_nsw_nuw_lhs_comm(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_lhs_comm(
+define i8 @smin_of_add_nsw_nuw_lhs_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_lhs_l(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
-; CHECK-NEXT: [[MIN:%.*]] = add nsw i8 [[TMP1]], [[A]]
+; CHECK-NEXT: [[MIN:%.*]] = add nsw i8 [[A]], [[TMP1]]
; CHECK-NEXT: ret i8 [[MIN]]
;
%add1 = add nsw nuw i8 %a, %b
@@ -471,8 +640,22 @@ define i8 @smin_of_add_nsw_nuw_lhs_comm(i8 %a, i8 %b, i8 %c) {
ret i8 %min
}
-define i8 @smin_of_add_nsw_nuw_rhs(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_rhs(
+define i8 @smin_of_add_nsw_nuw_lhs_comm(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_lhs_comm(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[ADD1:%.*]] = add nuw nsw i8 [[A]], [[B]]
+; CHECK-NEXT: [[ADD2:%.*]] = add nuw i8 [[C]], [[A]]
+; CHECK-NEXT: [[MIN:%.*]] = call i8 @llvm.smin.i8(i8 [[ADD1]], i8 [[ADD2]])
+; CHECK-NEXT: ret i8 [[MIN]]
+;
+ %add1 = add nsw nuw i8 %a, %b
+ %add2 = add nuw i8 %c, %a
+ %min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
+ ret i8 %min
+}
+
+define i8 @smin_of_add_nsw_nuw_rhs_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_rhs_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MIN:%.*]] = add nsw i8 [[TMP1]], [[A]]
@@ -484,6 +667,19 @@ define i8 @smin_of_add_nsw_nuw_rhs(i8 %a, i8 %b, i8 %c) {
ret i8 %min
}
+define i8 @smin_of_add_nsw_nuw_rhs_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_rhs_l(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT: [[MIN:%.*]] = add nsw i8 [[A]], [[TMP1]]
+; CHECK-NEXT: ret i8 [[MIN]]
+;
+ %add1 = add nsw i8 %a, %b
+ %add2 = add nsw nuw i8 %a, %c
+ %min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
+ ret i8 %min
+}
+
define i8 @smin_of_add_nsw_nuw_rhs_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_rhs_comm(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
@@ -491,14 +687,15 @@ define i8 @smin_of_add_nsw_nuw_rhs_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-NEXT: [[MIN:%.*]] = add nsw i8 [[TMP1]], [[A]]
; CHECK-NEXT: ret i8 [[MIN]]
;
- %add1 = add nsw i8 %a, %b
+ %add1 = add nsw i8 %b, %a
%add2 = add nsw nuw i8 %a, %c
%min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
ret i8 %min
}
-define i8 @smin_of_add_nsw_nuw(i8 %a, i8 %b, i8 %c) {
-; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw(
+
+define i8 @smin_of_add_nsw_nuw_r(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_r(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
; CHECK-NEXT: [[MIN:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
@@ -510,15 +707,28 @@ define i8 @smin_of_add_nsw_nuw(i8 %a, i8 %b, i8 %c) {
ret i8 %min
}
+define i8 @smin_of_add_nsw_nuw_l(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_l(
+; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
+; CHECK-NEXT: [[MIN:%.*]] = add nuw nsw i8 [[A]], [[TMP1]]
+; CHECK-NEXT: ret i8 [[MIN]]
+;
+ %add1 = add nsw nuw i8 %a, %b
+ %add2 = add nsw nuw i8 %a, %c
+ %min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
+ ret i8 %min
+}
+
define i8 @smin_of_add_nsw_nuw_comm(i8 %a, i8 %b, i8 %c) {
; CHECK-LABEL: define i8 @smin_of_add_nsw_nuw_comm(
; CHECK-SAME: i8 [[A:%.*]], i8 [[B:%.*]], i8 [[C:%.*]]) {
; CHECK-NEXT: [[TMP1:%.*]] = call i8 @llvm.smin.i8(i8 [[B]], i8 [[C]])
-; CHECK-NEXT: [[MIN:%.*]] = add nuw nsw i8 [[TMP1]], [[A]]
+; CHECK-NEXT: [[MIN:%.*]] = add nuw nsw i8 [[A]], [[TMP1]]
; CHECK-NEXT: ret i8 [[MIN]]
;
%add1 = add nsw nuw i8 %a, %b
- %add2 = add nsw nuw i8 %a, %c
+ %add2 = add nsw nuw i8 %c, %a
%min = call i8 @llvm.smin.i8(i8 %add1, i8 %add2)
ret i8 %min
}
diff --git a/llvm/test/Transforms/InstCombine/shift-uminmax.ll b/llvm/test/Transforms/InstCombine/shift-uminmax.ll
new file mode 100644
index 0000000000000..21f8ac9f34674
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/shift-uminmax.ll
@@ -0,0 +1,418 @@
+; 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(z, x), nuw_shl(z, y)) -> nuw_shl(z, umax(x, y))
+; umin(nuw_shl(z, x), nuw_shl(z, y)) -> nuw_shl(z, umin(x, y))
+; umax(nuw_shl(x, z), nuw_shl(y, z)) -> nuw_shl(umax(x, y), z)
+; umin(nuw_shl(x, z), nuw_shl(y, z)) -> nuw_shl(umin(x, y), z)
+
+define i32 @umax_shl_common_lhs(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umax_shl_common_lhs(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: [[MAX:%.*]] = shl nuw i32 [[Z]], [[TMP1]]
+; CHECK-NEXT: ret i32 [[MAX]]
+;
+ %shl_x = shl nuw i32 %z, %x
+ %shl_y = shl nuw i32 %z, %y
+ %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %max
+}
+
+define i32 @umax_shl_common_rhs(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umax_shl_common_rhs(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: [[MAX:%.*]] = shl nuw i32 [[TMP1]], [[Z]]
+; CHECK-NEXT: ret i32 [[MAX]]
+;
+ %shl_x = shl nuw i32 %x, %z
+ %shl_y = shl nuw i32 %y, %z
+ %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %max
+}
+
+define i32 @umin_shl_common_lhs(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umin_shl_common_lhs(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: [[MIN:%.*]] = shl nuw i32 [[Z]], [[TMP1]]
+; CHECK-NEXT: ret i32 [[MIN]]
+;
+ %shl_x = shl nuw i32 %z, %x
+ %shl_y = shl nuw i32 %z, %y
+ %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %min
+}
+
+define i32 @umin_shl_common_rhs(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umin_shl_common_rhs(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: [[MIN:%.*]] = shl nuw i32 [[TMP1]], [[Z]]
+; CHECK-NEXT: ret i32 [[MIN]]
+;
+ %shl_x = shl nuw i32 %x, %z
+ %shl_y = shl nuw i32 %y, %z
+ %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %min
+}
+
+define i32 @umax_shl_common_lhs_const1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umax_shl_common_lhs_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: 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 @umax_shl_common_rhs_const1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umax_shl_common_rhs_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 [[TMP1]], 1
+; CHECK-NEXT: ret i32 [[MAX]]
+;
+ %shl_x = shl nuw i32 %x, 1
+ %shl_y = shl nuw i32 %y, 1
+ %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %max
+}
+
+define i32 @umin_shl_common_lhs_const1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umin_shl_common_lhs_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: 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 @umin_shl_common_rhs_const1(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umin_shl_common_rhs_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 [[TMP1]], 1
+; CHECK-NEXT: ret i32 [[MIN]]
+;
+ %shl_x = shl nuw i32 %x, 1
+ %shl_y = shl nuw i32 %y, 1
+ %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %min
+}
+
+declare void @use(i8)
+
+define i32 @umax_shl_common_lhs_multi_use(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umax_shl_common_lhs_multi_use(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT: [[SHL_X:%.*]] = shl nuw i32 [[Z]], [[X]]
+; CHECK-NEXT: [[SHL_Y:%.*]] = shl nuw i32 [[Z]], [[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 %z, %x
+ %shl_y = shl nuw i32 %z, %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 @umax_shl_common_rhs_multi_use(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umax_shl_common_rhs_multi_use(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT: [[SHL_X:%.*]] = shl nuw i32 [[X]], [[Z]]
+; CHECK-NEXT: [[SHL_Y:%.*]] = shl nuw i32 [[Y]], [[Z]]
+; 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 %x, %z
+ %shl_y = shl nuw i32 %y, %z
+ 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 @umin_shl_common_lhs_multi_use(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umin_shl_common_lhs_multi_use(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT: [[SHL_X:%.*]] = shl nuw i32 [[Z]], [[X]]
+; CHECK-NEXT: [[SHL_Y:%.*]] = shl nuw i32 [[Z]], [[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 %z, %x
+ %shl_y = shl nuw i32 %z, %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 @umin_shl_common_rhs_multi_use(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umin_shl_common_rhs_multi_use(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT: [[SHL_X:%.*]] = shl nuw i32 [[X]], [[Z]]
+; CHECK-NEXT: [[SHL_Y:%.*]] = shl nuw i32 [[Y]], [[Z]]
+; 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 %x, %z
+ %shl_y = shl nuw i32 %y, %z
+ 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 @umax_shl_common_lhs_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umax_shl_common_lhs_commuted(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[Y]], i32 [[X]])
+; CHECK-NEXT: [[MAX:%.*]] = shl nuw i32 [[Z]], [[TMP1]]
+; CHECK-NEXT: ret i32 [[MAX]]
+;
+ %shl_x = shl nuw i32 %z, %x
+ %shl_y = shl nuw i32 %z, %y
+ %max = call i32 @llvm.umax.i32(i32 %shl_y, i32 %shl_x)
+ ret i32 %max
+}
+
+define i32 @umax_shl_common_rhs_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umax_shl_common_rhs_commuted(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[Y]], i32 [[X]])
+; CHECK-NEXT: [[MAX:%.*]] = shl nuw i32 [[TMP1]], [[Z]]
+; CHECK-NEXT: ret i32 [[MAX]]
+;
+ %shl_x = shl nuw i32 %x, %z
+ %shl_y = shl nuw i32 %y, %z
+ %max = call i32 @llvm.umax.i32(i32 %shl_y, i32 %shl_x)
+ ret i32 %max
+}
+
+define i32 @umin_shl_common_lhs_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umin_shl_common_lhs_commuted(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[Y]], i32 [[X]])
+; CHECK-NEXT: [[MIN:%.*]] = shl nuw i32 [[Z]], [[TMP1]]
+; CHECK-NEXT: ret i32 [[MIN]]
+;
+ %shl_x = shl nuw i32 %z, %x
+ %shl_y = shl nuw i32 %z, %y
+ %min = call i32 @llvm.umin.i32(i32 %shl_y, i32 %shl_x)
+ ret i32 %min
+}
+
+define i32 @umin_shl_common_rhs_commuted(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umin_shl_common_rhs_commuted(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umin.i32(i32 [[Y]], i32 [[X]])
+; CHECK-NEXT: [[MIN:%.*]] = shl nuw i32 [[TMP1]], [[Z]]
+; CHECK-NEXT: ret i32 [[MIN]]
+;
+ %shl_x = shl nuw i32 %x, %z
+ %shl_y = shl nuw i32 %y, %z
+ %min = call i32 @llvm.umin.i32(i32 %shl_y, i32 %shl_x)
+ ret i32 %min
+}
+
+define <2 x i32> @umax_shl_common_lhs_vector(<2 x i32> %z, <2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umax_shl_common_lhs_vector(
+; CHECK-SAME: <2 x i32> [[Z:%.*]], <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> [[Z]], [[TMP1]]
+; CHECK-NEXT: ret <2 x i32> [[MAX]]
+;
+ %shl_x = shl nuw <2 x i32> %z, %x
+ %shl_y = shl nuw <2 x i32> %z, %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> @umax_shl_common_rhs_vector(<2 x i32> %z, <2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umax_shl_common_rhs_vector(
+; CHECK-SAME: <2 x i32> [[Z:%.*]], <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> [[TMP1]], [[Z]]
+; CHECK-NEXT: ret <2 x i32> [[MAX]]
+;
+ %shl_x = shl nuw <2 x i32> %x, %z
+ %shl_y = shl nuw <2 x i32> %y, %z
+ %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> @umin_shl_common_lhs_vector(<2 x i32> %z, <2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umin_shl_common_lhs_vector(
+; CHECK-SAME: <2 x i32> [[Z:%.*]], <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> [[Z]], [[TMP1]]
+; CHECK-NEXT: ret <2 x i32> [[MIN]]
+;
+ %shl_x = shl nuw <2 x i32> %z, %x
+ %shl_y = shl nuw <2 x i32> %z, %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> @umin_shl_common_rhs_vector(<2 x i32> %z, <2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umin_shl_common_rhs_vector(
+; CHECK-SAME: <2 x i32> [[Z:%.*]], <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> [[TMP1]], [[Z]]
+; CHECK-NEXT: ret <2 x i32> [[MIN]]
+;
+ %shl_x = shl nuw <2 x i32> %x, %z
+ %shl_y = shl nuw <2 x i32> %y, %z
+ %min = call <2 x i32> @llvm.umin.v2i32(<2 x i32> %shl_x, <2 x i32> %shl_y)
+ ret <2 x i32> %min
+}
+
+; Negative tests
+
+define i32 @umax_shl_
diff erent_lhs(i32 %z1, i32 %z2, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umax_shl_
diff erent_lhs(
+; CHECK-SAME: i32 [[Z1:%.*]], i32 [[Z2:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[SHL_X:%.*]] = shl nuw i32 [[Z1]], [[X]]
+; CHECK-NEXT: [[SHL_Y:%.*]] = shl nuw i32 [[Z2]], [[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 %z1, %x
+ %shl_y = shl nuw i32 %z2, %y
+ %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %max
+}
+
+define i32 @umax_shl_
diff erent_rhs(i32 %z1, i32 %z2, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umax_shl_
diff erent_rhs(
+; CHECK-SAME: i32 [[Z1:%.*]], i32 [[Z2:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[SHL_X:%.*]] = shl nuw i32 [[X]], [[Z1]]
+; CHECK-NEXT: [[SHL_Y:%.*]] = shl nuw i32 [[Y]], [[Z2]]
+; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT: ret i32 [[MAX]]
+;
+ %shl_x = shl nuw i32 %x, %z1
+ %shl_y = shl nuw i32 %y, %z2
+ %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %max
+}
+
+define i32 @umin_shl_
diff erent_lhs(i32 %z1, i32 %z2, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umin_shl_
diff erent_lhs(
+; CHECK-SAME: i32 [[Z1:%.*]], i32 [[Z2:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[SHL_X:%.*]] = shl nuw i32 [[Z1]], [[X]]
+; CHECK-NEXT: [[SHL_Y:%.*]] = shl nuw i32 [[Z2]], [[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 %z1, %x
+ %shl_y = shl nuw i32 %z2, %y
+ %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %min
+}
+
+define i32 @umin_shl_
diff erent_rhs(i32 %z1, i32 %z2, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umin_shl_
diff erent_rhs(
+; CHECK-SAME: i32 [[Z1:%.*]], i32 [[Z2:%.*]], i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[SHL_X:%.*]] = shl nuw i32 [[X]], [[Z1]]
+; CHECK-NEXT: [[SHL_Y:%.*]] = shl nuw i32 [[Y]], [[Z2]]
+; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT: ret i32 [[MIN]]
+;
+ %shl_x = shl nuw i32 %x, %z1
+ %shl_y = shl nuw i32 %y, %z2
+ %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %min
+}
+
+define i32 @umax_shl_does_not_commute(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umax_shl_does_not_commute(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT: [[SHL_X:%.*]] = shl nuw i32 [[X]], [[Y]]
+; CHECK-NEXT: [[SHL_Y:%.*]] = shl nuw i32 [[Y]], [[Z]]
+; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT: ret i32 [[MAX]]
+;
+ %shl_x = shl nuw i32 %x, %y
+ %shl_y = shl nuw i32 %y, %z
+ %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %max
+}
+
+define i32 @umin_shl_does_not_commute(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umin_shl_does_not_commute(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT: [[SHL_X:%.*]] = shl nuw i32 [[X]], [[Y]]
+; CHECK-NEXT: [[SHL_Y:%.*]] = shl nuw i32 [[Y]], [[Z]]
+; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT: ret i32 [[MIN]]
+;
+ %shl_x = shl nuw i32 %x, %y
+ %shl_y = shl nuw i32 %y, %z
+ %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %min
+}
+
+define i32 @umax_shl_common_lhs_no_nuw_flag(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umax_shl_common_lhs_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 @umax_shl_common_rhs_no_nuw_flag(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umax_shl_common_rhs_no_nuw_flag(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[SHL_X:%.*]] = shl nuw i32 [[X]], 2
+; CHECK-NEXT: [[SHL_Y:%.*]] = shl i32 [[Y]], 2
+; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT: ret i32 [[MAX]]
+;
+ %shl_x = shl nuw i32 %x, 2
+ %shl_y = shl i32 %y, 2
+ %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %max
+}
+
+define i32 @umax_shl_common_lhs_preserve_nsw(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umax_shl_common_lhs_preserve_nsw(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]], i32 [[Z:%.*]]) {
+; CHECK-NEXT: [[TMP1:%.*]] = call i32 @llvm.umax.i32(i32 [[X]], i32 [[Y]])
+; CHECK-NEXT: [[MAX:%.*]] = shl nuw nsw i32 [[Z]], [[TMP1]]
+; CHECK-NEXT: ret i32 [[MAX]]
+;
+ %shl_x = shl nuw nsw i32 %z, %x
+ %shl_y = shl nuw nsw i32 %z, %y
+ %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %max
+}
More information about the llvm-commits
mailing list