[llvm] [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)` (PR #131076)
Nikita Popov via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 14 05:01:57 PDT 2025
- Previous message: [llvm] [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)` (PR #131076)
- Next message: [llvm] [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)` (PR #131076)
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
================
@@ -0,0 +1,663 @@
+; 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
+}
+
+define i32 @umax_shl_common_lhs_const5(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umax_shl_common_lhs_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: 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 @umax_shl_common_rhs_const5(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umax_shl_common_rhs_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 [[TMP1]], 5
+; CHECK-NEXT: ret i32 [[MIN]]
+;
+ %shl_x = shl nuw i32 %x, 5
+ %shl_y = shl nuw i32 %y, 5
+ %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %min
+}
+
+define i32 @umin_shl_common_lhs_const5(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umin_shl_common_lhs_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: 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
+}
+
+define i32 @umin_shl_common_rhs_const5(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umin_shl_common_rhs_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 [[TMP1]], 5
+; CHECK-NEXT: ret i32 [[MIN]]
+;
+ %shl_x = shl nuw i32 %x, 5
+ %shl_y = shl nuw i32 %y, 5
+ %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
+}
+
+define <2 x i32> @umax_shl_common_lhs_vector_splat(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umax_shl_common_lhs_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: 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> @umax_shl_common_rhs_vector_splat(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umax_shl_common_rhs_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> [[TMP1]], splat (i32 1)
+; CHECK-NEXT: ret <2 x i32> [[MAX]]
+;
+ %shl_x = shl nuw <2 x i32> %x, <i32 1, i32 1>
+ %shl_y = shl nuw <2 x i32> %y, <i32 1, i32 1>
+ %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_splat(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umin_shl_common_lhs_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: 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> @umin_shl_common_rhs_vector_splat(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umin_shl_common_rhs_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> [[TMP1]], splat (i32 1)
+; CHECK-NEXT: ret <2 x i32> [[MIN]]
+;
+ %shl_x = shl nuw <2 x i32> %x, <i32 1, i32 1>
+ %shl_y = shl nuw <2 x i32> %y, <i32 1, i32 1>
+ %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> @umax_shl_common_lhs_vector_splat_poison(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umax_shl_common_lhs_vector_splat_poison(
+; 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> <i32 1, i32 poison>, [[TMP1]]
+; 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> @umax_shl_common_rhs_vector_splat_poison(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umax_shl_common_rhs_vector_splat_poison(
+; 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> [[TMP1]], <i32 1, i32 poison>
+; CHECK-NEXT: ret <2 x i32> [[MAX]]
+;
+ %shl_x = shl nuw <2 x i32> %x, <i32 1, i32 poison>
+ %shl_y = shl nuw <2 x i32> %y, <i32 1, i32 poison>
+ %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_splat_poison(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umin_shl_common_lhs_vector_splat_poison(
+; 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> <i32 1, i32 poison>, [[TMP1]]
+; 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> @umin_shl_common_rhs_vector_splat_poison(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umin_shl_common_rhs_vector_splat_poison(
+; 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> [[TMP1]], <i32 1, i32 poison>
+; CHECK-NEXT: ret <2 x i32> [[MIN]]
+;
+ %shl_x = shl nuw <2 x i32> %x, <i32 1, i32 poison>
+ %shl_y = shl nuw <2 x i32> %y, <i32 1, i32 poison>
+ %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> @umax_shl_common_lhs_vector_non_splat(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umax_shl_common_lhs_vector_non_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> <i32 1, i32 2>, [[TMP1]]
+; 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> @umax_shl_common_rhs_vector_non_splat(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umax_shl_common_rhs_vector_non_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> [[TMP1]], <i32 1, i32 2>
+; CHECK-NEXT: ret <2 x i32> [[MAX]]
+;
+ %shl_x = shl nuw <2 x i32> %x, <i32 1, i32 2>
+ %shl_y = shl nuw <2 x i32> %y, <i32 1, i32 2>
+ %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_non_splat(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umin_shl_common_lhs_vector_non_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> <i32 1, i32 2>, [[TMP1]]
+; 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 <2 x i32> @umin_shl_common_rhs_vector_non_splat(<2 x i32> %x, <2 x i32> %y) {
+; CHECK-LABEL: define <2 x i32> @umin_shl_common_rhs_vector_non_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> [[TMP1]], <i32 1, i32 2>
+; CHECK-NEXT: ret <2 x i32> [[MIN]]
+;
+ %shl_x = shl nuw <2 x i32> %x, <i32 1, i32 2>
+ %shl_y = shl nuw <2 x i32> %y, <i32 1, i32 2>
+ %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 @umax_shl_different_lhs(i32 %z1, i32 %z2, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umax_shl_different_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_different_rhs(i32 %z1, i32 %z2, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umax_shl_different_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_different_lhs(i32 %z1, i32 %z2, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umin_shl_different_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_different_rhs(i32 %z1, i32 %z2, i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umin_shl_different_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_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 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 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 @umin_shl_common_lhs_no_nuw_flag(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umin_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: [[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
+}
+
+define i32 @umin_shl_common_rhs_no_nuw_flag(i32 %x, i32 %y) {
+; CHECK-LABEL: define i32 @umin_shl_common_rhs_no_nuw_flag(
+; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
+; CHECK-NEXT: [[SHL_X:%.*]] = shl i32 [[X]], 2
+; CHECK-NEXT: [[SHL_Y:%.*]] = shl i32 [[Y]], 2
+; CHECK-NEXT: [[MIN:%.*]] = call i32 @llvm.umin.i32(i32 [[SHL_X]], i32 [[SHL_Y]])
+; CHECK-NEXT: ret i32 [[MIN]]
+;
+ %shl_x = shl i32 %x, 2
+ %shl_y = shl i32 %y, 2
+ %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %min
+}
+
+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
+}
+
+define i32 @umax_shl_common_rhs_preserve_nsw(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umax_shl_common_rhs_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 [[TMP1]], [[Z]]
+; CHECK-NEXT: ret i32 [[MAX]]
+;
+ %shl_x = shl nuw nsw i32 %x, %z
+ %shl_y = shl nuw nsw i32 %y, %z
+ %max = call i32 @llvm.umax.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %max
+}
+
+define i32 @umin_shl_common_lhs_preserve_nsw(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umin_shl_common_lhs_preserve_nsw(
+; 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 nsw i32 [[Z]], [[TMP1]]
+; CHECK-NEXT: ret i32 [[MIN]]
+;
+ %shl_x = shl nuw nsw i32 %z, %x
+ %shl_y = shl nuw nsw i32 %z, %y
+ %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %min
+}
+
+define i32 @umin_shl_common_rhs_preserve_nsw(i32 %x, i32 %y, i32 %z) {
+; CHECK-LABEL: define i32 @umin_shl_common_rhs_preserve_nsw(
+; 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 nsw i32 [[TMP1]], [[Z]]
+; CHECK-NEXT: ret i32 [[MIN]]
+;
+ %shl_x = shl nuw nsw i32 %x, %z
+ %shl_y = shl nuw nsw i32 %y, %z
+ %min = call i32 @llvm.umin.i32(i32 %shl_x, i32 %shl_y)
+ ret i32 %min
+}
----------------
nikic wrote:
Maybe I missed it, but I'm missing a negative test to check that shl doesn't get commuted, so e.g. `shl x, y` and `shl y, z` don't fold.
https://github.com/llvm/llvm-project/pull/131076
- Previous message: [llvm] [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)` (PR #131076)
- Next message: [llvm] [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)` (PR #131076)
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the llvm-commits
mailing list