977 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3 4; PR43745 6define float @test1(float %x, float %y) {7; CHECK-LABEL: @test1(8; CHECK-NEXT: [[T1:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]9; CHECK-NEXT: [[T2:%.*]] = fneg float [[T1]]10; CHECK-NEXT: ret float [[T2]]11;12 %t1 = fsub float %x, %y13 %t2 = fsub float -0.0, %t114 ret float %t215}16 17define float @test1_unary(float %x, float %y) {18; CHECK-LABEL: @test1_unary(19; CHECK-NEXT: [[T1:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]20; CHECK-NEXT: [[T2:%.*]] = fneg float [[T1]]21; CHECK-NEXT: ret float [[T2]]22;23 %t1 = fsub float %x, %y24 %t2 = fneg float %t125 ret float %t226}27 28; Can't do anything with the test above because -0.0 - 0.0 = -0.0, but if we have nsz:29; -(X - Y) --> Y - X30 31define float @neg_sub_nsz(float %x, float %y) {32; CHECK-LABEL: @neg_sub_nsz(33; CHECK-NEXT: [[T2:%.*]] = fsub nsz float [[Y:%.*]], [[X:%.*]]34; CHECK-NEXT: ret float [[T2]]35;36 %t1 = fsub float %x, %y37 %t2 = fsub nsz float -0.0, %t138 ret float %t239}40 41define float @unary_neg_sub_nsz(float %x, float %y) {42; CHECK-LABEL: @unary_neg_sub_nsz(43; CHECK-NEXT: [[T2:%.*]] = fsub nsz float [[Y:%.*]], [[X:%.*]]44; CHECK-NEXT: ret float [[T2]]45;46 %t1 = fsub float %x, %y47 %t2 = fneg nsz float %t148 ret float %t249}50 51; If the subtract has another use, we don't do the transform (even though it52; doesn't increase the IR instruction count) because we assume that fneg is53; easier to analyze and generally cheaper than generic fsub.54 55declare void @use(float)56declare void @use2(float, double)57 58define float @neg_sub_nsz_extra_use(float %x, float %y) {59; CHECK-LABEL: @neg_sub_nsz_extra_use(60; CHECK-NEXT: [[T1:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]61; CHECK-NEXT: [[T2:%.*]] = fneg nsz float [[T1]]62; CHECK-NEXT: call void @use(float [[T1]])63; CHECK-NEXT: ret float [[T2]]64;65 %t1 = fsub float %x, %y66 %t2 = fsub nsz float -0.0, %t167 call void @use(float %t1)68 ret float %t269}70 71define float @unary_neg_sub_nsz_extra_use(float %x, float %y) {72; CHECK-LABEL: @unary_neg_sub_nsz_extra_use(73; CHECK-NEXT: [[T1:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]74; CHECK-NEXT: [[T2:%.*]] = fneg nsz float [[T1]]75; CHECK-NEXT: call void @use(float [[T1]])76; CHECK-NEXT: ret float [[T2]]77;78 %t1 = fsub float %x, %y79 %t2 = fneg nsz float %t180 call void @use(float %t1)81 ret float %t282}83 84; With nsz: Z - (X - Y) --> Z + (Y - X)85 86define float @sub_sub_nsz(float %x, float %y, float %z) {87; CHECK-LABEL: @sub_sub_nsz(88; CHECK-NEXT: [[TMP1:%.*]] = fsub nsz float [[Y:%.*]], [[X:%.*]]89; CHECK-NEXT: [[T2:%.*]] = fadd nsz float [[Z:%.*]], [[TMP1]]90; CHECK-NEXT: ret float [[T2]]91;92 %t1 = fsub float %x, %y93 %t2 = fsub nsz float %z, %t194 ret float %t295}96 97; With nsz and reassoc: Y - ((X * 5) + Y) --> X * -598 99define float @sub_add_neg_x(float %x, float %y) {100; CHECK-LABEL: @sub_add_neg_x(101; CHECK-NEXT: [[R:%.*]] = fmul nsz float [[X:%.*]], -5.000000e+00102; CHECK-NEXT: ret float [[R]]103;104 %mul = fmul float %x, 5.000000e+00105 %add = fadd float %mul, %y106 %r = fsub nsz reassoc float %y, %add107 ret float %r108}109 110; Same as above: if 'Z' is not -0.0, swap fsub operands and convert to fadd.111 112define float @sub_sub_known_not_negzero(float %x, float %y) {113; CHECK-LABEL: @sub_sub_known_not_negzero(114; CHECK-NEXT: [[TMP1:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]115; CHECK-NEXT: [[T2:%.*]] = fadd float [[TMP1]], 4.200000e+01116; CHECK-NEXT: ret float [[T2]]117;118 %t1 = fsub float %x, %y119 %t2 = fsub float 42.0, %t1120 ret float %t2121}122 123; <rdar://problem/7530098>124 125define double @test2(double %x, double %y) {126; CHECK-LABEL: @test2(127; CHECK-NEXT: [[T1:%.*]] = fadd double [[X:%.*]], [[Y:%.*]]128; CHECK-NEXT: [[T2:%.*]] = fsub double [[X]], [[T1]]129; CHECK-NEXT: ret double [[T2]]130;131 %t1 = fadd double %x, %y132 %t2 = fsub double %x, %t1133 ret double %t2134}135 136; X - C --> X + (-C)137 138define float @constant_op1(float %x, float %y) {139; CHECK-LABEL: @constant_op1(140; CHECK-NEXT: [[R:%.*]] = fadd float [[X:%.*]], -4.200000e+01141; CHECK-NEXT: ret float [[R]]142;143 %r = fsub float %x, 42.0144 ret float %r145}146 147define <2 x float> @constant_op1_vec(<2 x float> %x, <2 x float> %y) {148; CHECK-LABEL: @constant_op1_vec(149; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[X:%.*]], <float -4.200000e+01, float 4.200000e+01>150; CHECK-NEXT: ret <2 x float> [[R]]151;152 %r = fsub <2 x float> %x, <float 42.0, float -42.0>153 ret <2 x float> %r154}155 156define <2 x float> @constant_op1_vec_poison(<2 x float> %x, <2 x float> %y) {157; CHECK-LABEL: @constant_op1_vec_poison(158; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[X:%.*]], <float poison, float 4.200000e+01>159; CHECK-NEXT: ret <2 x float> [[R]]160;161 %r = fsub <2 x float> %x, <float poison, float -42.0>162 ret <2 x float> %r163}164 165; X - (-Y) --> X + Y166 167define float @neg_op1(float %x, float %y) {168; CHECK-LABEL: @neg_op1(169; CHECK-NEXT: [[R:%.*]] = fadd float [[X:%.*]], [[Y:%.*]]170; CHECK-NEXT: ret float [[R]]171;172 %negy = fsub float -0.0, %y173 %r = fsub float %x, %negy174 ret float %r175}176 177define float @unary_neg_op1(float %x, float %y) {178; CHECK-LABEL: @unary_neg_op1(179; CHECK-NEXT: [[R:%.*]] = fadd float [[X:%.*]], [[Y:%.*]]180; CHECK-NEXT: ret float [[R]]181;182 %negy = fneg float %y183 %r = fsub float %x, %negy184 ret float %r185}186 187define <2 x float> @neg_op1_vec(<2 x float> %x, <2 x float> %y) {188; CHECK-LABEL: @neg_op1_vec(189; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[X:%.*]], [[Y:%.*]]190; CHECK-NEXT: ret <2 x float> [[R]]191;192 %negy = fsub <2 x float> <float -0.0, float -0.0>, %y193 %r = fsub <2 x float> %x, %negy194 ret <2 x float> %r195}196 197define <2 x float> @unary_neg_op1_vec(<2 x float> %x, <2 x float> %y) {198; CHECK-LABEL: @unary_neg_op1_vec(199; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[X:%.*]], [[Y:%.*]]200; CHECK-NEXT: ret <2 x float> [[R]]201;202 %negy = fneg <2 x float> %y203 %r = fsub <2 x float> %x, %negy204 ret <2 x float> %r205}206 207define <2 x float> @neg_op1_vec_poison(<2 x float> %x, <2 x float> %y) {208; CHECK-LABEL: @neg_op1_vec_poison(209; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[X:%.*]], [[Y:%.*]]210; CHECK-NEXT: ret <2 x float> [[R]]211;212 %negy = fsub <2 x float> <float -0.0, float poison>, %y213 %r = fsub <2 x float> %x, %negy214 ret <2 x float> %r215}216 217; Similar to above - but look through fpext/fptrunc casts to find the fneg.218 219define double @neg_ext_op1(float %a, double %b) {220; CHECK-LABEL: @neg_ext_op1(221; CHECK-NEXT: [[TMP1:%.*]] = fpext float [[A:%.*]] to double222; CHECK-NEXT: [[T3:%.*]] = fadd double [[B:%.*]], [[TMP1]]223; CHECK-NEXT: ret double [[T3]]224;225 %t1 = fsub float -0.0, %a226 %t2 = fpext float %t1 to double227 %t3 = fsub double %b, %t2228 ret double %t3229}230 231define double @unary_neg_ext_op1(float %a, double %b) {232; CHECK-LABEL: @unary_neg_ext_op1(233; CHECK-NEXT: [[TMP1:%.*]] = fpext float [[A:%.*]] to double234; CHECK-NEXT: [[T3:%.*]] = fadd double [[B:%.*]], [[TMP1]]235; CHECK-NEXT: ret double [[T3]]236;237 %t1 = fneg float %a238 %t2 = fpext float %t1 to double239 %t3 = fsub double %b, %t2240 ret double %t3241}242 243; Verify that vectors work too.244 245define <2 x float> @neg_trunc_op1(<2 x double> %a, <2 x float> %b) {246; CHECK-LABEL: @neg_trunc_op1(247; CHECK-NEXT: [[TMP1:%.*]] = fptrunc <2 x double> [[A:%.*]] to <2 x float>248; CHECK-NEXT: [[T3:%.*]] = fadd <2 x float> [[B:%.*]], [[TMP1]]249; CHECK-NEXT: ret <2 x float> [[T3]]250;251 %t1 = fsub <2 x double> <double -0.0, double -0.0>, %a252 %t2 = fptrunc <2 x double> %t1 to <2 x float>253 %t3 = fsub <2 x float> %b, %t2254 ret <2 x float> %t3255}256 257define <2 x float> @unary_neg_trunc_op1(<2 x double> %a, <2 x float> %b) {258; CHECK-LABEL: @unary_neg_trunc_op1(259; CHECK-NEXT: [[TMP1:%.*]] = fptrunc <2 x double> [[A:%.*]] to <2 x float>260; CHECK-NEXT: [[T3:%.*]] = fadd <2 x float> [[B:%.*]], [[TMP1]]261; CHECK-NEXT: ret <2 x float> [[T3]]262;263 %t1 = fneg <2 x double> %a264 %t2 = fptrunc <2 x double> %t1 to <2 x float>265 %t3 = fsub <2 x float> %b, %t2266 ret <2 x float> %t3267}268 269; No FMF needed, but they should propagate to the fadd.270 271define double @neg_ext_op1_fast(float %a, double %b) {272; CHECK-LABEL: @neg_ext_op1_fast(273; CHECK-NEXT: [[TMP1:%.*]] = fpext float [[A:%.*]] to double274; CHECK-NEXT: [[T3:%.*]] = fadd fast double [[B:%.*]], [[TMP1]]275; CHECK-NEXT: ret double [[T3]]276;277 %t1 = fsub float -0.0, %a278 %t2 = fpext float %t1 to double279 %t3 = fsub fast double %b, %t2280 ret double %t3281}282 283define double @unary_neg_ext_op1_fast(float %a, double %b) {284; CHECK-LABEL: @unary_neg_ext_op1_fast(285; CHECK-NEXT: [[TMP1:%.*]] = fpext float [[A:%.*]] to double286; CHECK-NEXT: [[T3:%.*]] = fadd fast double [[B:%.*]], [[TMP1]]287; CHECK-NEXT: ret double [[T3]]288;289 %t1 = fneg float %a290 %t2 = fpext float %t1 to double291 %t3 = fsub fast double %b, %t2292 ret double %t3293}294 295; Extra use should prevent the transform.296 297define float @neg_ext_op1_extra_use(half %a, float %b) {298; CHECK-LABEL: @neg_ext_op1_extra_use(299; CHECK-NEXT: [[T1:%.*]] = fneg half [[A:%.*]]300; CHECK-NEXT: [[T2:%.*]] = fpext half [[T1]] to float301; CHECK-NEXT: [[T3:%.*]] = fsub float [[B:%.*]], [[T2]]302; CHECK-NEXT: call void @use(float [[T2]])303; CHECK-NEXT: ret float [[T3]]304;305 %t1 = fsub half -0.0, %a306 %t2 = fpext half %t1 to float307 %t3 = fsub float %b, %t2308 call void @use(float %t2)309 ret float %t3310}311 312define float @unary_neg_ext_op1_extra_use(half %a, float %b) {313; CHECK-LABEL: @unary_neg_ext_op1_extra_use(314; CHECK-NEXT: [[T1:%.*]] = fneg half [[A:%.*]]315; CHECK-NEXT: [[T2:%.*]] = fpext half [[T1]] to float316; CHECK-NEXT: [[T3:%.*]] = fsub float [[B:%.*]], [[T2]]317; CHECK-NEXT: call void @use(float [[T2]])318; CHECK-NEXT: ret float [[T3]]319;320 %t1 = fneg half %a321 %t2 = fpext half %t1 to float322 %t3 = fsub float %b, %t2323 call void @use(float %t2)324 ret float %t3325}326 327; One-use fptrunc is always hoisted above fneg, so the corresponding328; multi-use bug for fptrunc isn't visible with a fold starting from329; the last fsub.330 331define float @neg_trunc_op1_extra_use(double %a, float %b) {332; CHECK-LABEL: @neg_trunc_op1_extra_use(333; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[A:%.*]] to float334; CHECK-NEXT: [[T2:%.*]] = fneg float [[TMP1]]335; CHECK-NEXT: [[T3:%.*]] = fadd float [[B:%.*]], [[TMP1]]336; CHECK-NEXT: call void @use(float [[T2]])337; CHECK-NEXT: ret float [[T3]]338;339 %t1 = fsub double -0.0, %a340 %t2 = fptrunc double %t1 to float341 %t3 = fsub float %b, %t2342 call void @use(float %t2)343 ret float %t3344}345 346define float @unary_neg_trunc_op1_extra_use(double %a, float %b) {347; CHECK-LABEL: @unary_neg_trunc_op1_extra_use(348; CHECK-NEXT: [[TMP1:%.*]] = fptrunc double [[A:%.*]] to float349; CHECK-NEXT: [[T2:%.*]] = fneg float [[TMP1]]350; CHECK-NEXT: [[T3:%.*]] = fadd float [[B:%.*]], [[TMP1]]351; CHECK-NEXT: call void @use(float [[T2]])352; CHECK-NEXT: ret float [[T3]]353;354 %t1 = fneg double %a355 %t2 = fptrunc double %t1 to float356 %t3 = fsub float %b, %t2357 call void @use(float %t2)358 ret float %t3359}360 361; Extra uses should prevent the transform.362 363define float @neg_trunc_op1_extra_uses(double %a, float %b) {364; CHECK-LABEL: @neg_trunc_op1_extra_uses(365; CHECK-NEXT: [[T1:%.*]] = fneg double [[A:%.*]]366; CHECK-NEXT: [[T2:%.*]] = fptrunc double [[T1]] to float367; CHECK-NEXT: [[T3:%.*]] = fsub float [[B:%.*]], [[T2]]368; CHECK-NEXT: call void @use2(float [[T2]], double [[T1]])369; CHECK-NEXT: ret float [[T3]]370;371 %t1 = fsub double -0.0, %a372 %t2 = fptrunc double %t1 to float373 %t3 = fsub float %b, %t2374 call void @use2(float %t2, double %t1)375 ret float %t3376}377 378define float @unary_neg_trunc_op1_extra_uses(double %a, float %b) {379; CHECK-LABEL: @unary_neg_trunc_op1_extra_uses(380; CHECK-NEXT: [[T1:%.*]] = fneg double [[A:%.*]]381; CHECK-NEXT: [[T2:%.*]] = fptrunc double [[T1]] to float382; CHECK-NEXT: [[T3:%.*]] = fsub float [[B:%.*]], [[T2]]383; CHECK-NEXT: call void @use2(float [[T2]], double [[T1]])384; CHECK-NEXT: ret float [[T3]]385;386 %t1 = fneg double %a387 %t2 = fptrunc double %t1 to float388 %t3 = fsub float %b, %t2389 call void @use2(float %t2, double %t1)390 ret float %t3391}392 393; Don't negate a constant expression to form fadd and induce infinite looping:394; https://bugs.llvm.org/show_bug.cgi?id=37605395 396@b = external global i16, align 1397 398define float @PR37605(float %conv) {399; CHECK-LABEL: @PR37605(400; CHECK-NEXT: [[SUB:%.*]] = fsub float [[CONV:%.*]], bitcast (i32 ptrtoint (ptr @b to i32) to float)401; CHECK-NEXT: ret float [[SUB]]402;403 %sub = fsub float %conv, bitcast (i32 ptrtoint (ptr @b to i32) to float)404 ret float %sub405}406 407define double @fsub_fdiv_fneg1(double %x, double %y, double %z) {408; CHECK-LABEL: @fsub_fdiv_fneg1(409; CHECK-NEXT: [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]]410; CHECK-NEXT: [[R:%.*]] = fadd double [[Z:%.*]], [[TMP1]]411; CHECK-NEXT: ret double [[R]]412;413 %neg = fsub double -0.000000e+00, %x414 %div = fdiv double %neg, %y415 %r = fsub double %z, %div416 ret double %r417}418 419define <2 x double> @fsub_fdiv_fneg2(<2 x double> %x, <2 x double> %y, <2 x double> %z) {420; CHECK-LABEL: @fsub_fdiv_fneg2(421; CHECK-NEXT: [[TMP1:%.*]] = fdiv <2 x double> [[Y:%.*]], [[X:%.*]]422; CHECK-NEXT: [[R:%.*]] = fadd <2 x double> [[Z:%.*]], [[TMP1]]423; CHECK-NEXT: ret <2 x double> [[R]]424;425 %neg = fsub <2 x double> <double -0.0, double -0.0>, %x426 %div = fdiv <2 x double> %y, %neg427 %r = fsub <2 x double> %z, %div428 ret <2 x double> %r429}430 431define double @fsub_fmul_fneg1(double %x, double %y, double %z) {432; CHECK-LABEL: @fsub_fmul_fneg1(433; CHECK-NEXT: [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y:%.*]]434; CHECK-NEXT: [[R:%.*]] = fadd double [[Z:%.*]], [[TMP1]]435; CHECK-NEXT: ret double [[R]]436;437 %neg = fsub double -0.000000e+00, %x438 %mul = fmul double %neg, %y439 %r = fsub double %z, %mul440 ret double %r441}442 443define double @fsub_fmul_fneg2(double %x, double %y, double %z) {444; CHECK-LABEL: @fsub_fmul_fneg2(445; CHECK-NEXT: [[TMP1:%.*]] = fmul double [[X:%.*]], [[Y:%.*]]446; CHECK-NEXT: [[R:%.*]] = fadd double [[Z:%.*]], [[TMP1]]447; CHECK-NEXT: ret double [[R]]448;449 %neg = fsub double -0.000000e+00, %x450 %mul = fmul double %y, %neg451 %r = fsub double %z, %mul452 ret double %r453}454 455define float @fsub_fdiv_fneg1_extra_use(float %x, float %y, float %z) {456; CHECK-LABEL: @fsub_fdiv_fneg1_extra_use(457; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]458; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]459; CHECK-NEXT: call void @use(float [[DIV]])460; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[DIV]]461; CHECK-NEXT: ret float [[R]]462;463 %neg = fsub float -0.000000e+00, %x464 %div = fdiv float %neg, %y465 call void @use(float %div)466 %r = fsub float %z, %div467 ret float %r468}469 470define float @fsub_fdiv_fneg2_extra_use(float %x, float %y, float %z) {471; CHECK-LABEL: @fsub_fdiv_fneg2_extra_use(472; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]473; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[Y:%.*]], [[NEG]]474; CHECK-NEXT: call void @use(float [[DIV]])475; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[DIV]]476; CHECK-NEXT: ret float [[R]]477;478 %neg = fsub float -0.000000e+00, %x479 %div = fdiv float %y, %neg480 call void @use(float %div)481 %r = fsub float %z, %div482 ret float %r483}484 485declare void @use_vec(<2 x float>)486 487define <2 x float> @fsub_fmul_fneg1_extra_use(<2 x float> %x, <2 x float> %y, <2 x float> %z) {488; CHECK-LABEL: @fsub_fmul_fneg1_extra_use(489; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]490; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[Y:%.*]], [[NEG]]491; CHECK-NEXT: call void @use_vec(<2 x float> [[MUL]])492; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> [[Z:%.*]], [[MUL]]493; CHECK-NEXT: ret <2 x float> [[R]]494;495 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x496 %mul = fmul <2 x float> %neg, %y497 call void @use_vec(<2 x float> %mul)498 %r = fsub <2 x float> %z, %mul499 ret <2 x float> %r500}501 502define float @fsub_fmul_fneg2_extra_use(float %x, float %y, float %z) {503; CHECK-LABEL: @fsub_fmul_fneg2_extra_use(504; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]505; CHECK-NEXT: [[MUL:%.*]] = fmul float [[Y:%.*]], [[NEG]]506; CHECK-NEXT: call void @use(float [[MUL]])507; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[MUL]]508; CHECK-NEXT: ret float [[R]]509;510 %neg = fsub float -0.000000e+00, %x511 %mul = fmul float %y, %neg512 call void @use(float %mul)513 %r = fsub float %z, %mul514 ret float %r515}516 517define float @fsub_fdiv_fneg1_extra_use2(float %x, float %y, float %z) {518; CHECK-LABEL: @fsub_fdiv_fneg1_extra_use2(519; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]520; CHECK-NEXT: call void @use(float [[NEG]])521; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[X]], [[Y:%.*]]522; CHECK-NEXT: [[R:%.*]] = fadd float [[Z:%.*]], [[TMP1]]523; CHECK-NEXT: ret float [[R]]524;525 %neg = fsub float -0.000000e+00, %x526 call void @use(float %neg)527 %div = fdiv float %neg, %y528 %r = fsub float %z, %div529 ret float %r530}531 532define float @fsub_fdiv_fneg2_extra_use2(float %x, float %y, float %z) {533; CHECK-LABEL: @fsub_fdiv_fneg2_extra_use2(534; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]535; CHECK-NEXT: call void @use(float [[NEG]])536; CHECK-NEXT: [[TMP1:%.*]] = fdiv float [[Y:%.*]], [[X]]537; CHECK-NEXT: [[R:%.*]] = fadd float [[Z:%.*]], [[TMP1]]538; CHECK-NEXT: ret float [[R]]539;540 %neg = fsub float -0.000000e+00, %x541 call void @use(float %neg)542 %div = fdiv float %y, %neg543 %r = fsub float %z, %div544 ret float %r545}546 547define <2 x float> @fsub_fmul_fneg1_extra_use2(<2 x float> %x, <2 x float> %y, <2 x float> %z) {548; CHECK-LABEL: @fsub_fmul_fneg1_extra_use2(549; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]550; CHECK-NEXT: call void @use_vec(<2 x float> [[NEG]])551; CHECK-NEXT: [[TMP1:%.*]] = fmul <2 x float> [[X]], [[Y:%.*]]552; CHECK-NEXT: [[R:%.*]] = fadd <2 x float> [[Z:%.*]], [[TMP1]]553; CHECK-NEXT: ret <2 x float> [[R]]554;555 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x556 call void @use_vec(<2 x float> %neg)557 %mul = fmul <2 x float> %neg, %y558 %r = fsub <2 x float> %z, %mul559 ret <2 x float> %r560}561 562define float @fsub_fmul_fneg2_extra_use2(float %x, float %y, float %z) {563; CHECK-LABEL: @fsub_fmul_fneg2_extra_use2(564; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]565; CHECK-NEXT: call void @use(float [[NEG]])566; CHECK-NEXT: [[TMP1:%.*]] = fmul float [[X]], [[Y:%.*]]567; CHECK-NEXT: [[R:%.*]] = fadd float [[Z:%.*]], [[TMP1]]568; CHECK-NEXT: ret float [[R]]569;570 %neg = fsub float -0.000000e+00, %x571 call void @use(float %neg)572 %mul = fmul float %y, %neg573 %r = fsub float %z, %mul574 ret float %r575}576 577define float @fsub_fdiv_fneg1_extra_use3(float %x, float %y, float %z) {578; CHECK-LABEL: @fsub_fdiv_fneg1_extra_use3(579; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]580; CHECK-NEXT: call void @use(float [[NEG]])581; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[NEG]], [[Y:%.*]]582; CHECK-NEXT: call void @use(float [[DIV]])583; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[DIV]]584; CHECK-NEXT: ret float [[R]]585;586 %neg = fsub float -0.000000e+00, %x587 call void @use(float %neg)588 %div = fdiv float %neg, %y589 call void @use(float %div)590 %r = fsub float %z, %div591 ret float %r592}593 594define float @fsub_fdiv_fneg2_extra_use3(float %x, float %y, float %z) {595; CHECK-LABEL: @fsub_fdiv_fneg2_extra_use3(596; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]597; CHECK-NEXT: call void @use(float [[NEG]])598; CHECK-NEXT: [[DIV:%.*]] = fdiv float [[Y:%.*]], [[NEG]]599; CHECK-NEXT: call void @use(float [[DIV]])600; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[DIV]]601; CHECK-NEXT: ret float [[R]]602;603 %neg = fsub float -0.000000e+00, %x604 call void @use(float %neg)605 %div = fdiv float %y, %neg606 call void @use(float %div)607 %r = fsub float %z, %div608 ret float %r609}610 611define <2 x float> @fsub_fmul_fneg1_extra_use3(<2 x float> %x, <2 x float> %y, <2 x float> %z) {612; CHECK-LABEL: @fsub_fmul_fneg1_extra_use3(613; CHECK-NEXT: [[NEG:%.*]] = fneg <2 x float> [[X:%.*]]614; CHECK-NEXT: call void @use_vec(<2 x float> [[NEG]])615; CHECK-NEXT: [[MUL:%.*]] = fmul <2 x float> [[Y:%.*]], [[NEG]]616; CHECK-NEXT: call void @use_vec(<2 x float> [[MUL]])617; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> [[Z:%.*]], [[MUL]]618; CHECK-NEXT: ret <2 x float> [[R]]619;620 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x621 call void @use_vec(<2 x float> %neg)622 %mul = fmul <2 x float> %neg, %y623 call void @use_vec(<2 x float> %mul)624 %r = fsub <2 x float> %z, %mul625 ret <2 x float> %r626}627 628define float @fsub_fmul_fneg2_extra_use3(float %x, float %y, float %z) {629; CHECK-LABEL: @fsub_fmul_fneg2_extra_use3(630; CHECK-NEXT: [[NEG:%.*]] = fneg float [[X:%.*]]631; CHECK-NEXT: call void @use(float [[NEG]])632; CHECK-NEXT: [[MUL:%.*]] = fmul float [[Y:%.*]], [[NEG]]633; CHECK-NEXT: call void @use(float [[MUL]])634; CHECK-NEXT: [[R:%.*]] = fsub float [[Z:%.*]], [[MUL]]635; CHECK-NEXT: ret float [[R]]636;637 %neg = fsub float -0.000000e+00, %x638 call void @use(float %neg)639 %mul = fmul float %y, %neg640 call void @use(float %mul)641 %r = fsub float %z, %mul642 ret float %r643}644 645; Negative test - can't reassociate without FMF.646 647define float @fsub_fsub(float %x, float %y, float %z) {648; CHECK-LABEL: @fsub_fsub(649; CHECK-NEXT: [[XY:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]650; CHECK-NEXT: [[XYZ:%.*]] = fsub float [[XY]], [[Z:%.*]]651; CHECK-NEXT: ret float [[XYZ]]652;653 %xy = fsub float %x, %y654 %xyz = fsub float %xy, %z655 ret float %xyz656}657 658; Negative test - can't reassociate without enough FMF.659 660define float @fsub_fsub_nsz(float %x, float %y, float %z) {661; CHECK-LABEL: @fsub_fsub_nsz(662; CHECK-NEXT: [[XY:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]663; CHECK-NEXT: [[XYZ:%.*]] = fsub nsz float [[XY]], [[Z:%.*]]664; CHECK-NEXT: ret float [[XYZ]]665;666 %xy = fsub float %x, %y667 %xyz = fsub nsz float %xy, %z668 ret float %xyz669}670 671; Negative test - can't reassociate without enough FMF.672 673define float @fsub_fsub_reassoc(float %x, float %y, float %z) {674; CHECK-LABEL: @fsub_fsub_reassoc(675; CHECK-NEXT: [[XY:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]676; CHECK-NEXT: [[XYZ:%.*]] = fsub reassoc float [[XY]], [[Z:%.*]]677; CHECK-NEXT: ret float [[XYZ]]678;679 %xy = fsub float %x, %y680 %xyz = fsub reassoc float %xy, %z681 ret float %xyz682}683 684define float @fsub_fsub_nsz_reassoc(float %x, float %y, float %z) {685; CHECK-LABEL: @fsub_fsub_nsz_reassoc(686; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[Y:%.*]], [[Z:%.*]]687; CHECK-NEXT: [[XYZ:%.*]] = fsub reassoc nsz float [[X:%.*]], [[TMP1]]688; CHECK-NEXT: ret float [[XYZ]]689;690 %xy = fsub float %x, %y691 %xyz = fsub nsz reassoc float %xy, %z692 ret float %xyz693}694 695define <2 x double> @fsub_fsub_fast_vec(<2 x double> %x, <2 x double> %y, <2 x double> %z) {696; CHECK-LABEL: @fsub_fsub_fast_vec(697; CHECK-NEXT: [[TMP1:%.*]] = fadd fast <2 x double> [[Y:%.*]], [[Z:%.*]]698; CHECK-NEXT: [[XYZ:%.*]] = fsub fast <2 x double> [[X:%.*]], [[TMP1]]699; CHECK-NEXT: ret <2 x double> [[XYZ]]700;701 %xy = fsub fast <2 x double> %x, %y702 %xyz = fsub fast reassoc <2 x double> %xy, %z703 ret <2 x double> %xyz704}705 706; Negative test - don't reassociate and increase instructions.707 708define float @fsub_fsub_nsz_reassoc_extra_use(float %x, float %y, float %z) {709; CHECK-LABEL: @fsub_fsub_nsz_reassoc_extra_use(710; CHECK-NEXT: [[XY:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]711; CHECK-NEXT: call void @use(float [[XY]])712; CHECK-NEXT: [[XYZ:%.*]] = fsub reassoc nsz float [[XY]], [[Z:%.*]]713; CHECK-NEXT: ret float [[XYZ]]714;715 %xy = fsub float %x, %y716 call void @use(float %xy)717 %xyz = fsub nsz reassoc float %xy, %z718 ret float %xyz719}720 721define float @fneg_fsub(float %x, float %y) {722; CHECK-LABEL: @fneg_fsub(723; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]724; CHECK-NEXT: [[SUB:%.*]] = fsub float [[NEGX]], [[Y:%.*]]725; CHECK-NEXT: ret float [[SUB]]726;727 %negx = fneg float %x728 %sub = fsub float %negx, %y729 ret float %sub730}731 732define float @fneg_fsub_nsz(float %x, float %y) {733; CHECK-LABEL: @fneg_fsub_nsz(734; CHECK-NEXT: [[TMP1:%.*]] = fadd nsz float [[X:%.*]], [[Y:%.*]]735; CHECK-NEXT: [[SUB:%.*]] = fneg nsz float [[TMP1]]736; CHECK-NEXT: ret float [[SUB]]737;738 %negx = fneg float %x739 %sub = fsub nsz float %negx, %y740 ret float %sub741}742 743define float @fake_fneg_fsub_fast(float %x, float %y) {744; CHECK-LABEL: @fake_fneg_fsub_fast(745; CHECK-NEXT: [[TMP1:%.*]] = fadd fast float [[X:%.*]], [[Y:%.*]]746; CHECK-NEXT: [[SUB:%.*]] = fneg fast float [[TMP1]]747; CHECK-NEXT: ret float [[SUB]]748;749 %negx = fsub float -0.0, %x750 %sub = fsub fast float %negx, %y751 ret float %sub752}753 754define float @fake_fneg_fsub_fast_extra_use(float %x, float %y) {755; CHECK-LABEL: @fake_fneg_fsub_fast_extra_use(756; CHECK-NEXT: [[NEGX:%.*]] = fneg float [[X:%.*]]757; CHECK-NEXT: call void @use(float [[NEGX]])758; CHECK-NEXT: [[SUB:%.*]] = fsub fast float [[NEGX]], [[Y:%.*]]759; CHECK-NEXT: ret float [[SUB]]760;761 %negx = fsub float -0.0, %x762 call void @use(float %negx)763 %sub = fsub fast float %negx, %y764 ret float %sub765}766 767define <2 x float> @fake_fneg_fsub_vec(<2 x float> %x, <2 x float> %y) {768; CHECK-LABEL: @fake_fneg_fsub_vec(769; CHECK-NEXT: [[TMP1:%.*]] = fadd nsz <2 x float> [[X:%.*]], [[Y:%.*]]770; CHECK-NEXT: [[SUB:%.*]] = fneg nsz <2 x float> [[TMP1]]771; CHECK-NEXT: ret <2 x float> [[SUB]]772;773 %negx = fsub <2 x float> <float -0.0, float -0.0>, %x774 %sub = fsub nsz <2 x float> %negx, %y775 ret <2 x float> %sub776}777 778define float @fneg_fsub_constant(float %x) {779; CHECK-LABEL: @fneg_fsub_constant(780; CHECK-NEXT: [[SUB:%.*]] = fsub nsz float -4.200000e+01, [[X:%.*]]781; CHECK-NEXT: ret float [[SUB]]782;783 %negx = fneg float %x784 %sub = fsub nsz float %negx, 42.0785 ret float %sub786}787 788; ((w-x) + y) - z --> (w+y) - (x+z)789 790define float @fsub_fadd_fsub_reassoc(float %w, float %x, float %y, float %z) {791; CHECK-LABEL: @fsub_fadd_fsub_reassoc(792; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[W:%.*]], [[Y:%.*]]793; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc nsz float [[X:%.*]], [[Z:%.*]]794; CHECK-NEXT: [[S2:%.*]] = fsub reassoc nsz float [[TMP1]], [[TMP2]]795; CHECK-NEXT: ret float [[S2]]796;797 %s1 = fsub reassoc nsz float %w, %x798 %a = fadd reassoc nsz float %s1, %y799 %s2 = fsub reassoc nsz float %a, %z800 ret float %s2801}802 803; FMF on the last op is enough to do the transform; vectors work too.804 805define <2 x float> @fsub_fadd_fsub_reassoc_commute(<2 x float> %w, <2 x float> %x, <2 x float> %y, <2 x float> %z) {806; CHECK-LABEL: @fsub_fadd_fsub_reassoc_commute(807; CHECK-NEXT: [[D:%.*]] = fdiv <2 x float> [[Y:%.*]], <float 4.200000e+01, float -4.200000e+01>808; CHECK-NEXT: [[TMP1:%.*]] = fadd fast <2 x float> [[W:%.*]], [[D]]809; CHECK-NEXT: [[TMP2:%.*]] = fadd fast <2 x float> [[X:%.*]], [[Z:%.*]]810; CHECK-NEXT: [[S2:%.*]] = fsub fast <2 x float> [[TMP1]], [[TMP2]]811; CHECK-NEXT: ret <2 x float> [[S2]]812;813 %d = fdiv <2 x float> %y, <float 42.0, float -42.0> ; thwart complexity-based canonicalization814 %s1 = fsub <2 x float> %w, %x815 %a = fadd <2 x float> %d, %s1816 %s2 = fsub fast <2 x float> %a, %z817 ret <2 x float> %s2818}819 820; (v-w) + (x-y) - z --> (v+x) - (w+y+z)821 822define float @fsub_fadd_fsub_reassoc_twice(float %v, float %w, float %x, float %y, float %z) {823; CHECK-LABEL: @fsub_fadd_fsub_reassoc_twice(824; CHECK-NEXT: [[TMP1:%.*]] = fadd reassoc nsz float [[W:%.*]], [[Z:%.*]]825; CHECK-NEXT: [[TMP2:%.*]] = fadd reassoc nsz float [[X:%.*]], [[V:%.*]]826; CHECK-NEXT: [[TMP3:%.*]] = fadd reassoc nsz float [[Y:%.*]], [[TMP1]]827; CHECK-NEXT: [[S3:%.*]] = fsub reassoc nsz float [[TMP2]], [[TMP3]]828; CHECK-NEXT: ret float [[S3]]829;830 %s1 = fsub reassoc nsz float %v, %w831 %s2 = fsub reassoc nsz float %x, %y832 %a = fadd reassoc nsz float %s1, %s2833 %s3 = fsub reassoc nsz float %a, %z834 ret float %s3835}836 837; negative test - FMF838 839define float @fsub_fadd_fsub_not_reassoc(float %w, float %x, float %y, float %z) {840; CHECK-LABEL: @fsub_fadd_fsub_not_reassoc(841; CHECK-NEXT: [[S1:%.*]] = fsub fast float [[W:%.*]], [[X:%.*]]842; CHECK-NEXT: [[A:%.*]] = fadd fast float [[S1]], [[Y:%.*]]843; CHECK-NEXT: [[S2:%.*]] = fsub nsz float [[A]], [[Z:%.*]]844; CHECK-NEXT: ret float [[S2]]845;846 %s1 = fsub fast float %w, %x847 %a = fadd fast float %s1, %y848 %s2 = fsub nsz float %a, %z849 ret float %s2850}851 852; negative test - uses853 854define float @fsub_fadd_fsub_reassoc_use1(float %w, float %x, float %y, float %z) {855; CHECK-LABEL: @fsub_fadd_fsub_reassoc_use1(856; CHECK-NEXT: [[S1:%.*]] = fsub fast float [[W:%.*]], [[X:%.*]]857; CHECK-NEXT: call void @use(float [[S1]])858; CHECK-NEXT: [[A:%.*]] = fadd fast float [[S1]], [[Y:%.*]]859; CHECK-NEXT: [[S2:%.*]] = fsub fast float [[A]], [[Z:%.*]]860; CHECK-NEXT: ret float [[S2]]861;862 %s1 = fsub fast float %w, %x863 call void @use(float %s1)864 %a = fadd fast float %s1, %y865 %s2 = fsub fast float %a, %z866 ret float %s2867}868 869; negative test - uses870 871define float @fsub_fadd_fsub_reassoc_use2(float %w, float %x, float %y, float %z) {872; CHECK-LABEL: @fsub_fadd_fsub_reassoc_use2(873; CHECK-NEXT: [[S1:%.*]] = fsub fast float [[W:%.*]], [[X:%.*]]874; CHECK-NEXT: [[A:%.*]] = fadd fast float [[S1]], [[Y:%.*]]875; CHECK-NEXT: call void @use(float [[A]])876; CHECK-NEXT: [[S2:%.*]] = fsub fast float [[A]], [[Z:%.*]]877; CHECK-NEXT: ret float [[S2]]878;879 %s1 = fsub fast float %w, %x880 %a = fadd fast float %s1, %y881 call void @use(float %a)882 %s2 = fsub fast float %a, %z883 ret float %s2884}885 886define float @fmul_c1(float %x, float %y) {887; CHECK-LABEL: @fmul_c1(888; CHECK-NEXT: [[M:%.*]] = fmul float [[X:%.*]], 4.200000e+01889; CHECK-NEXT: [[R:%.*]] = fsub float [[Y:%.*]], [[M]]890; CHECK-NEXT: ret float [[R]]891;892 %m = fmul float %x, 42.0893 %r = fsub float %y, %m894 ret float %r895}896 897define <2 x float> @fmul_c1_fmf(<2 x float> %x, <2 x float> %y) {898; CHECK-LABEL: @fmul_c1_fmf(899; CHECK-NEXT: [[M:%.*]] = fmul ninf nsz <2 x float> [[X:%.*]], <float 4.200000e+01, float 5.000000e-01>900; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> [[Y:%.*]], [[M]]901; CHECK-NEXT: ret <2 x float> [[R]]902;903 %m = fmul ninf nsz <2 x float> %x, <float 42.0, float 0.5>904 %r = fsub <2 x float> %y, %m905 ret <2 x float> %r906}907 908define float @fmul_c1_use(float %x, float %y) {909; CHECK-LABEL: @fmul_c1_use(910; CHECK-NEXT: [[M:%.*]] = fmul float [[X:%.*]], 4.200000e+01911; CHECK-NEXT: call void @use(float [[M]])912; CHECK-NEXT: [[R:%.*]] = fsub float [[Y:%.*]], [[M]]913; CHECK-NEXT: ret float [[R]]914;915 %m = fmul float %x, 42.0916 call void @use(float %m)917 %r = fsub float %y, %m918 ret float %r919}920 921define half @fdiv_c0(half %x, half %y) {922; CHECK-LABEL: @fdiv_c0(923; CHECK-NEXT: [[M:%.*]] = fdiv half 0xH4700, [[X:%.*]]924; CHECK-NEXT: [[R:%.*]] = fsub half [[Y:%.*]], [[M]]925; CHECK-NEXT: ret half [[R]]926;927 %m = fdiv half 7.0, %x928 %r = fsub half %y, %m929 ret half %r930}931 932define double @fdiv_c0_fmf(double %x, double %y) {933; CHECK-LABEL: @fdiv_c0_fmf(934; CHECK-NEXT: [[M:%.*]] = fdiv double 7.000000e+00, [[X:%.*]]935; CHECK-NEXT: [[R:%.*]] = fsub reassoc nnan double [[Y:%.*]], [[M]]936; CHECK-NEXT: ret double [[R]]937;938 %m = fdiv double 7.0, %x939 %r = fsub reassoc nnan double %y, %m940 ret double %r941}942 943define <2 x float> @fdiv_c1(<2 x float> %x, <2 x float> %y) {944; CHECK-LABEL: @fdiv_c1(945; CHECK-NEXT: [[M:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.270000e+02, float -0.000000e+00>946; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> [[Y:%.*]], [[M]]947; CHECK-NEXT: ret <2 x float> [[R]]948;949 %m = fdiv <2 x float> %x, <float 427.0, float -0.0>950 %r = fsub <2 x float> %y, %m951 ret <2 x float> %r952}953 954define float @fdiv_c1_fmf(float %x, float %y) {955; CHECK-LABEL: @fdiv_c1_fmf(956; CHECK-NEXT: [[M:%.*]] = fdiv nnan float [[X:%.*]], 4.270000e+02957; CHECK-NEXT: [[R:%.*]] = fsub reassoc float [[Y:%.*]], [[M]]958; CHECK-NEXT: ret float [[R]]959;960 %m = fdiv nnan float %x, 427.0961 %r = fsub reassoc float %y, %m962 ret float %r963}964 965define <2 x float> @fdiv_c1_use(<2 x float> %x, <2 x float> %y) {966; CHECK-LABEL: @fdiv_c1_use(967; CHECK-NEXT: [[M:%.*]] = fdiv <2 x float> [[X:%.*]], <float 4.270000e+02, float -0.000000e+00>968; CHECK-NEXT: call void @use_vec(<2 x float> [[M]])969; CHECK-NEXT: [[R:%.*]] = fsub <2 x float> [[Y:%.*]], [[M]]970; CHECK-NEXT: ret <2 x float> [[R]]971;972 %m = fdiv <2 x float> %x, <float 427.0, float -0.0>973 call void @use_vec(<2 x float> %m)974 %r = fsub <2 x float> %y, %m975 ret <2 x float> %r976}977