; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt < %s -passes=instcombine -S | FileCheck %s declare void @use8(i8) declare i64 @llvm.vscale.i64() declare i32 @llvm.vscale.i32() define i8 @srem_non_matching(i8 %X, i8 %Y) { ; CHECK-LABEL: @srem_non_matching( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], 15 ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[Y:%.*]], 5 ; CHECK-NEXT: [[R:%.*]] = srem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nsw nuw i8 %X, 15 %BO1 = mul nsw nuw i8 %Y, 5 %r = srem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_1_shl(i8 %X, i8 %Y) { ; CHECK-LABEL: @urem_1_shl( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 1, [[X:%.*]] ; CHECK-NEXT: [[NOTMASK:%.*]] = shl nsw i8 -1, [[Y:%.*]] ; CHECK-NEXT: [[TMP1:%.*]] = xor i8 [[NOTMASK]], -1 ; CHECK-NEXT: [[R:%.*]] = and i8 [[BO0]], [[TMP1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nsw nuw i8 1, %X %BO1 = shl nsw nuw i8 1, %Y %r = urem i8 %BO0, %BO1 ret i8 %r } define @urem_XY_XZ_with_CY_rem_CZ_eq_0_scalable( %X) { ; CHECK-LABEL: @urem_XY_XZ_with_CY_rem_CZ_eq_0_scalable( ; CHECK-NEXT: ret zeroinitializer ; %BO0 = mul nuw %X, shufflevector( insertelement( poison, i8 15, i64 0) , poison, zeroinitializer) %BO1 = mul %X, shufflevector( insertelement( poison, i8 5, i64 0) , poison, zeroinitializer) %r = urem %BO0, %BO1 ret %r } define i8 @urem_XY_XZ_with_CY_rem_CZ_eq_0(i8 %X) { ; CHECK-LABEL: @urem_XY_XZ_with_CY_rem_CZ_eq_0( ; CHECK-NEXT: ret i8 0 ; %BO0 = mul nuw i8 %X, 15 %BO1 = mul i8 %X, 5 %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_XY_XZ_with_CY_rem_CZ_eq_0_with_shl(i8 %X) { ; CHECK-LABEL: @urem_XY_XZ_with_CY_rem_CZ_eq_0_with_shl( ; CHECK-NEXT: ret i8 0 ; %BO0 = shl nuw i8 15, %X %BO1 = shl i8 5, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_XY_XZ_with_CY_rem_CZ_eq_0_fail_missing_flag(i8 %X) { ; CHECK-LABEL: @urem_XY_XZ_with_CY_rem_CZ_eq_0_fail_missing_flag( ; CHECK-NEXT: [[BO0:%.*]] = mul nsw i8 [[X:%.*]], 15 ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[X]], 5 ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nsw i8 %X, 15 %BO1 = mul nsw nuw i8 %X, 5 %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_XY_XZ_with_CY_lt_CZ(i8 %X) { ; CHECK-LABEL: @urem_XY_XZ_with_CY_lt_CZ( ; CHECK-NEXT: [[R:%.*]] = mul nuw i8 [[X:%.*]], 3 ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul i8 %X, 3 %BO1 = mul nuw i8 %X, 12 %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_XY_XZ_with_CY_lt_CZ_with_shl(i8 %X) { ; CHECK-LABEL: @urem_XY_XZ_with_CY_lt_CZ_with_shl( ; CHECK-NEXT: [[R:%.*]] = shl nuw i8 3, [[X:%.*]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl i8 3, %X %BO1 = shl nuw i8 12, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define <2 x i8> @urem_XY_XZ_with_CY_lt_CZ_with_nsw_out(<2 x i8> %X) { ; CHECK-LABEL: @urem_XY_XZ_with_CY_lt_CZ_with_nsw_out( ; CHECK-NEXT: [[R:%.*]] = shl nuw nsw <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i8> [[R]] ; %BO0 = shl nsw <2 x i8> %X, %BO1 = mul nuw <2 x i8> %X, %r = urem <2 x i8> %BO0, %BO1 ret <2 x i8> %r } define i8 @urem_XY_XZ_with_CY_lt_CZ_no_nsw_out(i8 %X) { ; CHECK-LABEL: @urem_XY_XZ_with_CY_lt_CZ_no_nsw_out( ; CHECK-NEXT: [[R:%.*]] = mul nuw i8 [[X:%.*]], 3 ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw i8 %X, 3 %BO1 = shl nsw nuw i8 %X, 3 %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_XY_XZ_with_CY_lt_CZ_fail_missing_flag(i8 %X) { ; CHECK-LABEL: @urem_XY_XZ_with_CY_lt_CZ_fail_missing_flag( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], 3 ; CHECK-NEXT: [[BO1:%.*]] = mul nsw i8 [[X]], 12 ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw nsw i8 %X, 3 %BO1 = mul nsw i8 %X, 12 %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_XY_XZ_with_CY_gt_CZ(i8 %X) { ; CHECK-LABEL: @urem_XY_XZ_with_CY_gt_CZ( ; CHECK-NEXT: [[R:%.*]] = mul nuw nsw i8 [[X:%.*]], 3 ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw i8 %X, 21 %BO1 = mul i8 %X, 6 %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_XY_XZ_with_CY_gt_CZ_fail_missing_flag(i8 %X) { ; CHECK-LABEL: @urem_XY_XZ_with_CY_gt_CZ_fail_missing_flag( ; CHECK-NEXT: [[BO0:%.*]] = mul nsw i8 [[X:%.*]], 21 ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[X]], 6 ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nsw i8 %X, 21 %BO1 = mul nsw nuw i8 %X, 6 %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_XY_XZ_with_Y_Z_is_mul_X_RemYZ(i8 %X, i8 %Y, i8 %Z) { ; CHECK-LABEL: @urem_XY_XZ_with_Y_Z_is_mul_X_RemYZ( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = mul nuw i8 [[Z:%.*]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw i8 %X, %Y %BO1 = mul nuw i8 %Z, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_XY_XZ_with_CX_Y_Z_is_mul_X_RemYZ(i8 %Y, i8 %Z) { ; CHECK-LABEL: @urem_XY_XZ_with_CX_Y_Z_is_mul_X_RemYZ( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw i8 [[Y:%.*]], 10 ; CHECK-NEXT: [[BO1:%.*]] = shl nuw i8 10, [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw i8 10, %Y %BO1 = shl nuw i8 10, %Z %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_with_nsw_out1(i8 %X, i8 %Y, i8 %Z) { ; CHECK-LABEL: @urem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_with_nsw_out1( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw i8 [[X]], [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw nsw i8 %X, %Y %BO1 = shl nuw i8 %X, %Z %r = urem i8 %BO0, %BO1 ret i8 %r } define <2 x i8> @urem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_with_nsw_out2(<2 x i8> %X, <2 x i8> %Y, <2 x i8> %Z) { ; CHECK-LABEL: @urem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_with_nsw_out2( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw <2 x i8> [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw <2 x i8> [[Z:%.*]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem <2 x i8> [[BO0]], [[BO1]] ; CHECK-NEXT: ret <2 x i8> [[R]] ; %BO0 = shl nuw <2 x i8> %Y, %X %BO1 = shl nuw nsw <2 x i8> %Z, %X %r = urem <2 x i8> %BO0, %BO1 ret <2 x i8> %r } define i8 @urem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_fail_reused1(i8 %X, i8 %Y, i8 %Z) { ; CHECK-LABEL: @urem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_fail_reused1( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[X]], [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: call void @use8(i8 [[BO0]]) ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nsw nuw i8 %X, %Y %BO1 = mul nsw nuw i8 %X, %Z %r = urem i8 %BO0, %BO1 call void @use8(i8 %BO0) ret i8 %r } define <2 x i8> @urem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_fail_missing_flags1(<2 x i8> %X, <2 x i8> %Y, <2 x i8> %Z) { ; CHECK-LABEL: @urem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_fail_missing_flags1( ; CHECK-NEXT: [[BO0:%.*]] = mul nsw <2 x i8> [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw <2 x i8> [[X]], [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = urem <2 x i8> [[BO0]], [[BO1]] ; CHECK-NEXT: ret <2 x i8> [[R]] ; %BO0 = mul nsw <2 x i8> %X, %Y %BO1 = mul nsw nuw <2 x i8> %X, %Z %r = urem <2 x i8> %BO0, %BO1 ret <2 x i8> %r } define i8 @urem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_fail_missing_flags2(i8 %X, i8 %Y, i8 %Z) { ; CHECK-LABEL: @urem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_fail_missing_flags2( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = shl nsw i8 [[X]], [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nsw nuw i8 %X, %Y %BO1 = shl nsw i8 %X, %Z %r = urem i8 %BO0, %BO1 ret i8 %r } ;; Signed Verions define @srem_XY_XZ_with_CY_rem_CZ_eq_0_scalable( %X) { ; CHECK-LABEL: @srem_XY_XZ_with_CY_rem_CZ_eq_0_scalable( ; CHECK-NEXT: ret zeroinitializer ; %BO0 = mul nsw %X, shufflevector( insertelement( poison, i8 15, i64 0) , poison, zeroinitializer) %BO1 = mul %X, shufflevector( insertelement( poison, i8 5, i64 0) , poison, zeroinitializer) %r = srem %BO0, %BO1 ret %r } define i8 @srem_XY_XZ_with_CY_rem_CZ_eq_0(i8 %X) { ; CHECK-LABEL: @srem_XY_XZ_with_CY_rem_CZ_eq_0( ; CHECK-NEXT: ret i8 0 ; %BO0 = mul nsw i8 %X, 9 %BO1 = mul i8 %X, 3 %r = srem i8 %BO0, %BO1 ret i8 %r } define i8 @srem_XY_XZ_with_CY_rem_CZ_eq_0_fail_missing_flag(i8 %X) { ; CHECK-LABEL: @srem_XY_XZ_with_CY_rem_CZ_eq_0_fail_missing_flag( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw i8 [[X:%.*]], 9 ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[X]], 3 ; CHECK-NEXT: [[R:%.*]] = srem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw i8 %X, 9 %BO1 = mul nsw nuw i8 %X, 3 %r = srem i8 %BO0, %BO1 ret i8 %r } define <2 x i8> @srem_XY_XZ_with_CY_lt_CZ(<2 x i8> %X) { ; CHECK-LABEL: @srem_XY_XZ_with_CY_lt_CZ( ; CHECK-NEXT: [[R:%.*]] = shl nsw <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i8> [[R]] ; %BO0 = shl <2 x i8> %X, %BO1 = mul nsw <2 x i8> %X, %r = srem <2 x i8> %BO0, %BO1 ret <2 x i8> %r } define i8 @srem_XY_XZ_with_CY_lt_CZ_with_nuw_out(i8 %X) { ; CHECK-LABEL: @srem_XY_XZ_with_CY_lt_CZ_with_nuw_out( ; CHECK-NEXT: [[R:%.*]] = mul nuw nsw i8 [[X:%.*]], 5 ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw i8 %X, 5 %BO1 = mul nsw i8 %X, 15 %r = srem i8 %BO0, %BO1 ret i8 %r } define <2 x i8> @srem_XY_XZ_with_CY_lt_CZ_with_nuw_out_with_shl(<2 x i8> %X) { ; CHECK-LABEL: @srem_XY_XZ_with_CY_lt_CZ_with_nuw_out_with_shl( ; CHECK-NEXT: [[R:%.*]] = shl nuw nsw <2 x i8> , [[X:%.*]] ; CHECK-NEXT: ret <2 x i8> [[R]] ; %BO0 = shl nuw <2 x i8> , %X %BO1 = shl nsw <2 x i8> , %X %r = srem <2 x i8> %BO0, %BO1 ret <2 x i8> %r } define i8 @srem_XY_XZ_with_CY_lt_CZ_no_nsw_out(i8 %X) { ; CHECK-LABEL: @srem_XY_XZ_with_CY_lt_CZ_no_nsw_out( ; CHECK-NEXT: [[R:%.*]] = mul nsw i8 [[X:%.*]], 5 ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nsw i8 %X, 5 %BO1 = shl nsw nuw i8 %X, 4 %r = srem i8 %BO0, %BO1 ret i8 %r } define i8 @srem_XY_XZ_with_CY_lt_CZ_fail_missing_flag(i8 %X) { ; CHECK-LABEL: @srem_XY_XZ_with_CY_lt_CZ_fail_missing_flag( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], 5 ; CHECK-NEXT: [[BO1:%.*]] = shl nuw i8 [[X]], 4 ; CHECK-NEXT: [[R:%.*]] = srem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw nsw i8 %X, 5 %BO1 = shl nuw i8 %X, 4 %r = srem i8 %BO0, %BO1 ret i8 %r } define i8 @srem_XY_XZ_with_CY_gt_CZ(i8 %X) { ; CHECK-LABEL: @srem_XY_XZ_with_CY_gt_CZ( ; CHECK-NEXT: [[R:%.*]] = shl nsw i8 [[X:%.*]], 1 ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nsw i8 %X, 3 %BO1 = mul nsw i8 %X, 6 %r = srem i8 %BO0, %BO1 ret i8 %r } define i8 @srem_XY_XZ_with_CY_gt_CZ_with_nuw_out(i8 %X) { ; CHECK-LABEL: @srem_XY_XZ_with_CY_gt_CZ_with_nuw_out( ; CHECK-NEXT: [[R:%.*]] = shl nuw nsw i8 [[X:%.*]], 2 ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nsw nuw i8 %X, 10 %BO1 = mul nsw i8 %X, 6 %r = srem i8 %BO0, %BO1 ret i8 %r } define <2 x i8> @srem_XY_XZ_with_CY_gt_CZ_no_nuw_out(<2 x i8> %X) { ; CHECK-LABEL: @srem_XY_XZ_with_CY_gt_CZ_no_nuw_out( ; CHECK-NEXT: [[R:%.*]] = shl nsw <2 x i8> [[X:%.*]], ; CHECK-NEXT: ret <2 x i8> [[R]] ; %BO0 = mul nsw <2 x i8> %X, %BO1 = shl nsw nuw <2 x i8> %X, %r = srem <2 x i8> %BO0, %BO1 ret <2 x i8> %r } define i8 @srem_XY_XZ_with_CY_gt_CZ_fail_missing_flag1(i8 %X) { ; CHECK-LABEL: @srem_XY_XZ_with_CY_gt_CZ_fail_missing_flag1( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], 10 ; CHECK-NEXT: [[BO1:%.*]] = mul nuw i8 [[X]], 6 ; CHECK-NEXT: [[R:%.*]] = srem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nsw nuw i8 %X, 10 %BO1 = mul nuw i8 %X, 6 %r = srem i8 %BO0, %BO1 ret i8 %r } define i8 @srem_XY_XZ_with_CY_gt_CZ_fail_missing_flag2(i8 %X) { ; CHECK-LABEL: @srem_XY_XZ_with_CY_gt_CZ_fail_missing_flag2( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw i8 [[X:%.*]], 4 ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[X]], 5 ; CHECK-NEXT: [[R:%.*]] = srem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw i8 %X, 4 %BO1 = mul nsw nuw i8 %X, 5 %r = srem i8 %BO0, %BO1 ret i8 %r } define i8 @srem_XY_XZ_with_Y_Z_is_mul_X_RemYZ(i8 %X, i8 %Y, i8 %Z) { ; CHECK-LABEL: @srem_XY_XZ_with_Y_Z_is_mul_X_RemYZ( ; CHECK-NEXT: [[BO0:%.*]] = mul nsw i8 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[X]], [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = srem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nsw i8 %Y, %X %BO1 = mul nsw nuw i8 %X, %Z %r = srem i8 %BO0, %BO1 ret i8 %r } define i8 @srem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_with_nuw_out(i8 %X, i8 %Y, i8 %Z) { ; CHECK-LABEL: @srem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_with_nuw_out( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[Z:%.*]], [[X]] ; CHECK-NEXT: [[R:%.*]] = srem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nsw nuw i8 %Y, %X %BO1 = mul nsw nuw i8 %Z, %X %r = srem i8 %BO0, %BO1 ret i8 %r } define i8 @srem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_fail_shl(i8 %X, i8 %Y, i8 %Z) { ; CHECK-LABEL: @srem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_fail_shl( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[X]], [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = srem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nsw nuw i8 %X, %Y %BO1 = shl nsw nuw i8 %X, %Z %r = srem i8 %BO0, %BO1 ret i8 %r } define i8 @srem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_fail_missing_flags1(i8 %X, i8 %Y, i8 %Z) { ; CHECK-LABEL: @srem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_fail_missing_flags1( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[X]], [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = srem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw i8 %X, %Y %BO1 = mul nsw nuw i8 %X, %Z %r = srem i8 %BO0, %BO1 ret i8 %r } define i8 @srem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_fail_missing_flags2(i8 %X, i8 %Y, i8 %Z) { ; CHECK-LABEL: @srem_XY_XZ_with_Y_Z_is_mul_X_RemYZ_fail_missing_flags2( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = mul nuw i8 [[X]], [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = srem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nsw nuw i8 %X, %Y %BO1 = mul nuw i8 %X, %Z %r = srem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_XY_shl_ZX_fail(i8 %X, i8 %Z, i8 %Y) { ; CHECK-LABEL: @urem_shl_XY_shl_ZX_fail( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[Z:%.*]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %X, %Y %BO1 = shl nuw nsw i8 %Z, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_mul_XY_shl_ZX_fail(i8 %X, i8 %Z, i8 %Y) { ; CHECK-LABEL: @urem_mul_XY_shl_ZX_fail( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[Z:%.*]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw nsw i8 %X, %Y %BO1 = shl nuw nsw i8 %Z, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_YX_shl_XZ_fail(i8 %X, i8 %Z, i8 %Y) { ; CHECK-LABEL: @urem_shl_YX_shl_XZ_fail( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[X]], [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %Y, %X %BO1 = shl nuw nsw i8 %X, %Z %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_YX_mul_XZ_fail(i8 %X, i8 %Z, i8 %Y) { ; CHECK-LABEL: @urem_shl_YX_mul_XZ_fail( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[X]], [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %Y, %X %BO1 = mul nuw nsw i8 %X, %Z %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_YX_mul_ZX_fail(i8 %X, i8 %Z, i8 %Y) { ; CHECK-LABEL: @urem_shl_YX_mul_ZX_fail( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[Z:%.*]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %Y, %X %BO1 = mul nuw nsw i8 %Z, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_mul_YX_shl_ZX_fail(i8 %X, i8 %Z, i8 %Y) { ; CHECK-LABEL: @urem_mul_YX_shl_ZX_fail( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[Z:%.*]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw nsw i8 %Y, %X %BO1 = shl nuw nsw i8 %Z, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_CXY_shl_ZCX_fail(i8 %Z, i8 %Y) { ; CHECK-LABEL: @urem_shl_CXY_shl_ZCX_fail( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 3, [[Y:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[Z:%.*]], 3 ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 3, %Y %BO1 = shl nuw nsw i8 %Z, 3 %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_YCX_shl_CXZ_fail(i8 %Z, i8 %Y) { ; CHECK-LABEL: @urem_shl_YCX_shl_CXZ_fail( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[Y:%.*]], 3 ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 3, [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %Y, 3 %BO1 = shl nuw nsw i8 3, %Z %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_YCX_mul_ZCX_fail(i8 %Z, i8 %Y) { ; CHECK-LABEL: @urem_shl_YCX_mul_ZCX_fail( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[Y:%.*]], 3 ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[Z:%.*]], 10 ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %Y, 3 %BO1 = mul nuw nsw i8 %Z, 10 %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_mul_YCX_shl_ZCX_fail(i8 %Z, i8 %Y) { ; CHECK-LABEL: @urem_mul_YCX_shl_ZCX_fail( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[Y:%.*]], 3 ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[Z:%.*]], 3 ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw nsw i8 %Y, 3 %BO1 = shl nuw nsw i8 %Z, 3 %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_XCY_shl_CZX_fail(i8 %X) { ; CHECK-LABEL: @urem_shl_XCY_shl_CZX_fail( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[X:%.*]], 3 ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 6, [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %X, 3 %BO1 = shl nuw nsw i8 6, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_mul_XCY_shl_CZX_fail(i8 %X) { ; CHECK-LABEL: @urem_mul_XCY_shl_CZX_fail( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], 6 ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 3, [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw nsw i8 %X, 6 %BO1 = shl nuw nsw i8 3, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_CYX_shl_XCZ_fail(i8 %X) { ; CHECK-LABEL: @urem_shl_CYX_shl_XCZ_fail( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 3, [[X:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[X]], 6 ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 3, %X %BO1 = shl nuw nsw i8 %X, 6 %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_CYX_mul_XCZ_fail(i8 %X) { ; CHECK-LABEL: @urem_shl_CYX_mul_XCZ_fail( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 3, [[X:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[X]], 10 ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 3, %X %BO1 = mul nuw nsw i8 %X, 10 %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_XX_shl_ZX(i8 %X, i8 %Z) { ; CHECK-LABEL: @urem_shl_XX_shl_ZX( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[X:%.*]], [[X]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[Z:%.*]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %X, %X %BO1 = shl nuw nsw i8 %Z, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_YX_shl_XX(i8 %X, i8 %Y) { ; CHECK-LABEL: @urem_shl_YX_shl_XX( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[X]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %Y, %X %BO1 = shl nuw nsw i8 %X, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_XX_shl_XZ(i8 %X, i8 %Z) { ; CHECK-LABEL: @urem_shl_XX_shl_XZ( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[X:%.*]], [[X]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[X]], [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %X, %X %BO1 = shl nuw nsw i8 %X, %Z %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_XY_shl_XX(i8 %X, i8 %Y) { ; CHECK-LABEL: @urem_shl_XY_shl_XX( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[X]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %X, %Y %BO1 = shl nuw nsw i8 %X, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_mul_XX_shl_ZX(i8 %X, i8 %Z) { ; CHECK-LABEL: @urem_mul_XX_shl_ZX( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], [[X]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[Z:%.*]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw nsw i8 %X, %X %BO1 = shl nuw nsw i8 %Z, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_mul_YX_shl_XX(i8 %X, i8 %Y) { ; CHECK-LABEL: @urem_mul_YX_shl_XX( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[X]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw nsw i8 %Y, %X %BO1 = shl nuw nsw i8 %X, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_mul_XX_shl_XZ(i8 %X, i8 %Z) { ; CHECK-LABEL: @urem_mul_XX_shl_XZ( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], [[X]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[X]], [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw nsw i8 %X, %X %BO1 = shl nuw nsw i8 %X, %Z %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_mul_XY_shl_XX(i8 %X, i8 %Y) { ; CHECK-LABEL: @urem_mul_XY_shl_XX( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[X]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw nsw i8 %X, %Y %BO1 = shl nuw nsw i8 %X, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_XX_mul_ZX(i8 %X, i8 %Z) { ; CHECK-LABEL: @urem_shl_XX_mul_ZX( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[X:%.*]], [[X]] ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[Z:%.*]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %X, %X %BO1 = mul nuw nsw i8 %Z, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_YX_mul_XX(i8 %X, i8 %Y) { ; CHECK-LABEL: @urem_shl_YX_mul_XX( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[Y:%.*]], [[X:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[X]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %Y, %X %BO1 = mul nuw nsw i8 %X, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_XX_mul_XZ(i8 %X, i8 %Z) { ; CHECK-LABEL: @urem_shl_XX_mul_XZ( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[X:%.*]], [[X]] ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[X]], [[Z:%.*]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %X, %X %BO1 = mul nuw nsw i8 %X, %Z %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_XY_mul_XX(i8 %X, i8 %Y) { ; CHECK-LABEL: @urem_shl_XY_mul_XX( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[X]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %X, %Y %BO1 = mul nuw nsw i8 %X, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_mul_XX_shl_XX(i8 %X) { ; CHECK-LABEL: @urem_mul_XX_shl_XX( ; CHECK-NEXT: [[BO0:%.*]] = mul nuw nsw i8 [[X:%.*]], [[X]] ; CHECK-NEXT: [[BO1:%.*]] = shl nuw nsw i8 [[X]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = mul nuw nsw i8 %X, %X %BO1 = shl nuw nsw i8 %X, %X %r = urem i8 %BO0, %BO1 ret i8 %r } define i8 @urem_shl_XX_mul_XX(i8 %X) { ; CHECK-LABEL: @urem_shl_XX_mul_XX( ; CHECK-NEXT: [[BO0:%.*]] = shl nuw nsw i8 [[X:%.*]], [[X]] ; CHECK-NEXT: [[BO1:%.*]] = mul nuw nsw i8 [[X]], [[X]] ; CHECK-NEXT: [[R:%.*]] = urem i8 [[BO0]], [[BO1]] ; CHECK-NEXT: ret i8 [[R]] ; %BO0 = shl nuw nsw i8 %X, %X %BO1 = mul nuw nsw i8 %X, %X %r = urem i8 %BO0, %BO1 ret i8 %r } ; Negative test: No attribute vscale_range to indicate range define i64 @urem_shl_vscale() { ; CHECK-LABEL: @urem_shl_vscale( ; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-NEXT: [[SHIFT:%.*]] = shl nuw nsw i64 [[VSCALE]], 2 ; CHECK-NEXT: [[REM:%.*]] = urem i64 1024, [[SHIFT]] ; CHECK-NEXT: ret i64 [[REM]] ; %vscale = call i64 @llvm.vscale.i64() %shift = shl nuw nsw i64 %vscale, 2 %rem = urem i64 1024, %shift ret i64 %rem } define i64 @urem_shl_vscale_range() vscale_range(1,16) { ; CHECK-LABEL: @urem_shl_vscale_range( ; CHECK-NEXT: ret i64 0 ; %vscale = call i64 @llvm.vscale.i64() %shift = shl nuw nsw i64 %vscale, 2 %rem = urem i64 1024, %shift ret i64 %rem } define i64 @urem_vscale_range() vscale_range(1,16) { ; CHECK-LABEL: @urem_vscale_range( ; CHECK-NEXT: ret i64 0 ; %vscale = call i64 @llvm.vscale.i64() %shift = shl nuw nsw i64 %vscale, 6 %rem = urem i64 1024, %shift ret i64 %rem } define i64 @urem_shl_vscale_out_of_range() vscale_range(1,16) { ; CHECK-LABEL: @urem_shl_vscale_out_of_range( ; CHECK-NEXT: ret i64 1024 ; %vscale = call i64 @llvm.vscale.i64() %shift = shl nuw nsw i64 %vscale, 11 %rem = urem i64 1024, %shift ret i64 %rem } ; Negative test: The min value 1 << 10 is overlap to 1024 define i64 @urem_shl_vscale_overlap() vscale_range(1,16) { ; CHECK-LABEL: @urem_shl_vscale_overlap( ; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-NEXT: [[SHIFT:%.*]] = shl nuw nsw i64 [[VSCALE]], 10 ; CHECK-NEXT: [[TMP1:%.*]] = add nuw nsw i64 [[SHIFT]], 2047 ; CHECK-NEXT: [[REM:%.*]] = and i64 [[TMP1]], 1024 ; CHECK-NEXT: ret i64 [[REM]] ; %vscale = call i64 @llvm.vscale.i64() %shift = shl nuw nsw i64 %vscale, 10 %rem = urem i64 1024, %shift ret i64 %rem } define i64 @and_add_vscale_range_low() vscale_range(1,16) { ; CHECK-LABEL: @and_add_vscale_range_low( ; CHECK-NEXT: ret i64 0 ; %vscale = call i64 @llvm.vscale.i64() %shift = shl nuw nsw i64 %vscale, 6 %add = add i64 %shift, -1 %rem = and i64 1024, %add ret i64 %rem } ; TODO: have no bits that may be part of the mask set, ; but now expect the const is a power of two define i64 @and_add_shl_vscale_not_power2() vscale_range(1,16) { ; CHECK-LABEL: @and_add_shl_vscale_not_power2( ; CHECK-NEXT: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64() ; CHECK-NEXT: [[SHIFT:%.*]] = shl nuw nsw i64 [[VSCALE]], 6 ; CHECK-NEXT: [[ADD:%.*]] = add nuw nsw i64 [[SHIFT]], 4095 ; CHECK-NEXT: [[REM:%.*]] = and i64 [[ADD]], 3072 ; CHECK-NEXT: ret i64 [[REM]] ; %vscale = call i64 @llvm.vscale.i64() %shift = shl nuw nsw i64 %vscale, 6 %add = add i64 %shift, -1 %rem = and i64 3072, %add ret i64 %rem } ; Allow for INT_MIN, https://alive2.llvm.org/ce/z/yZ_I2a define i32 @and_add_shl_vscale_not_power2_negative() vscale_range(1,16) { ; CHECK-LABEL: @and_add_shl_vscale_not_power2_negative( ; CHECK-NEXT: ret i32 0 ; %vscale = call i32 @llvm.vscale.i32() %shift = shl nuw nsw i32 %vscale, 6 %add = add i32 %shift, -1 %rem = and i32 -2147483648, %add ret i32 %rem } ; Negative test: the %sign may be 0, https://alive2.llvm.org/ce/z/WU_j4a define i32 @and_add_and (i32 %x) { ; CHECK-LABEL: @and_add_and( ; CHECK-NEXT: [[TMP1:%.*]] = shl i32 [[X:%.*]], 24 ; CHECK-NEXT: [[TMP2:%.*]] = and i32 [[TMP1]], -2147483648 ; CHECK-NEXT: [[AND:%.*]] = xor i32 [[TMP2]], -2147483648 ; CHECK-NEXT: ret i32 [[AND]] ; %x1 = lshr i32 %x, 7 %sign = and i32 %x1, 1 ; %sign = (%x >> 7) & 1 %add = add i32 %sign, -1 %and = and i32 %add, 2147483648 ret i32 %and }