diff --git a/llvm/test/Transforms/InstCombine/fmul-and-fdiv-by-int-pow2.ll b/llvm/test/Transforms/InstCombine/fmul-and-fdiv-by-int-pow2.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/InstCombine/fmul-and-fdiv-by-int-pow2.ll @@ -0,0 +1,214 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 3 +; RUN: opt < %s -passes=instcombine -S | FileCheck %s + +define double @fmul_dbl_pow_1_shl_cnt(i64 %cnt) { +; CHECK-LABEL: define double @fmul_dbl_pow_1_shl_cnt +; CHECK-SAME: (i64 [[CNT:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 1, [[CNT]] +; CHECK-NEXT: [[CONV:%.*]] = uitofp i64 [[SHL]] to double +; CHECK-NEXT: [[MUL:%.*]] = fmul double [[CONV]], 9.000000e+00 +; CHECK-NEXT: ret double [[MUL]] +; + %shl = shl nuw i64 1, %cnt + %conv = uitofp i64 %shl to double + %mul = fmul double 9.000000e+00, %conv + ret double %mul +} + +define double @fmul_dbl_pow_1_shl_cnt_fail_maybe_non_pow2(i64 %v, i64 %cnt) { +; CHECK-LABEL: define double @fmul_dbl_pow_1_shl_cnt_fail_maybe_non_pow2 +; CHECK-SAME: (i64 [[V:%.*]], i64 [[CNT:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 [[V]], [[CNT]] +; CHECK-NEXT: [[CONV:%.*]] = uitofp i64 [[SHL]] to double +; CHECK-NEXT: [[MUL:%.*]] = fmul double [[CONV]], 9.000000e+00 +; CHECK-NEXT: ret double [[MUL]] +; + %shl = shl nuw i64 %v, %cnt + %conv = uitofp i64 %shl to double + %mul = fmul double 9.000000e+00, %conv + ret double %mul +} + +define float @fmul_pow_1_shl_cnt(i64 %cnt) { +; CHECK-LABEL: define float @fmul_pow_1_shl_cnt +; CHECK-SAME: (i64 [[CNT:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw i64 8, [[CNT]] +; CHECK-NEXT: [[CONV:%.*]] = uitofp i64 [[SHL]] to float +; CHECK-NEXT: [[MUL:%.*]] = fmul float [[CONV]], -9.000000e+00 +; CHECK-NEXT: ret float [[MUL]] +; + %shl = shl nsw nuw i64 8, %cnt + %conv = uitofp i64 %shl to float + %mul = fmul float -9.000000e+00, %conv + ret float %mul +} + +define <2 x float> @fmul_pow_2_shl_cnt_vec(<2 x i64> %cnt) { +; CHECK-LABEL: define <2 x float> @fmul_pow_2_shl_cnt_vec +; CHECK-SAME: (<2 x i64> [[CNT:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw <2 x i64> , [[CNT]] +; CHECK-NEXT: [[CONV:%.*]] = uitofp <2 x i64> [[SHL]] to <2 x float> +; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[CONV]], +; CHECK-NEXT: ret <2 x float> [[MUL]] +; + %shl = shl nsw nuw <2 x i64> , %cnt + %conv = uitofp <2 x i64> %shl to <2 x float> + %mul = fmul <2 x float> , %conv + ret <2 x float> %mul +} + +define <2 x half> @fmul_pow_2_shl_cnt_vec_to_large(<2 x i64> %cnt) { +; CHECK-LABEL: define <2 x half> @fmul_pow_2_shl_cnt_vec_to_large +; CHECK-SAME: (<2 x i64> [[CNT:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl nuw nsw <2 x i64> , [[CNT]] +; CHECK-NEXT: [[CONV:%.*]] = uitofp <2 x i64> [[SHL]] to <2 x half> +; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x half> [[CONV]], +; CHECK-NEXT: ret <2 x half> [[MUL]] +; + %shl = shl nsw nuw <2 x i64> , %cnt + %conv = uitofp <2 x i64> %shl to <2 x half> + %mul = fmul <2 x half> , %conv + ret <2 x half> %mul +} + +define double @fmul_pow_1_shl_cnt_fail_maybe_bad_exp(i64 %cnt) { +; CHECK-LABEL: define double @fmul_pow_1_shl_cnt_fail_maybe_bad_exp +; CHECK-SAME: (i64 [[CNT:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl nuw i64 1, [[CNT]] +; CHECK-NEXT: [[CONV:%.*]] = uitofp i64 [[SHL]] to double +; CHECK-NEXT: [[MUL:%.*]] = fmul double [[CONV]], 0x7BEFFFFFFF5F3992 +; CHECK-NEXT: ret double [[MUL]] +; + %shl = shl nuw i64 1, %cnt + %conv = uitofp i64 %shl to double + %mul = fmul double 9.745314e+288, %conv + ret double %mul +} + +define double @fmul_pow_1_shl_cnt_safe(i16 %cnt) { +; CHECK-LABEL: define double @fmul_pow_1_shl_cnt_safe +; CHECK-SAME: (i16 [[CNT:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl nuw i16 1, [[CNT]] +; CHECK-NEXT: [[CONV:%.*]] = uitofp i16 [[SHL]] to double +; CHECK-NEXT: [[MUL:%.*]] = fmul double [[CONV]], 0x7BEFFFFFFF5F3992 +; CHECK-NEXT: ret double [[MUL]] +; + %shl = shl nuw i16 1, %cnt + %conv = uitofp i16 %shl to double + %mul = fmul double 9.745314e+288, %conv + ret double %mul +} + +define <2 x double> @fdiv_pow_1_shl_cnt_vec(<2 x i64> %cnt) { +; CHECK-LABEL: define <2 x double> @fdiv_pow_1_shl_cnt_vec +; CHECK-SAME: (<2 x i64> [[CNT:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl nuw <2 x i64> , [[CNT]] +; CHECK-NEXT: [[CONV:%.*]] = uitofp <2 x i64> [[SHL]] to <2 x double> +; CHECK-NEXT: [[MUL:%.*]] = fdiv <2 x double> , [[CONV]] +; CHECK-NEXT: ret <2 x double> [[MUL]] +; + %shl = shl nuw <2 x i64> , %cnt + %conv = uitofp <2 x i64> %shl to <2 x double> + %mul = fdiv <2 x double> , %conv + ret <2 x double> %mul +} + +define float @fdiv_pow_1_shl_cnt_fail_maybe_z(i64 %cnt) { +; CHECK-LABEL: define float @fdiv_pow_1_shl_cnt_fail_maybe_z +; CHECK-SAME: (i64 [[CNT:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl i64 8, [[CNT]] +; CHECK-NEXT: [[CONV:%.*]] = uitofp i64 [[SHL]] to float +; CHECK-NEXT: [[MUL:%.*]] = fdiv float -9.000000e+00, [[CONV]] +; CHECK-NEXT: ret float [[MUL]] +; + %shl = shl i64 8, %cnt + %conv = uitofp i64 %shl to float + %mul = fdiv float -9.000000e+00, %conv + ret float %mul +} + +define float @fdiv_pow_1_shl_cnt_fail_neg_int(i64 %cnt) { +; CHECK-LABEL: define float @fdiv_pow_1_shl_cnt_fail_neg_int +; CHECK-SAME: (i64 [[CNT:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl i64 8, [[CNT]] +; CHECK-NEXT: [[CONV:%.*]] = sitofp i64 [[SHL]] to float +; CHECK-NEXT: [[MUL:%.*]] = fdiv float -9.000000e+00, [[CONV]] +; CHECK-NEXT: ret float [[MUL]] +; + %shl = shl i64 8, %cnt + %conv = sitofp i64 %shl to float + %mul = fdiv float -9.000000e+00, %conv + ret float %mul +} + +define float @fdiv_pow_1_shl_cnt(i64 %cnt_in) { +; CHECK-LABEL: define float @fdiv_pow_1_shl_cnt +; CHECK-SAME: (i64 [[CNT_IN:%.*]]) { +; CHECK-NEXT: [[CNT:%.*]] = and i64 [[CNT_IN]], 31 +; CHECK-NEXT: [[SHL:%.*]] = shl i64 8, [[CNT]] +; CHECK-NEXT: [[CONV:%.*]] = sitofp i64 [[SHL]] to float +; CHECK-NEXT: [[MUL:%.*]] = fdiv float -5.000000e-01, [[CONV]] +; CHECK-NEXT: ret float [[MUL]] +; + %cnt = and i64 %cnt_in, 31 + %shl = shl i64 8, %cnt + %conv = sitofp i64 %shl to float + %mul = fdiv float -0.500000e+00, %conv + ret float %mul +} + +define half @fdiv_pow_1_shl_cnt_fail_out_of_bounds(i32 %cnt) { +; CHECK-LABEL: define half @fdiv_pow_1_shl_cnt_fail_out_of_bounds +; CHECK-SAME: (i32 [[CNT:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl nuw i32 1, [[CNT]] +; CHECK-NEXT: [[CONV:%.*]] = uitofp i32 [[SHL]] to half +; CHECK-NEXT: [[MUL:%.*]] = fdiv half 0xH7000, [[CONV]] +; CHECK-NEXT: ret half [[MUL]] +; + %shl = shl nuw i32 1, %cnt + %conv = uitofp i32 %shl to half + %mul = fdiv half 0xH7000, %conv + ret half %mul +} + +define half @fdiv_pow_1_shl_cnt_in_bounds(i16 %cnt) { +; CHECK-LABEL: define half @fdiv_pow_1_shl_cnt_in_bounds +; CHECK-SAME: (i16 [[CNT:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl nuw i16 1, [[CNT]] +; CHECK-NEXT: [[CONV:%.*]] = uitofp i16 [[SHL]] to half +; CHECK-NEXT: [[MUL:%.*]] = fdiv half 0xH7000, [[CONV]] +; CHECK-NEXT: ret half [[MUL]] +; + %shl = shl nuw i16 1, %cnt + %conv = uitofp i16 %shl to half + %mul = fdiv half 0xH7000, %conv + ret half %mul +} + +define half @fdiv_pow_1_shl_cnt_in_bounds2(i16 %cnt) { +; CHECK-LABEL: define half @fdiv_pow_1_shl_cnt_in_bounds2 +; CHECK-SAME: (i16 [[CNT:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl nuw i16 1, [[CNT]] +; CHECK-NEXT: [[CONV:%.*]] = uitofp i16 [[SHL]] to half +; CHECK-NEXT: [[MUL:%.*]] = fdiv half 0xH4800, [[CONV]] +; CHECK-NEXT: ret half [[MUL]] +; + %shl = shl nuw i16 1, %cnt + %conv = uitofp i16 %shl to half + %mul = fdiv half 0xH4800, %conv + ret half %mul +} + +define half @fdiv_pow_1_shl_cnt_in_bounds3(i16 %cnt) { +; CHECK-LABEL: define half @fdiv_pow_1_shl_cnt_in_bounds3 +; CHECK-SAME: (i16 [[CNT:%.*]]) { +; CHECK-NEXT: [[SHL:%.*]] = shl nuw i16 1, [[CNT]] +; CHECK-NEXT: [[CONV:%.*]] = uitofp i16 [[SHL]] to half +; CHECK-NEXT: [[MUL:%.*]] = fdiv half 0xH3800, [[CONV]] +; CHECK-NEXT: ret half [[MUL]] +; + %shl = shl nuw i16 1, %cnt + %conv = uitofp i16 %shl to half + %mul = fdiv half 0xH3800, %conv + ret half %mul +}