; 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_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_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 }