diff options
-rw-r--r-- | llvm/test/Transforms/InstCombine/fcmp.ll | 200 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/fma.ll | 24 | ||||
-rw-r--r-- | llvm/test/Transforms/InstCombine/fmul.ll | 91 |
3 files changed, 226 insertions, 89 deletions
diff --git a/llvm/test/Transforms/InstCombine/fcmp.ll b/llvm/test/Transforms/InstCombine/fcmp.ll index 40f7bf9b64f..72de3dfaf5e 100644 --- a/llvm/test/Transforms/InstCombine/fcmp.ll +++ b/llvm/test/Transforms/InstCombine/fcmp.ll @@ -1,10 +1,11 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py ; RUN: opt -S -instcombine < %s | FileCheck %s -declare double @llvm.fabs.f64(double) nounwind readnone +declare double @llvm.fabs.f64(double) readnone -define i1 @test1(float %x, float %y) nounwind { +define i1 @test1(float %x, float %y) { ; CHECK-LABEL: @test1( -; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float %x, %y +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[CMP]] ; %ext1 = fpext float %x to double @@ -13,9 +14,9 @@ define i1 @test1(float %x, float %y) nounwind { ret i1 %cmp } -define i1 @test2(float %a) nounwind { +define i1 @test2(float %a) { ; CHECK-LABEL: @test2( -; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float %a, 1.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[A:%.*]], 1.000000e+00 ; CHECK-NEXT: ret i1 [[CMP]] ; %ext = fpext float %a to double @@ -23,9 +24,9 @@ define i1 @test2(float %a) nounwind { ret i1 %cmp } -define i1 @test3(float %a) nounwind { +define i1 @test3(float %a) { ; CHECK-LABEL: @test3( -; CHECK-NEXT: [[EXT:%.*]] = fpext float %a to double +; CHECK-NEXT: [[EXT:%.*]] = fpext float [[A:%.*]] to double ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[EXT]], 0x3FF0000000000001 ; CHECK-NEXT: ret i1 [[CMP]] ; @@ -34,9 +35,9 @@ define i1 @test3(float %a) nounwind { ret i1 %cmp } -define i1 @test4(float %a) nounwind { +define i1 @test4(float %a) { ; CHECK-LABEL: @test4( -; CHECK-NEXT: [[EXT:%.*]] = fpext float %a to double +; CHECK-NEXT: [[EXT:%.*]] = fpext float [[A:%.*]] to double ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[EXT]], 0x36A0000000000000 ; CHECK-NEXT: ret i1 [[CMP]] ; @@ -45,30 +46,75 @@ define i1 @test4(float %a) nounwind { ret i1 %cmp } -define i1 @test5(float %a) nounwind { -; CHECK-LABEL: @test5( -; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float %a, -1.000000e+00 +define i1 @fneg_constant_swap_pred(float %x) { +; CHECK-LABEL: @fneg_constant_swap_pred( +; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], -1.000000e+00 ; CHECK-NEXT: ret i1 [[CMP]] ; - %neg = fsub float -0.000000e+00, %a - %cmp = fcmp ogt float %neg, 1.000000e+00 + %neg = fsub float -0.0, %x + %cmp = fcmp ogt float %neg, 1.0 ret i1 %cmp } -define i1 @test6(float %x, float %y) nounwind { -; CHECK-LABEL: @test6( -; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float %x, %y +define <2 x i1> @fneg_constant_swap_pred_vec(<2 x float> %x) { +; CHECK-LABEL: @fneg_constant_swap_pred_vec( +; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x float> [[X:%.*]], <float -1.000000e+00, float -2.000000e+00> +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %neg = fsub <2 x float> <float -0.0, float -0.0>, %x + %cmp = fcmp ogt <2 x float> %neg, <float 1.0, float 2.0> + ret <2 x i1> %cmp +} + +define <2 x i1> @fneg_constant_swap_pred_vec_undef(<2 x float> %x) { +; CHECK-LABEL: @fneg_constant_swap_pred_vec_undef( +; CHECK-NEXT: [[NEG:%.*]] = fsub <2 x float> <float undef, float -0.000000e+00>, [[X:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <2 x float> [[NEG]], <float 1.000000e+00, float 2.000000e+00> +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %neg = fsub <2 x float> <float undef, float -0.0>, %x + %cmp = fcmp ogt <2 x float> %neg, <float 1.0, float 2.0> + ret <2 x i1> %cmp +} + +define i1 @fneg_fneg_swap_pred(float %x, float %y) { +; CHECK-LABEL: @fneg_fneg_swap_pred( +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret i1 [[CMP]] ; - %neg1 = fsub float -0.000000e+00, %x - %neg2 = fsub float -0.000000e+00, %y + %neg1 = fsub float -0.0, %x + %neg2 = fsub float -0.0, %y %cmp = fcmp olt float %neg1, %neg2 ret i1 %cmp } -define i1 @test7(float %x) nounwind readnone ssp noredzone { +define <2 x i1> @fneg_fneg_swap_pred_vec(<2 x float> %x, <2 x float> %y) { +; CHECK-LABEL: @fneg_fneg_swap_pred_vec( +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <2 x float> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %neg1 = fsub <2 x float> <float -0.0, float -0.0>, %x + %neg2 = fsub <2 x float> <float -0.0, float -0.0>, %y + %cmp = fcmp olt <2 x float> %neg1, %neg2 + ret <2 x i1> %cmp +} + +define <2 x i1> @fneg_fneg_swap_pred_vec_undef(<2 x float> %x, <2 x float> %y) { +; CHECK-LABEL: @fneg_fneg_swap_pred_vec_undef( +; CHECK-NEXT: [[NEG1:%.*]] = fsub <2 x float> <float -0.000000e+00, float undef>, [[X:%.*]] +; CHECK-NEXT: [[NEG2:%.*]] = fsub <2 x float> <float undef, float -0.000000e+00>, [[Y:%.*]] +; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x float> [[NEG1]], [[NEG2]] +; CHECK-NEXT: ret <2 x i1> [[CMP]] +; + %neg1 = fsub <2 x float> <float -0.0, float undef>, %x + %neg2 = fsub <2 x float> <float undef, float -0.0>, %y + %cmp = fcmp olt <2 x float> %neg1, %neg2 + ret <2 x i1> %cmp +} + +define i1 @test7(float %x) { ; CHECK-LABEL: @test7( -; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float %x, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: ret i1 [[CMP]] ; %ext = fpext float %x to ppc_fp128 @@ -76,9 +122,9 @@ define i1 @test7(float %x) nounwind readnone ssp noredzone { ret i1 %cmp } -define float @test8(float %x) nounwind readnone optsize ssp { +define float @test8(float %x) { ; CHECK-LABEL: @test8( -; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float %x, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00 ; CHECK-NEXT: [[CONV2:%.*]] = uitofp i1 [[CMP]] to float ; CHECK-NEXT: ret float [[CONV2]] ; @@ -90,212 +136,212 @@ define float @test8(float %x) nounwind readnone optsize ssp { ; Float comparison to zero shouldn't cast to double. } -declare double @fabs(double) nounwind readnone +declare double @fabs(double) readnone -define i32 @test9(double %a) nounwind { +define i32 @test9(double %a) { ; CHECK-LABEL: @test9( ; CHECK-NEXT: ret i32 0 ; - %call = tail call double @fabs(double %a) nounwind + %call = tail call double @fabs(double %a) %cmp = fcmp olt double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } -define i32 @test9_intrinsic(double %a) nounwind { +define i32 @test9_intrinsic(double %a) { ; CHECK-LABEL: @test9_intrinsic( ; CHECK-NEXT: ret i32 0 ; - %call = tail call double @llvm.fabs.f64(double %a) nounwind + %call = tail call double @llvm.fabs.f64(double %a) %cmp = fcmp olt double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } -define i32 @test10(double %a) nounwind { +define i32 @test10(double %a) { ; CHECK-LABEL: @test10( -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double %a, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; - %call = tail call double @fabs(double %a) nounwind + %call = tail call double @fabs(double %a) %cmp = fcmp ole double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } -define i32 @test10_intrinsic(double %a) nounwind { +define i32 @test10_intrinsic(double %a) { ; CHECK-LABEL: @test10_intrinsic( -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double %a, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; - %call = tail call double @llvm.fabs.f64(double %a) nounwind + %call = tail call double @llvm.fabs.f64(double %a) %cmp = fcmp ole double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } -define i32 @test11(double %a) nounwind { +define i32 @test11(double %a) { ; CHECK-LABEL: @test11( -; CHECK-NEXT: [[CMP:%.*]] = fcmp one double %a, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; - %call = tail call double @fabs(double %a) nounwind + %call = tail call double @fabs(double %a) %cmp = fcmp ogt double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } -define i32 @test11_intrinsic(double %a) nounwind { +define i32 @test11_intrinsic(double %a) { ; CHECK-LABEL: @test11_intrinsic( -; CHECK-NEXT: [[CMP:%.*]] = fcmp one double %a, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; - %call = tail call double @llvm.fabs.f64(double %a) nounwind + %call = tail call double @llvm.fabs.f64(double %a) %cmp = fcmp ogt double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } -define i32 @test12(double %a) nounwind { +define i32 @test12(double %a) { ; CHECK-LABEL: @test12( -; CHECK-NEXT: [[CMP:%.*]] = fcmp ord double %a, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp ord double [[A:%.*]], 0.000000e+00 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; - %call = tail call double @fabs(double %a) nounwind + %call = tail call double @fabs(double %a) %cmp = fcmp oge double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } -define i32 @test12_intrinsic(double %a) nounwind { +define i32 @test12_intrinsic(double %a) { ; CHECK-LABEL: @test12_intrinsic( -; CHECK-NEXT: [[CMP:%.*]] = fcmp ord double %a, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp ord double [[A:%.*]], 0.000000e+00 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; - %call = tail call double @llvm.fabs.f64(double %a) nounwind + %call = tail call double @llvm.fabs.f64(double %a) %cmp = fcmp oge double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } -define i32 @test13(double %a) nounwind { +define i32 @test13(double %a) { ; CHECK-LABEL: @test13( -; CHECK-NEXT: [[CMP:%.*]] = fcmp une double %a, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[A:%.*]], 0.000000e+00 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; - %call = tail call double @fabs(double %a) nounwind + %call = tail call double @fabs(double %a) %cmp = fcmp une double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } -define i32 @test13_intrinsic(double %a) nounwind { +define i32 @test13_intrinsic(double %a) { ; CHECK-LABEL: @test13_intrinsic( -; CHECK-NEXT: [[CMP:%.*]] = fcmp une double %a, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp une double [[A:%.*]], 0.000000e+00 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; - %call = tail call double @llvm.fabs.f64(double %a) nounwind + %call = tail call double @llvm.fabs.f64(double %a) %cmp = fcmp une double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } -define i32 @test14(double %a) nounwind { +define i32 @test14(double %a) { ; CHECK-LABEL: @test14( -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double %a, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; - %call = tail call double @fabs(double %a) nounwind + %call = tail call double @fabs(double %a) %cmp = fcmp oeq double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } -define i32 @test14_intrinsic(double %a) nounwind { +define i32 @test14_intrinsic(double %a) { ; CHECK-LABEL: @test14_intrinsic( -; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double %a, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[A:%.*]], 0.000000e+00 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; - %call = tail call double @llvm.fabs.f64(double %a) nounwind + %call = tail call double @llvm.fabs.f64(double %a) %cmp = fcmp oeq double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } -define i32 @test15(double %a) nounwind { +define i32 @test15(double %a) { ; CHECK-LABEL: @test15( -; CHECK-NEXT: [[CMP:%.*]] = fcmp one double %a, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; - %call = tail call double @fabs(double %a) nounwind + %call = tail call double @fabs(double %a) %cmp = fcmp one double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } -define i32 @test15_intrinsic(double %a) nounwind { +define i32 @test15_intrinsic(double %a) { ; CHECK-LABEL: @test15_intrinsic( -; CHECK-NEXT: [[CMP:%.*]] = fcmp one double %a, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp one double [[A:%.*]], 0.000000e+00 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; - %call = tail call double @llvm.fabs.f64(double %a) nounwind + %call = tail call double @llvm.fabs.f64(double %a) %cmp = fcmp one double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } -define i32 @test16(double %a) nounwind { +define i32 @test16(double %a) { ; CHECK-LABEL: @test16( -; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double %a, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[A:%.*]], 0.000000e+00 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; - %call = tail call double @fabs(double %a) nounwind + %call = tail call double @fabs(double %a) %cmp = fcmp ueq double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } -define i32 @test16_intrinsic(double %a) nounwind { +define i32 @test16_intrinsic(double %a) { ; CHECK-LABEL: @test16_intrinsic( -; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double %a, 0.000000e+00 +; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[A:%.*]], 0.000000e+00 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; - %call = tail call double @llvm.fabs.f64(double %a) nounwind + %call = tail call double @llvm.fabs.f64(double %a) %cmp = fcmp ueq double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } ; Don't crash. -define i32 @test17(double %a, double (double)* %p) nounwind { +define i32 @test17(double %a, double (double)* %p) { ; CHECK-LABEL: @test17( -; CHECK-NEXT: [[CALL:%.*]] = tail call double %p(double %a) #1 +; CHECK-NEXT: [[CALL:%.*]] = tail call double [[P:%.*]](double [[A:%.*]]) ; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[CALL]], 0.000000e+00 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32 ; CHECK-NEXT: ret i32 [[CONV]] ; - %call = tail call double %p(double %a) nounwind + %call = tail call double %p(double %a) %cmp = fcmp ueq double %call, 0.000000e+00 %conv = zext i1 %cmp to i32 ret i32 %conv } ; Can fold fcmp with undef on one side by choosing NaN for the undef -define i32 @test18_undef_unordered(float %a) nounwind { +define i32 @test18_undef_unordered(float %a) { ; CHECK-LABEL: @test18_undef_unordered( ; CHECK-NEXT: ret i32 1 ; @@ -304,7 +350,7 @@ define i32 @test18_undef_unordered(float %a) nounwind { ret i32 %conv } ; Can fold fcmp with undef on one side by choosing NaN for the undef -define i32 @test18_undef_ordered(float %a) nounwind { +define i32 @test18_undef_ordered(float %a) { ; CHECK-LABEL: @test18_undef_ordered( ; CHECK-NEXT: ret i32 0 ; @@ -318,7 +364,7 @@ define i32 @test18_undef_ordered(float %a) nounwind { ; fcmp o_pred undef, undef -> false ; because whatever you choose for the first undef ; you can choose NaN for the other undef -define i1 @test19_undef_unordered() nounwind { +define i1 @test19_undef_unordered() { ; CHECK-LABEL: @test19_undef_unordered( ; CHECK-NEXT: ret i1 true ; @@ -326,7 +372,7 @@ define i1 @test19_undef_unordered() nounwind { ret i1 %cmp } -define i1 @test19_undef_ordered() nounwind { +define i1 @test19_undef_ordered() { ; CHECK-LABEL: @test19_undef_ordered( ; CHECK-NEXT: ret i1 false ; diff --git a/llvm/test/Transforms/InstCombine/fma.ll b/llvm/test/Transforms/InstCombine/fma.ll index 4270374379c..7efa8bfd0c6 100644 --- a/llvm/test/Transforms/InstCombine/fma.ll +++ b/llvm/test/Transforms/InstCombine/fma.ll @@ -19,6 +19,30 @@ define float @fma_fneg_x_fneg_y(float %x, float %y, float %z) { ret float %fma } +define <2 x float> @fma_fneg_x_fneg_y_vec(<2 x float> %x, <2 x float> %y, <2 x float> %z) { +; CHECK-LABEL: @fma_fneg_x_fneg_y_vec( +; CHECK-NEXT: [[FMA:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[X:%.*]], <2 x float> [[Y:%.*]], <2 x float> [[Z:%.*]]) +; CHECK-NEXT: ret <2 x float> [[FMA]] +; + %xn = fsub <2 x float> <float -0.0, float -0.0>, %x + %yn = fsub <2 x float> <float -0.0, float -0.0>, %y + %fma = call <2 x float> @llvm.fma.v2f32(<2 x float> %xn, <2 x float> %yn, <2 x float> %z) + ret <2 x float> %fma +} + +define <2 x float> @fma_fneg_x_fneg_y_vec_undef(<2 x float> %x, <2 x float> %y, <2 x float> %z) { +; CHECK-LABEL: @fma_fneg_x_fneg_y_vec_undef( +; CHECK-NEXT: [[XN:%.*]] = fsub <2 x float> <float -0.000000e+00, float undef>, [[X:%.*]] +; CHECK-NEXT: [[YN:%.*]] = fsub <2 x float> <float undef, float -0.000000e+00>, [[Y:%.*]] +; CHECK-NEXT: [[FMA:%.*]] = call <2 x float> @llvm.fma.v2f32(<2 x float> [[XN]], <2 x float> [[YN]], <2 x float> [[Z:%.*]]) +; CHECK-NEXT: ret <2 x float> [[FMA]] +; + %xn = fsub <2 x float> <float -0.0, float undef>, %x + %yn = fsub <2 x float> <float undef, float -0.0>, %y + %fma = call <2 x float> @llvm.fma.v2f32(<2 x float> %xn, <2 x float> %yn, <2 x float> %z) + ret <2 x float> %fma +} + define float @fma_fneg_x_fneg_y_fast(float %x, float %y, float %z) { ; CHECK-LABEL: @fma_fneg_x_fneg_y_fast( ; CHECK-NEXT: [[FMA:%.*]] = call fast float @llvm.fma.f32(float [[X:%.*]], float [[Y:%.*]], float [[Z:%.*]]) diff --git a/llvm/test/Transforms/InstCombine/fmul.ll b/llvm/test/Transforms/InstCombine/fmul.ll index 4d8557f2645..5856a590d7d 100644 --- a/llvm/test/Transforms/InstCombine/fmul.ll +++ b/llvm/test/Transforms/InstCombine/fmul.ll @@ -7,18 +7,39 @@ define float @neg_constant(float %x) { ; CHECK-NEXT: [[MUL:%.*]] = fmul ninf float [[X:%.*]], -2.000000e+01 ; CHECK-NEXT: ret float [[MUL]] ; - %sub = fsub float -0.000000e+00, %x + %sub = fsub float -0.0, %x %mul = fmul ninf float %sub, 2.0e+1 ret float %mul } +define <2 x float> @neg_constant_vec(<2 x float> %x) { +; CHECK-LABEL: @neg_constant_vec( +; CHECK-NEXT: [[MUL:%.*]] = fmul ninf <2 x float> [[X:%.*]], <float -2.000000e+00, float -3.000000e+00> +; CHECK-NEXT: ret <2 x float> [[MUL]] +; + %sub = fsub <2 x float> <float -0.0, float -0.0>, %x + %mul = fmul ninf <2 x float> %sub, <float 2.0, float 3.0> + ret <2 x float> %mul +} + +define <2 x float> @neg_constant_vec_undef(<2 x float> %x) { +; CHECK-LABEL: @neg_constant_vec_undef( +; CHECK-NEXT: [[SUB:%.*]] = fsub <2 x float> <float undef, float -0.000000e+00>, [[X:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = fmul ninf <2 x float> [[SUB]], <float 2.000000e+00, float 3.000000e+00> +; CHECK-NEXT: ret <2 x float> [[MUL]] +; + %sub = fsub <2 x float> <float undef, float -0.0>, %x + %mul = fmul ninf <2 x float> %sub, <float 2.0, float 3.0> + ret <2 x float> %mul +} + ; (0.0 - X) * C => X * -C define float @neg_nsz_constant(float %x) { ; CHECK-LABEL: @neg_nsz_constant( ; CHECK-NEXT: [[MUL:%.*]] = fmul nnan float [[X:%.*]], -2.000000e+01 ; CHECK-NEXT: ret float [[MUL]] ; - %sub = fsub nsz float 0.000000e+00, %x + %sub = fsub nsz float 0.0, %x %mul = fmul nnan float %sub, 2.0e+1 ret float %mul } @@ -29,20 +50,44 @@ define float @neg_neg(float %x, float %y) { ; CHECK-NEXT: [[MUL:%.*]] = fmul arcp float [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret float [[MUL]] ; - %sub1 = fsub float -0.000000e+00, %x - %sub2 = fsub float -0.000000e+00, %y + %sub1 = fsub float -0.0, %x + %sub2 = fsub float -0.0, %y %mul = fmul arcp float %sub1, %sub2 ret float %mul } +define <2 x float> @neg_neg_vec(<2 x float> %x, <2 x float> %y) { +; CHECK-LABEL: @neg_neg_vec( +; CHECK-NEXT: [[MUL:%.*]] = fmul arcp <2 x float> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: ret <2 x float> [[MUL]] +; + %sub1 = fsub <2 x float> <float -0.0, float -0.0>, %x + %sub2 = fsub <2 x float> <float -0.0, float -0.0>, %y + %mul = fmul arcp <2 x float> %sub1, %sub2 + ret <2 x float> %mul +} + +define <2 x float> @neg_neg_vec_undef(<2 x float> %x, <2 x float> %y) { +; CHECK-LABEL: @neg_neg_vec_undef( +; CHECK-NEXT: [[SUB1:%.*]] = fsub <2 x float> <float -0.000000e+00, float undef>, [[X:%.*]] +; CHECK-NEXT: [[SUB2:%.*]] = fsub <2 x float> <float undef, float -0.000000e+00>, [[Y:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = fmul arcp <2 x float> [[SUB1]], [[SUB2]] +; CHECK-NEXT: ret <2 x float> [[MUL]] +; + %sub1 = fsub <2 x float> <float -0.0, float undef>, %x + %sub2 = fsub <2 x float> <float undef, float -0.0>, %y + %mul = fmul arcp <2 x float> %sub1, %sub2 + ret <2 x float> %mul +} + ; (0.0 - X) * (0.0 - Y) => X * Y define float @neg_neg_nsz(float %x, float %y) { ; CHECK-LABEL: @neg_neg_nsz( ; CHECK-NEXT: [[MUL:%.*]] = fmul afn float [[X:%.*]], [[Y:%.*]] ; CHECK-NEXT: ret float [[MUL]] ; - %sub1 = fsub nsz float 0.000000e+00, %x - %sub2 = fsub nsz float 0.000000e+00, %y + %sub1 = fsub nsz float 0.0, %x + %sub2 = fsub nsz float 0.0, %y %mul = fmul afn float %sub1, %sub2 ret float %mul } @@ -58,8 +103,8 @@ define float @neg_neg_multi_use(float %x, float %y) { ; CHECK-NEXT: call void @use_f32(float [[NY]]) ; CHECK-NEXT: ret float [[MUL]] ; - %nx = fsub float -0.000000e+00, %x - %ny = fsub float -0.000000e+00, %y + %nx = fsub float -0.0, %x + %ny = fsub float -0.0, %y %mul = fmul afn float %nx, %ny call void @use_f32(float %nx) call void @use_f32(float %ny) @@ -73,11 +118,33 @@ define float @neg_sink(float %x, float %y) { ; CHECK-NEXT: [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]] ; CHECK-NEXT: ret float [[MUL]] ; - %sub1 = fsub float -0.000000e+00, %x - %mul = fmul float %sub1, %y + %sub = fsub float -0.0, %x + %mul = fmul float %sub, %y ret float %mul } +define <2 x float> @neg_sink_vec(<2 x float> %x, <2 x float> %y) { +; CHECK-LABEL: @neg_sink_vec( +; CHECK-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[X:%.*]], [[Y:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = fsub <2 x float> <float -0.000000e+00, float -0.000000e+00>, [[TMP1]] +; CHECK-NEXT: ret <2 x float> [[MUL]] +; + %sub = fsub <2 x float> <float -0.0, float -0.0>, %x + %mul = fmul <2 x float> %sub, %y + ret <2 x float> %mul +} + +define <2 x float> @neg_sink_vec_undef(<2 x float> %x, <2 x float> %y) { +; CHECK-LABEL: @neg_sink_vec_undef( +; CHECK-NEXT: [[SUB:%.*]] = fsub <2 x float> <float undef, float -0.000000e+00>, [[X:%.*]] +; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[SUB]], [[Y:%.*]] +; CHECK-NEXT: ret <2 x float> [[MUL]] +; + %sub = fsub <2 x float> <float undef, float -0.0>, %x + %mul = fmul <2 x float> %sub, %y + ret <2 x float> %mul +} + ; (0.0 - X) * Y => 0.0 - (X * Y) define float @neg_sink_nsz(float %x, float %y) { ; CHECK-LABEL: @neg_sink_nsz( @@ -85,7 +152,7 @@ define float @neg_sink_nsz(float %x, float %y) { ; CHECK-NEXT: [[MUL:%.*]] = fsub float -0.000000e+00, [[TMP1]] ; CHECK-NEXT: ret float [[MUL]] ; - %sub1 = fsub nsz float 0.000000e+00, %x + %sub1 = fsub nsz float 0.0, %x %mul = fmul float %sub1, %y ret float %mul } @@ -99,7 +166,7 @@ define float @neg_sink_multi_use(float %x, float %y) { ; CHECK-NEXT: [[MUL2:%.*]] = fmul float [[MUL]], [[SUB1]] ; CHECK-NEXT: ret float [[MUL2]] ; - %sub1 = fsub float -0.000000e+00, %x + %sub1 = fsub float -0.0, %x %mul = fmul float %sub1, %y %mul2 = fmul float %mul, %sub1 ret float %mul2 |