1308 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=instcombine -S | FileCheck %s3; RUN: opt < %s -passes=instcombine -use-constant-fp-for-fixed-length-splat -S | FileCheck %s4 5declare float @llvm.ldexp.f32.i32(float, i32)6declare <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float>, <2 x i32>)7declare void @use(float)8 9define float @fneg_fneg(float %a) {10;11; CHECK-LABEL: @fneg_fneg(12; CHECK-NEXT: ret float [[A:%.*]]13;14 %f = fneg float %a15 %r = fneg float %f16 ret float %r17}18 19; -(X * C) --> X * (-C)20 21define float @fmul_fsub(float %x) {22; CHECK-LABEL: @fmul_fsub(23; CHECK-NEXT: [[R:%.*]] = fmul float [[X:%.*]], -4.200000e+0124; CHECK-NEXT: ret float [[R]]25;26 %m = fmul float %x, 42.027 %r = fsub float -0.0, %m28 ret float %r29}30 31define float @fmul_fneg(float %x) {32; CHECK-LABEL: @fmul_fneg(33; CHECK-NEXT: [[R:%.*]] = fmul float [[X:%.*]], -4.200000e+0134; CHECK-NEXT: ret float [[R]]35;36 %m = fmul float %x, 42.037 %r = fneg float %m38 ret float %r39}40 41; Fast math is not required, but it should be propagated.42 43define float @fmul_fsub_fmf(float %x) {44; CHECK-LABEL: @fmul_fsub_fmf(45; CHECK-NEXT: [[R:%.*]] = fmul nsz float [[X:%.*]], -4.200000e+0146; CHECK-NEXT: ret float [[R]]47;48 %m = fmul float %x, 42.049 %r = fsub reassoc nsz float -0.0, %m50 ret float %r51}52 53define float @fmul_fneg_fmf(float %x) {54; CHECK-LABEL: @fmul_fneg_fmf(55; CHECK-NEXT: [[R:%.*]] = fmul nsz float [[X:%.*]], -4.200000e+0156; CHECK-NEXT: ret float [[R]]57;58 %m = fmul float %x, 42.059 %r = fneg reassoc nsz float %m60 ret float %r61}62 63; Extra use prevents the fold. We don't want to replace the fneg with an fmul.64 65define float @fmul_fsub_extra_use(float %x) {66; CHECK-LABEL: @fmul_fsub_extra_use(67; CHECK-NEXT: [[M:%.*]] = fmul float [[X:%.*]], 4.200000e+0168; CHECK-NEXT: [[R:%.*]] = fneg float [[M]]69; CHECK-NEXT: call void @use(float [[M]])70; CHECK-NEXT: ret float [[R]]71;72 %m = fmul float %x, 42.073 %r = fsub float -0.0, %m74 call void @use(float %m)75 ret float %r76}77 78define float @fmul_fneg_extra_use(float %x) {79; CHECK-LABEL: @fmul_fneg_extra_use(80; CHECK-NEXT: [[M:%.*]] = fmul float [[X:%.*]], 4.200000e+0181; CHECK-NEXT: [[R:%.*]] = fneg float [[M]]82; CHECK-NEXT: call void @use(float [[M]])83; CHECK-NEXT: ret float [[R]]84;85 %m = fmul float %x, 42.086 %r = fneg float %m87 call void @use(float %m)88 ret float %r89}90 91; Try a vector. Use special constants (NaN, INF, poison) because they don't change anything.92 93define <4 x double> @fmul_fsub_vec(<4 x double> %x) {94; CHECK-LABEL: @fmul_fsub_vec(95; CHECK-NEXT: [[R:%.*]] = fmul <4 x double> [[X:%.*]], <double -4.200000e+01, double 0xFFF8000000000000, double 0xFFF0000000000000, double poison>96; CHECK-NEXT: ret <4 x double> [[R]]97;98 %m = fmul <4 x double> %x, <double 42.0, double 0x7FF8000000000000, double 0x7FF0000000000000, double poison>99 %r = fsub <4 x double> <double -0.0, double -0.0, double -0.0, double -0.0>, %m100 ret <4 x double> %r101}102 103define <4 x double> @fmul_fneg_vec(<4 x double> %x) {104; CHECK-LABEL: @fmul_fneg_vec(105; CHECK-NEXT: [[R:%.*]] = fmul <4 x double> [[X:%.*]], <double -4.200000e+01, double 0xFFF8000000000000, double 0xFFF0000000000000, double poison>106; CHECK-NEXT: ret <4 x double> [[R]]107;108 %m = fmul <4 x double> %x, <double 42.0, double 0x7FF8000000000000, double 0x7FF0000000000000, double poison>109 %r = fneg <4 x double> %m110 ret <4 x double> %r111}112 113; -(X / C) --> X / (-C)114 115define float @fdiv_op1_constant_fsub(float %x) {116; CHECK-LABEL: @fdiv_op1_constant_fsub(117; CHECK-NEXT: [[R:%.*]] = fdiv float [[X:%.*]], 4.200000e+01118; CHECK-NEXT: ret float [[R]]119;120 %d = fdiv float %x, -42.0121 %r = fsub float -0.0, %d122 ret float %r123}124 125define float @fdiv_op1_constant_fneg(float %x) {126; CHECK-LABEL: @fdiv_op1_constant_fneg(127; CHECK-NEXT: [[R:%.*]] = fdiv float [[X:%.*]], 4.200000e+01128; CHECK-NEXT: ret float [[R]]129;130 %d = fdiv float %x, -42.0131 %r = fneg float %d132 ret float %r133}134 135; Fast math is not required, but it should be propagated.136 137define float @fdiv_op1_constant_fsub_fmf(float %x) {138; CHECK-LABEL: @fdiv_op1_constant_fsub_fmf(139; CHECK-NEXT: [[R:%.*]] = fdiv nnan float [[X:%.*]], 4.200000e+01140; CHECK-NEXT: ret float [[R]]141;142 %d = fdiv float %x, -42.0143 %r = fsub nnan float -0.0, %d144 ret float %r145}146 147define float @fdiv_op1_constant_fneg_fmf(float %x) {148; CHECK-LABEL: @fdiv_op1_constant_fneg_fmf(149; CHECK-NEXT: [[R:%.*]] = fdiv nnan float [[X:%.*]], 4.200000e+01150; CHECK-NEXT: ret float [[R]]151;152 %d = fdiv float %x, -42.0153 %r = fneg nnan float %d154 ret float %r155}156 157; Extra use prevents the fold. We don't want to replace the fneg with an fdiv.158 159define float @fdiv_op1_constant_fsub_extra_use(float %x) {160; CHECK-LABEL: @fdiv_op1_constant_fsub_extra_use(161; CHECK-NEXT: [[D:%.*]] = fdiv float [[X:%.*]], 4.200000e+01162; CHECK-NEXT: [[R:%.*]] = fneg float [[D]]163; CHECK-NEXT: call void @use(float [[D]])164; CHECK-NEXT: ret float [[R]]165;166 %d = fdiv float %x, 42.0167 %r = fsub float -0.0, %d168 call void @use(float %d)169 ret float %r170}171 172define float @fdiv_op1_constant_fneg_extra_use(float %x) {173; CHECK-LABEL: @fdiv_op1_constant_fneg_extra_use(174; CHECK-NEXT: [[D:%.*]] = fdiv float [[X:%.*]], 4.200000e+01175; CHECK-NEXT: [[R:%.*]] = fneg float [[D]]176; CHECK-NEXT: call void @use(float [[D]])177; CHECK-NEXT: ret float [[R]]178;179 %d = fdiv float %x, 42.0180 %r = fneg float %d181 call void @use(float %d)182 ret float %r183}184 185; Try a vector. Use special constants (NaN, INF, poison) because they don't change anything.186 187define <4 x double> @fdiv_op1_constant_fsub_vec(<4 x double> %x) {188; CHECK-LABEL: @fdiv_op1_constant_fsub_vec(189; CHECK-NEXT: [[R:%.*]] = fdiv <4 x double> [[X:%.*]], <double 4.200000e+01, double 0x7FF800000ABCD000, double 0x7FF0000000000000, double poison>190; CHECK-NEXT: ret <4 x double> [[R]]191;192 %d = fdiv <4 x double> %x, <double -42.0, double 0xFFF800000ABCD000, double 0xFFF0000000000000, double poison>193 %r = fsub <4 x double> <double -0.0, double -0.0, double -0.0, double -0.0>, %d194 ret <4 x double> %r195}196 197define <4 x double> @fdiv_op1_constant_fneg_vec(<4 x double> %x) {198; CHECK-LABEL: @fdiv_op1_constant_fneg_vec(199; CHECK-NEXT: [[R:%.*]] = fdiv <4 x double> [[X:%.*]], <double 4.200000e+01, double 0x7FF800000ABCD000, double 0x7FF0000000000000, double poison>200; CHECK-NEXT: ret <4 x double> [[R]]201;202 %d = fdiv <4 x double> %x, <double -42.0, double 0xFFF800000ABCD000, double 0xFFF0000000000000, double poison>203 %r = fneg <4 x double> %d204 ret <4 x double> %r205}206 207; -(C / X) --> (-C) / X208 209define float @fdiv_op0_constant_fsub(float %x) {210; CHECK-LABEL: @fdiv_op0_constant_fsub(211; CHECK-NEXT: [[R:%.*]] = fdiv float -4.200000e+01, [[X:%.*]]212; CHECK-NEXT: ret float [[R]]213;214 %d = fdiv float 42.0, %x215 %r = fsub float -0.0, %d216 ret float %r217}218 219define float @fdiv_op0_constant_fneg(float %x) {220; CHECK-LABEL: @fdiv_op0_constant_fneg(221; CHECK-NEXT: [[R:%.*]] = fdiv float -4.200000e+01, [[X:%.*]]222; CHECK-NEXT: ret float [[R]]223;224 %d = fdiv float 42.0, %x225 %r = fneg float %d226 ret float %r227}228 229; Fast math is not required, but it should be propagated.230 231define float @fdiv_op0_constant_fneg_fast_fast(float %x) {232; CHECK-LABEL: @fdiv_op0_constant_fneg_fast_fast(233; CHECK-NEXT: [[R:%.*]] = fdiv fast float -4.200000e+01, [[X:%.*]]234; CHECK-NEXT: ret float [[R]]235;236 %d = fdiv fast float 42.0, %x237 %r = fneg fast float %d238 ret float %r239}240 241define float @fdiv_op0_constant_fneg_fast(float %x) {242; CHECK-LABEL: @fdiv_op0_constant_fneg_fast(243; CHECK-NEXT: [[R:%.*]] = fdiv reassoc nnan arcp contract afn float -4.200000e+01, [[X:%.*]]244; CHECK-NEXT: ret float [[R]]245;246 %d = fdiv float 42.0, %x247 %r = fneg fast float %d248 ret float %r249}250 251define float @fdiv_op0_constant_fneg_nsz_nsz(float %x) {252; CHECK-LABEL: @fdiv_op0_constant_fneg_nsz_nsz(253; CHECK-NEXT: [[R:%.*]] = fdiv nsz float -4.200000e+01, [[X:%.*]]254; CHECK-NEXT: ret float [[R]]255;256 %d = fdiv nsz float 42.0, %x257 %r = fneg nsz float %d258 ret float %r259}260 261define float @fdiv_op0_constant_fneg_nsz(float %x) {262; CHECK-LABEL: @fdiv_op0_constant_fneg_nsz(263; CHECK-NEXT: [[R:%.*]] = fdiv float -4.200000e+01, [[X:%.*]]264; CHECK-NEXT: ret float [[R]]265;266 %d = fdiv float 42.0, %x267 %r = fneg nsz float %d268 ret float %r269}270 271define float @fdiv_op0_constant_fneg_ninf_ninf(float %x) {272; CHECK-LABEL: @fdiv_op0_constant_fneg_ninf_ninf(273; CHECK-NEXT: [[R:%.*]] = fdiv ninf float -4.200000e+01, [[X:%.*]]274; CHECK-NEXT: ret float [[R]]275;276 %d = fdiv ninf float 42.0, %x277 %r = fneg ninf float %d278 ret float %r279}280 281define float @fdiv_op0_constant_fneg_ninf(float %x) {282; CHECK-LABEL: @fdiv_op0_constant_fneg_ninf(283; CHECK-NEXT: [[R:%.*]] = fdiv float -4.200000e+01, [[X:%.*]]284; CHECK-NEXT: ret float [[R]]285;286 %d = fdiv float 42.0, %x287 %r = fneg ninf float %d288 ret float %r289}290 291define float @fdiv_op0_constant_fneg_nnan_nnan(float %x) {292; CHECK-LABEL: @fdiv_op0_constant_fneg_nnan_nnan(293; CHECK-NEXT: [[R:%.*]] = fdiv nnan float -4.200000e+01, [[X:%.*]]294; CHECK-NEXT: ret float [[R]]295;296 %d = fdiv nnan float 42.0, %x297 %r = fneg nnan float %d298 ret float %r299}300 301define float @fdiv_op0_constant_fneg_nnan(float %x) {302; CHECK-LABEL: @fdiv_op0_constant_fneg_nnan(303; CHECK-NEXT: [[R:%.*]] = fdiv nnan float -4.200000e+01, [[X:%.*]]304; CHECK-NEXT: ret float [[R]]305;306 %d = fdiv float 42.0, %x307 %r = fneg nnan float %d308 ret float %r309}310 311; Extra use prevents the fold. We don't want to replace the fneg with an fdiv.312 313define float @fdiv_op0_constant_fsub_extra_use(float %x) {314; CHECK-LABEL: @fdiv_op0_constant_fsub_extra_use(315; CHECK-NEXT: [[D:%.*]] = fdiv float -4.200000e+01, [[X:%.*]]316; CHECK-NEXT: [[R:%.*]] = fneg float [[D]]317; CHECK-NEXT: call void @use(float [[D]])318; CHECK-NEXT: ret float [[R]]319;320 %d = fdiv float -42.0, %x321 %r = fsub float -0.0, %d322 call void @use(float %d)323 ret float %r324}325 326define float @fdiv_op0_constant_fneg_extra_use(float %x) {327; CHECK-LABEL: @fdiv_op0_constant_fneg_extra_use(328; CHECK-NEXT: [[D:%.*]] = fdiv float -4.200000e+01, [[X:%.*]]329; CHECK-NEXT: [[R:%.*]] = fneg float [[D]]330; CHECK-NEXT: call void @use(float [[D]])331; CHECK-NEXT: ret float [[R]]332;333 %d = fdiv float -42.0, %x334 %r = fneg float %d335 call void @use(float %d)336 ret float %r337}338 339; Try a vector. Use special constants (NaN, INF, poison) because they don't change anything.340 341define <4 x double> @fdiv_op0_constant_fsub_vec(<4 x double> %x) {342; CHECK-LABEL: @fdiv_op0_constant_fsub_vec(343; CHECK-NEXT: [[R:%.*]] = fdiv <4 x double> <double 4.200000e+01, double 0xFFF8000000000000, double 0x7FF0000000000000, double poison>, [[X:%.*]]344; CHECK-NEXT: ret <4 x double> [[R]]345;346 %d = fdiv <4 x double> <double -42.0, double 0x7FF8000000000000, double 0xFFF0000000000000, double poison>, %x347 %r = fsub <4 x double> <double -0.0, double -0.0, double -0.0, double -0.0>, %d348 ret <4 x double> %r349}350 351define <4 x double> @fdiv_op0_constant_fneg_vec(<4 x double> %x) {352; CHECK-LABEL: @fdiv_op0_constant_fneg_vec(353; CHECK-NEXT: [[R:%.*]] = fdiv <4 x double> <double 4.200000e+01, double 0xFFF8000000000000, double 0x7FF0000000000000, double poison>, [[X:%.*]]354; CHECK-NEXT: ret <4 x double> [[R]]355;356 %d = fdiv <4 x double> <double -42.0, double 0x7FF8000000000000, double 0xFFF0000000000000, double poison>, %x357 %r = fneg <4 x double> %d358 ret <4 x double> %r359}360 361; Sink FP negation through a select:362; c ? -x : -y --> -(c ? x : y)363 364define <2 x double> @fneg_fneg_sel(<2 x double> %x, <2 x double> %y, i1 %cond) {365; CHECK-LABEL: @fneg_fneg_sel(366; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[COND:%.*]], <2 x double> [[X:%.*]], <2 x double> [[Y:%.*]]367; CHECK-NEXT: [[SEL:%.*]] = fneg <2 x double> [[SEL_V]]368; CHECK-NEXT: ret <2 x double> [[SEL]]369;370 %n1 = fneg <2 x double> %x371 %n2 = fneg <2 x double> %y372 %sel = select i1 %cond, <2 x double> %n1, <2 x double> %n2373 ret <2 x double> %sel374}375 376; An extra use is allowed.377 378define float @fneg_fneg_sel_extra_use1(float %x, float %y, i1 %cond) {379; CHECK-LABEL: @fneg_fneg_sel_extra_use1(380; CHECK-NEXT: [[N1:%.*]] = fneg float [[X:%.*]]381; CHECK-NEXT: call void @use(float [[N1]])382; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[COND:%.*]], float [[X]], float [[Y:%.*]]383; CHECK-NEXT: [[SEL:%.*]] = fneg float [[SEL_V]]384; CHECK-NEXT: ret float [[SEL]]385;386 %n1 = fneg float %x387 call void @use(float %n1)388 %n2 = fneg float %y389 %sel = select i1 %cond, float %n1, float %n2390 ret float %sel391}392 393define float @fneg_fneg_sel_extra_use2(float %x, float %y, i1 %cond) {394; CHECK-LABEL: @fneg_fneg_sel_extra_use2(395; CHECK-NEXT: [[N2:%.*]] = fneg float [[Y:%.*]]396; CHECK-NEXT: call void @use(float [[N2]])397; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[COND:%.*]], float [[X:%.*]], float [[Y]]398; CHECK-NEXT: [[SEL:%.*]] = fneg float [[SEL_V]]399; CHECK-NEXT: ret float [[SEL]]400;401 %n1 = fneg float %x402 %n2 = fneg float %y403 call void @use(float %n2)404 %sel = select i1 %cond, float %n1, float %n2405 ret float %sel406}407 408; Legacy form of fneg should work too.409 410define float @fsub_fsub_sel_extra_use1(float %x, float %y, i1 %cond) {411; CHECK-LABEL: @fsub_fsub_sel_extra_use1(412; CHECK-NEXT: [[N1:%.*]] = fneg float [[X:%.*]]413; CHECK-NEXT: call void @use(float [[N1]])414; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[COND:%.*]], float [[X]], float [[Y:%.*]]415; CHECK-NEXT: [[SEL:%.*]] = fneg float [[SEL_V]]416; CHECK-NEXT: ret float [[SEL]]417;418 %n1 = fsub float -0.0, %x419 call void @use(float %n1)420 %n2 = fsub float -0.0, %y421 %sel = select i1 %cond, float %n1, float %n2422 ret float %sel423}424 425; Negative test: but 2 extra uses would require an extra instruction.426 427define float @fneg_fneg_sel_extra_use3(float %x, float %y, i1 %cond) {428; CHECK-LABEL: @fneg_fneg_sel_extra_use3(429; CHECK-NEXT: [[N1:%.*]] = fneg float [[X:%.*]]430; CHECK-NEXT: call void @use(float [[N1]])431; CHECK-NEXT: [[N2:%.*]] = fneg float [[Y:%.*]]432; CHECK-NEXT: call void @use(float [[N2]])433; CHECK-NEXT: [[SEL:%.*]] = select i1 [[COND:%.*]], float [[N1]], float [[N2]]434; CHECK-NEXT: ret float [[SEL]]435;436 %n1 = fneg float %x437 call void @use(float %n1)438 %n2 = fneg float %y439 call void @use(float %n2)440 %sel = select i1 %cond, float %n1, float %n2441 ret float %sel442}443 444define double @fneg_fneg_sel_fmf1(double %x, double %y, i1 %cond) {445; CHECK-LABEL: @fneg_fneg_sel_fmf1(446; CHECK-NEXT: [[SEL_V:%.*]] = select i1 [[COND:%.*]], double [[X:%.*]], double [[Y:%.*]]447; CHECK-NEXT: [[SEL:%.*]] = fneg double [[SEL_V]]448; CHECK-NEXT: ret double [[SEL]]449;450 %n1 = fneg nnan double %x451 %n2 = fneg ninf double %y452 %sel = select i1 %cond, double %n1, double %n2453 ret double %sel454}455 456define double @fneg_fneg_sel_fmf2(double %x, double %y, i1 %cond) {457; CHECK-LABEL: @fneg_fneg_sel_fmf2(458; CHECK-NEXT: [[SEL_V:%.*]] = select ninf i1 [[COND:%.*]], double [[X:%.*]], double [[Y:%.*]]459; CHECK-NEXT: [[SEL:%.*]] = fneg ninf double [[SEL_V]]460; CHECK-NEXT: ret double [[SEL]]461;462 %n1 = fneg nnan ninf double %x463 %n2 = fneg ninf double %y464 %sel = select i1 %cond, double %n1, double %n2465 ret double %sel466}467 468define double @fneg_fneg_sel_fmf3(double %x, double %y, i1 %cond) {469; CHECK-LABEL: @fneg_fneg_sel_fmf3(470; CHECK-NEXT: [[SEL_V:%.*]] = select ninf i1 [[COND:%.*]], double [[X:%.*]], double [[Y:%.*]]471; CHECK-NEXT: [[SEL:%.*]] = fneg ninf double [[SEL_V]]472; CHECK-NEXT: ret double [[SEL]]473;474 %n1 = fneg nnan ninf double %x475 %n2 = fneg ninf double %y476 %sel = select ninf i1 %cond, double %n1, double %n2477 ret double %sel478}479 480define double @fneg_fneg_sel_fmf4(double %x, double %y, i1 %cond) {481; CHECK-LABEL: @fneg_fneg_sel_fmf4(482; CHECK-NEXT: [[SEL_V:%.*]] = select nnan ninf nsz i1 [[COND:%.*]], double [[X:%.*]], double [[Y:%.*]]483; CHECK-NEXT: [[SEL:%.*]] = fneg nnan ninf nsz double [[SEL_V]]484; CHECK-NEXT: ret double [[SEL]]485;486 %n1 = fneg nnan double %x487 %n2 = fneg ninf double %y488 %sel = select nsz nnan ninf i1 %cond, double %n1, double %n2489 ret double %sel490}491 492; Negative test493 494define float @fneg_fadd_constant(float %x) {495; CHECK-LABEL: @fneg_fadd_constant(496; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], 4.200000e+01497; CHECK-NEXT: [[R:%.*]] = fneg float [[A]]498; CHECK-NEXT: ret float [[R]]499;500 %a = fadd float %x, 42.0501 %r = fneg float %a502 ret float %r503}504 505; Negative test506 507define float @fake_nsz_fadd_constant(float %x) {508; CHECK-LABEL: @fake_nsz_fadd_constant(509; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], 4.200000e+01510; CHECK-NEXT: [[R:%.*]] = fneg float [[A]]511; CHECK-NEXT: ret float [[R]]512;513 %a = fadd float %x, 42.0514 %r = fsub float -0.0, %a515 ret float %r516}517 518; -(X + C) --> -C - X519 520define float @fneg_nsz_fadd_constant(float %x) {521; CHECK-LABEL: @fneg_nsz_fadd_constant(522; CHECK-NEXT: [[R:%.*]] = fsub nsz float -4.200000e+01, [[X:%.*]]523; CHECK-NEXT: ret float [[R]]524;525 %a = fadd float %x, 42.0526 %r = fneg nsz float %a527 ret float %r528}529 530; -(X + C) --> -C - X531 532define float @fake_fneg_nsz_fadd_constant(float %x) {533; CHECK-LABEL: @fake_fneg_nsz_fadd_constant(534; CHECK-NEXT: [[R:%.*]] = fsub fast float -4.200000e+01, [[X:%.*]]535; CHECK-NEXT: ret float [[R]]536;537 %a = fadd float %x, 42.0538 %r = fsub fast float -0.0, %a539 ret float %r540}541 542; Negative test543 544define float @fneg_nsz_fadd_constant_extra_use(float %x) {545; CHECK-LABEL: @fneg_nsz_fadd_constant_extra_use(546; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], 4.200000e+01547; CHECK-NEXT: call void @use(float [[A]])548; CHECK-NEXT: [[R:%.*]] = fneg nsz float [[A]]549; CHECK-NEXT: ret float [[R]]550;551 %a = fadd float %x, 42.0552 call void @use(float %a)553 %r = fneg nsz float %a554 ret float %r555}556 557; Negative test558 559define float @fake_fneg_nsz_fadd_constant_extra_use(float %x) {560; CHECK-LABEL: @fake_fneg_nsz_fadd_constant_extra_use(561; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], 4.200000e+01562; CHECK-NEXT: call void @use(float [[A]])563; CHECK-NEXT: [[R:%.*]] = fneg fast float [[A]]564; CHECK-NEXT: ret float [[R]]565;566 %a = fadd float %x, 42.0567 call void @use(float %a)568 %r = fsub fast float -0.0, %a569 ret float %r570}571 572; -(X + C) --> -C - X573 574define <2 x float> @fneg_nsz_fadd_constant_vec(<2 x float> %x) {575; CHECK-LABEL: @fneg_nsz_fadd_constant_vec(576; CHECK-NEXT: [[R:%.*]] = fsub reassoc nnan nsz <2 x float> <float -4.200000e+01, float -4.300000e+01>, [[X:%.*]]577; CHECK-NEXT: ret <2 x float> [[R]]578;579 %a = fadd <2 x float> %x, <float 42.0, float 43.0>580 %r = fneg nsz nnan reassoc <2 x float> %a581 ret <2 x float> %r582}583 584; -(X + C) --> -C - X585 586define <2 x float> @fake_fneg_nsz_fadd_constant_vec(<2 x float> %x) {587; CHECK-LABEL: @fake_fneg_nsz_fadd_constant_vec(588; CHECK-NEXT: [[R:%.*]] = fsub nsz <2 x float> <float -4.200000e+01, float poison>, [[X:%.*]]589; CHECK-NEXT: ret <2 x float> [[R]]590;591 %a = fadd <2 x float> %x, <float 42.0, float poison>592 %r = fsub nsz <2 x float> <float poison, float -0.0>, %a593 ret <2 x float> %r594}595 596@g = external global i16, align 1597 598define float @fneg_nsz_fadd_constant_expr(float %x) {599; CHECK-LABEL: @fneg_nsz_fadd_constant_expr(600; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], bitcast (i32 ptrtoint (ptr @g to i32) to float)601; CHECK-NEXT: [[R:%.*]] = fneg nsz float [[A]]602; CHECK-NEXT: ret float [[R]]603;604 %a = fadd float %x, bitcast (i32 ptrtoint (ptr @g to i32) to float)605 %r = fneg nsz float %a606 ret float %r607}608 609define float @fake_fneg_nsz_fadd_constant_expr(float %x) {610; CHECK-LABEL: @fake_fneg_nsz_fadd_constant_expr(611; CHECK-NEXT: [[A:%.*]] = fadd float [[X:%.*]], bitcast (i32 ptrtoint (ptr @g to i32) to float)612; CHECK-NEXT: [[R:%.*]] = fneg nsz float [[A]]613; CHECK-NEXT: ret float [[R]]614;615 %a = fadd float %x, bitcast (i32 ptrtoint (ptr @g to i32) to float)616 %r = fsub nsz float -0.0, %a617 ret float %r618}619 620define float @select_fneg_true(float %x, float %y, i1 %b) {621; CHECK-LABEL: @select_fneg_true(622; CHECK-NEXT: [[Y_NEG:%.*]] = fneg float [[Y:%.*]]623; CHECK-NEXT: [[R:%.*]] = select i1 [[B:%.*]], float [[X:%.*]], float [[Y_NEG]]624; CHECK-NEXT: ret float [[R]]625;626 %nx = fneg float %x627 %s = select i1 %b, float %nx, float %y628 %r = fneg float %s629 ret float %r630}631 632define <2 x float> @select_fneg_false(<2 x float> %x, <2 x float> %y, <2 x i1> %b) {633; CHECK-LABEL: @select_fneg_false(634; CHECK-NEXT: [[X_NEG:%.*]] = fneg nnan nsz <2 x float> [[X:%.*]]635; CHECK-NEXT: [[R:%.*]] = select nnan ninf <2 x i1> [[B:%.*]], <2 x float> [[X_NEG]], <2 x float> [[Y:%.*]]636; CHECK-NEXT: ret <2 x float> [[R]]637;638 %ny = fneg nnan <2 x float> %y639 %s = select ninf <2 x i1> %b, <2 x float> %x, <2 x float> %ny640 %r = fneg nsz nnan <2 x float> %s641 ret <2 x float> %r642}643 644define float @select_fneg_false_no_nsz(float %x, float %y, i1 %b) {645; CHECK-LABEL: @select_fneg_false_no_nsz(646; CHECK-NEXT: [[X_NEG:%.*]] = fneg nnan ninf nsz float [[X:%.*]]647; CHECK-NEXT: [[R:%.*]] = select nnan ninf i1 [[B:%.*]], float [[X_NEG]], float [[Y:%.*]]648; CHECK-NEXT: ret float [[R]]649;650 %ny = fneg float %y651 %s = select i1 %b, float %x, float %ny652 %r = fneg ninf nnan nsz float %s653 ret float %r654}655 656; The removal of nsz in this pattern is not needed if the select condition can't be poison.657 658define float @select_fneg_false_nsz_ok(float %x, float %y, i1 noundef %b) {659; CHECK-LABEL: @select_fneg_false_nsz_ok(660; CHECK-NEXT: [[X_NEG:%.*]] = fneg nnan ninf nsz float [[X:%.*]]661; CHECK-NEXT: [[R:%.*]] = select nnan ninf nsz i1 [[B:%.*]], float [[X_NEG]], float [[Y:%.*]]662; CHECK-NEXT: ret float [[R]]663;664 %ny = fneg float %y665 %s = select i1 %b, float %x, float %ny666 %r = fneg nsz ninf nnan float %s667 ret float %r668}669 670define float @select_fneg_false_nsz(float %x, float %y, i1 %b) {671; CHECK-LABEL: @select_fneg_false_nsz(672; CHECK-NEXT: [[X_NEG:%.*]] = fneg nnan ninf nsz float [[X:%.*]]673; CHECK-NEXT: [[R:%.*]] = select nnan ninf nsz i1 [[B:%.*]], float [[X_NEG]], float [[Y:%.*]]674; CHECK-NEXT: ret float [[R]]675;676 %ny = fneg float %y677 %s = select nsz i1 %b, float %x, float %ny678 %r = fneg ninf nnan nsz float %s679 ret float %r680}681 682; Special-case for propagating nsz: it's ok when selecting between an operand and its negation.683 684define float @select_common_op_fneg_true(float %x, i1 %b) {685; CHECK-LABEL: @select_common_op_fneg_true(686; CHECK-NEXT: [[X_NEG:%.*]] = fneg nnan ninf nsz float [[X:%.*]]687; CHECK-NEXT: [[R:%.*]] = select nnan ninf nsz i1 [[B:%.*]], float [[X_NEG]], float [[X]]688; CHECK-NEXT: ret float [[R]]689;690 %nx = fneg float %x691 %s = select i1 %b, float %x, float %nx692 %r = fneg nsz ninf nnan float %s693 ret float %r694}695 696define float @select_common_op_fneg_false(float %x, i1 %b) {697; CHECK-LABEL: @select_common_op_fneg_false(698; CHECK-NEXT: [[X_NEG:%.*]] = fneg nnan ninf nsz float [[X:%.*]]699; CHECK-NEXT: [[R:%.*]] = select nnan ninf nsz i1 [[B:%.*]], float [[X_NEG]], float [[X]]700; CHECK-NEXT: ret float [[R]]701;702 %nx = fneg float %x703 %s = select i1 %b, float %x, float %nx704 %r = fneg nsz ninf nnan float %s705 ret float %r706}707 708; The transform above allows follow-on folds to convert to fabs.709 710define float @fabs(float %a) {711; CHECK-LABEL: @fabs(712; CHECK-NEXT: [[FNEG1:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]])713; CHECK-NEXT: ret float [[FNEG1]]714;715 %fneg = fneg float %a716 %cmp = fcmp ogt float %a, %fneg717 %sel = select i1 %cmp, float %fneg, float %a718 %fneg1 = fneg nnan ninf nsz float %sel719 ret float %fneg1720}721 722define float @fnabs(float %a) {723; CHECK-LABEL: @fnabs(724; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]])725; CHECK-NEXT: [[FNEG1:%.*]] = fneg fast float [[TMP1]]726; CHECK-NEXT: ret float [[FNEG1]]727;728 %fneg = fneg float %a729 %cmp = fcmp olt float %a, %fneg730 %sel = select i1 %cmp, float %fneg, float %a731 %fneg1 = fneg fast float %sel732 ret float %fneg1733}734 735define float @fnabs_1(float %a) {736; CHECK-LABEL: @fnabs_1(737; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]])738; CHECK-NEXT: [[FNEG1:%.*]] = fneg fast float [[TMP1]]739; CHECK-NEXT: ret float [[FNEG1]]740;741 %fneg = fneg float %a742 %cmp = fcmp ogt float %a, %fneg743 %sel = select i1 %cmp, float %a, float %fneg744 %fneg1 = fneg fast float %sel745 ret float %fneg1746}747 748; This is not fabs because that could produce a different signbit for a NAN input.749; PR59279750 751define float @fnabs_2_nsz(float %a) {752; CHECK-LABEL: @fnabs_2_nsz(753; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[A:%.*]], 0.000000e+00754; CHECK-NEXT: [[A_NEG:%.*]] = fneg float [[A]]755; CHECK-NEXT: [[FNEG1:%.*]] = select nsz i1 [[CMP]], float [[A]], float [[A_NEG]]756; CHECK-NEXT: ret float [[FNEG1]]757;758 %fneg = fneg float %a759 %cmp = fcmp olt float %a, %fneg760 %sel = select nsz i1 %cmp, float %fneg, float %a761 %fneg1 = fneg float %sel762 ret float %fneg1763}764 765define float @fnabs_2_nsz_nnan(float %a) {766; CHECK-LABEL: @fnabs_2_nsz_nnan(767; CHECK-NEXT: [[SEL:%.*]] = call nnan nsz float @llvm.fabs.f32(float [[A:%.*]])768; CHECK-NEXT: [[FNEG1:%.*]] = fneg float [[SEL]]769; CHECK-NEXT: ret float [[FNEG1]]770;771 %fneg = fneg float %a772 %cmp = fcmp olt float %a, %fneg773 %sel = select nsz nnan i1 %cmp, float %fneg, float %a774 %fneg1 = fneg float %sel775 ret float %fneg1776}777 778define float @select_fneg_both(float %x, float %y, i1 %b) {779; CHECK-LABEL: @select_fneg_both(780; CHECK-NEXT: [[S_V:%.*]] = select i1 [[B:%.*]], float [[X:%.*]], float [[Y:%.*]]781; CHECK-NEXT: ret float [[S_V]]782;783 %nx = fneg float %x784 %ny = fneg float %y785 %s = select i1 %b, float %nx, float %ny786 %r = fneg float %s787 ret float %r788}789 790define float @select_fneg_use1(float %x, float %y, i1 %b) {791; CHECK-LABEL: @select_fneg_use1(792; CHECK-NEXT: [[NX:%.*]] = fneg ninf float [[X:%.*]]793; CHECK-NEXT: call void @use(float [[NX]])794; CHECK-NEXT: [[Y_NEG:%.*]] = fneg float [[Y:%.*]]795; CHECK-NEXT: [[R:%.*]] = select fast i1 [[B:%.*]], float [[X]], float [[Y_NEG]]796; CHECK-NEXT: ret float [[R]]797;798 %nx = fneg ninf float %x799 call void @use(float %nx)800 %s = select fast i1 %b, float %nx, float %y801 %r = fneg float %s802 ret float %r803}804 805define float @select_fneg_use2(float %x, float %y, i1 %b) {806; CHECK-LABEL: @select_fneg_use2(807; CHECK-NEXT: call void @use(float [[Y:%.*]])808; CHECK-NEXT: [[Y_NEG:%.*]] = fneg fast float [[Y]]809; CHECK-NEXT: [[R:%.*]] = select reassoc nnan ninf arcp contract afn i1 [[B:%.*]], float [[X:%.*]], float [[Y_NEG]]810; CHECK-NEXT: ret float [[R]]811;812 call void @use(float %y)813 %nx = fneg nsz float %x814 %s = select ninf i1 %b, float %nx, float %y815 %r = fneg fast float %s816 ret float %r817}818 819; Negative test820 821define float @select_fneg_use3(float %x, float %y, i1 %b) {822; CHECK-LABEL: @select_fneg_use3(823; CHECK-NEXT: [[NX:%.*]] = fneg float [[X:%.*]]824; CHECK-NEXT: [[S:%.*]] = select i1 [[B:%.*]], float [[NX]], float [[Y:%.*]]825; CHECK-NEXT: call void @use(float [[S]])826; CHECK-NEXT: [[R:%.*]] = fneg float [[S]]827; CHECK-NEXT: ret float [[R]]828;829 %nx = fneg float %x830 %s = select i1 %b, float %nx, float %y831 call void @use(float %s)832 %r = fneg float %s833 ret float %r834}835 836define float @fneg_ldexp(float %x, i32 %n) {837; CHECK-LABEL: @fneg_ldexp(838; CHECK-NEXT: [[TMP1:%.*]] = fneg float [[X:%.*]]839; CHECK-NEXT: [[NEG:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])840; CHECK-NEXT: ret float [[NEG]]841;842 %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)843 %neg = fneg float %ldexp844 ret float %neg845}846 847define float @fsub_fneg_ldexp(float %x, i32 %n) {848; CHECK-LABEL: @fsub_fneg_ldexp(849; CHECK-NEXT: [[TMP1:%.*]] = fneg float [[X:%.*]]850; CHECK-NEXT: [[NEG:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])851; CHECK-NEXT: ret float [[NEG]]852;853 %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)854 %neg = fsub float -0.0, %ldexp855 ret float %neg856}857 858define float @fsub_fneg_ldexp_nsz(float %x, i32 %n) {859; CHECK-LABEL: @fsub_fneg_ldexp_nsz(860; CHECK-NEXT: [[TMP1:%.*]] = fneg nsz float [[X:%.*]]861; CHECK-NEXT: [[NEG:%.*]] = call nsz float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])862; CHECK-NEXT: ret float [[NEG]]863;864 %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)865 %neg = fsub nsz float -0.0, %ldexp866 ret float %neg867}868 869define float @fsub_fneg_ldexp_p0_nsz(float %x, i32 %n) {870; CHECK-LABEL: @fsub_fneg_ldexp_p0_nsz(871; CHECK-NEXT: [[TMP1:%.*]] = fneg nsz float [[X:%.*]]872; CHECK-NEXT: [[NEG:%.*]] = call nsz float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])873; CHECK-NEXT: ret float [[NEG]]874;875 %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)876 %neg = fsub nsz float 0.0, %ldexp877 ret float %neg878}879 880define float @fsub_fneg_ldexp_p0(float %x, i32 %n) {881; CHECK-LABEL: @fsub_fneg_ldexp_p0(882; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])883; CHECK-NEXT: [[NEG:%.*]] = fsub float 0.000000e+00, [[LDEXP]]884; CHECK-NEXT: ret float [[NEG]]885;886 %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)887 %neg = fsub float 0.0, %ldexp888 ret float %neg889}890 891define <2 x float> @fneg_ldexp_vector(<2 x float> %x, <2 x i32> %n) {892; CHECK-LABEL: @fneg_ldexp_vector(893; CHECK-NEXT: [[TMP1:%.*]] = fneg <2 x float> [[X:%.*]]894; CHECK-NEXT: [[NEG:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[TMP1]], <2 x i32> [[N:%.*]])895; CHECK-NEXT: ret <2 x float> [[NEG]]896;897 %ldexp = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %x, <2 x i32> %n)898 %neg = fneg <2 x float> %ldexp899 ret <2 x float> %neg900}901 902define float @fneg_ldexp_multiuse(float %x, i32 %n, ptr %ptr) {903; CHECK-LABEL: @fneg_ldexp_multiuse(904; CHECK-NEXT: [[LDEXP:%.*]] = call float @llvm.ldexp.f32.i32(float [[X:%.*]], i32 [[N:%.*]])905; CHECK-NEXT: store float [[LDEXP]], ptr [[PTR:%.*]], align 4906; CHECK-NEXT: [[NEG:%.*]] = fneg float [[LDEXP]]907; CHECK-NEXT: ret float [[NEG]]908;909 %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)910 store float %ldexp, ptr %ptr911 %neg = fneg float %ldexp912 ret float %neg913}914 915define float @fneg_ldexp_fmf_ldexp(float %x, i32 %n) {916; CHECK-LABEL: @fneg_ldexp_fmf_ldexp(917; CHECK-NEXT: [[TMP1:%.*]] = fneg nnan float [[X:%.*]]918; CHECK-NEXT: [[NEG:%.*]] = call nnan float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])919; CHECK-NEXT: ret float [[NEG]]920;921 %ldexp = call nnan float @llvm.ldexp.f32.i32(float %x, i32 %n)922 %neg = fneg float %ldexp923 ret float %neg924}925 926define float @fneg_ldexp_fmf_neg(float %x, i32 %n) {927; CHECK-LABEL: @fneg_ldexp_fmf_neg(928; CHECK-NEXT: [[TMP1:%.*]] = fneg nnan float [[X:%.*]]929; CHECK-NEXT: [[NEG:%.*]] = call nnan float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])930; CHECK-NEXT: ret float [[NEG]]931;932 %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)933 %neg = fneg nnan float %ldexp934 ret float %neg935}936 937define float @fneg_ldexp_fmf(float %x, i32 %n) {938; CHECK-LABEL: @fneg_ldexp_fmf(939; CHECK-NEXT: [[TMP1:%.*]] = fneg nnan ninf float [[X:%.*]]940; CHECK-NEXT: [[NEG:%.*]] = call nnan ninf float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])941; CHECK-NEXT: ret float [[NEG]]942;943 %ldexp = call ninf float @llvm.ldexp.f32.i32(float %x, i32 %n)944 %neg = fneg nnan float %ldexp945 ret float %neg946}947 948define float @fneg_ldexp_contract0(float %x, i32 %n) {949; CHECK-LABEL: @fneg_ldexp_contract0(950; CHECK-NEXT: [[TMP1:%.*]] = fneg contract float [[X:%.*]]951; CHECK-NEXT: [[NEG:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])952; CHECK-NEXT: ret float [[NEG]]953;954 %ldexp = call contract float @llvm.ldexp.f32.i32(float %x, i32 %n)955 %neg = fneg float %ldexp956 ret float %neg957}958 959define float @fneg_ldexp_contract1(float %x, i32 %n) {960; CHECK-LABEL: @fneg_ldexp_contract1(961; CHECK-NEXT: [[TMP1:%.*]] = fneg contract float [[X:%.*]]962; CHECK-NEXT: [[NEG:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])963; CHECK-NEXT: ret float [[NEG]]964;965 %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n)966 %neg = fneg contract float %ldexp967 ret float %neg968}969 970define float @fneg_ldexp_contract(float %x, i32 %n) {971; CHECK-LABEL: @fneg_ldexp_contract(972; CHECK-NEXT: [[TMP1:%.*]] = fneg contract float [[X:%.*]]973; CHECK-NEXT: [[NEG:%.*]] = call contract float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]])974; CHECK-NEXT: ret float [[NEG]]975;976 %ldexp = call contract float @llvm.ldexp.f32.i32(float %x, i32 %n)977 %neg = fneg contract float %ldexp978 ret float %neg979}980 981define float @fneg_ldexp_metadata(float %x, i32 %n) {982; CHECK-LABEL: @fneg_ldexp_metadata(983; CHECK-NEXT: [[TMP1:%.*]] = fneg float [[X:%.*]]984; CHECK-NEXT: [[NEG:%.*]] = call float @llvm.ldexp.f32.i32(float [[TMP1]], i32 [[N:%.*]]), !arst [[META0:![0-9]+]]985; CHECK-NEXT: ret float [[NEG]]986;987 %ldexp = call float @llvm.ldexp.f32.i32(float %x, i32 %n), !arst !0988 %neg = fneg float %ldexp989 ret float %neg990}991 992define float @test_fneg_select_constants(i1 %cond) {993; CHECK-LABEL: @test_fneg_select_constants(994; CHECK-NEXT: [[NEG:%.*]] = select i1 [[COND:%.*]], float -0.000000e+00, float 0.000000e+00995; CHECK-NEXT: ret float [[NEG]]996;997 %sel1 = select i1 %cond, float 0.0, float -0.0998 %neg = fneg float %sel1999 ret float %neg1000}1001 1002define <2 x float> @test_fneg_vec(<2 x i1> %cond) {1003; CHECK-LABEL: @test_fneg_vec(1004; CHECK-NEXT: [[NEG:%.*]] = select <2 x i1> [[COND:%.*]], <2 x float> <float -0.000000e+00, float 0.000000e+00>, <2 x float> <float 0.000000e+00, float -0.000000e+00>1005; CHECK-NEXT: ret <2 x float> [[NEG]]1006;1007 %sel1 = select <2 x i1> %cond, <2 x float> <float 0.0, float -0.0>, <2 x float> <float -0.0, float 0.0>1008 %neg = fneg <2 x float> %sel11009 ret <2 x float> %neg1010}1011 1012define float @test_fneg_select_var_constant(i1 %cond, float %x) {1013; CHECK-LABEL: @test_fneg_select_var_constant(1014; CHECK-NEXT: [[X_NEG:%.*]] = fneg float [[X:%.*]]1015; CHECK-NEXT: [[NEG:%.*]] = select i1 [[COND:%.*]], float [[X_NEG]], float 0.000000e+001016; CHECK-NEXT: ret float [[NEG]]1017;1018 %sel1 = select i1 %cond, float %x, float -0.01019 %neg = fneg float %sel11020 ret float %neg1021}1022 1023; nsz can be preserved.1024 1025define float @test_fneg_select_var_constant_fmf1(i1 %cond, float %x) {1026; CHECK-LABEL: @test_fneg_select_var_constant_fmf1(1027; CHECK-NEXT: [[X_NEG:%.*]] = fneg float [[X:%.*]]1028; CHECK-NEXT: [[NEG:%.*]] = select nnan ninf nsz i1 [[COND:%.*]], float [[X_NEG]], float -1.000000e+001029; CHECK-NEXT: ret float [[NEG]]1030;1031 %sel1 = select nnan ninf nsz i1 %cond, float %x, float 1.01032 %neg = fneg float %sel11033 ret float %neg1034}1035 1036define float @test_fneg_select_var_constant_fmf2(i1 %cond, float %x) {1037; CHECK-LABEL: @test_fneg_select_var_constant_fmf2(1038; CHECK-NEXT: [[X_NEG:%.*]] = fneg nnan ninf nsz float [[X:%.*]]1039; CHECK-NEXT: [[NEG:%.*]] = select nnan ninf nsz i1 [[COND:%.*]], float [[X_NEG]], float -1.000000e+001040; CHECK-NEXT: ret float [[NEG]]1041;1042 %sel1 = select i1 %cond, float %x, float 1.01043 %neg = fneg nnan ninf nsz float %sel11044 ret float %neg1045}1046 1047define float @test_fneg_select_constant_var(i1 %cond, float %x) {1048; CHECK-LABEL: @test_fneg_select_constant_var(1049; CHECK-NEXT: [[X_NEG:%.*]] = fneg float [[X:%.*]]1050; CHECK-NEXT: [[NEG:%.*]] = select i1 [[COND:%.*]], float -0.000000e+00, float [[X_NEG]]1051; CHECK-NEXT: ret float [[NEG]]1052;1053 %sel1 = select i1 %cond, float 0.0, float %x1054 %neg = fneg float %sel11055 ret float %neg1056}1057 1058; Make sure nabs is generated.1059 1060define float @test_fneg_select_abs(i1 %cond, float %x) {1061; CHECK-LABEL: @test_fneg_select_abs(1062; CHECK-NEXT: [[ABSX:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])1063; CHECK-NEXT: [[ABSX_NEG:%.*]] = fneg float [[ABSX]]1064; CHECK-NEXT: [[NEG:%.*]] = select i1 [[COND:%.*]], float -0.000000e+00, float [[ABSX_NEG]]1065; CHECK-NEXT: ret float [[NEG]]1066;1067 %absx = call float @llvm.fabs.f32(float %x)1068 %sel1 = select i1 %cond, float 0.0, float %absx1069 %neg = fneg float %sel11070 ret float %neg1071}1072 1073define float @test_fneg_fabs_select(i1 %cond, float %x) {1074; CHECK-LABEL: @test_fneg_fabs_select(1075; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])1076; CHECK-NEXT: [[DOTNEG:%.*]] = fneg float [[TMP1]]1077; CHECK-NEXT: [[NEG:%.*]] = select i1 [[COND:%.*]], float -0.000000e+00, float [[DOTNEG]]1078; CHECK-NEXT: ret float [[NEG]]1079;1080 %sel1 = select i1 %cond, float 0.0, float %x1081 %abs = call float @llvm.fabs.f32(float %sel1)1082 %neg = fneg float %abs1083 ret float %neg1084}1085 1086define float @test_fneg_select_constant_var_multiuse(i1 %cond, float %x) {1087; CHECK-LABEL: @test_fneg_select_constant_var_multiuse(1088; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[COND:%.*]], float 0.000000e+00, float [[X:%.*]]1089; CHECK-NEXT: call void @use(float [[SEL1]])1090; CHECK-NEXT: [[NEG:%.*]] = fneg float [[SEL1]]1091; CHECK-NEXT: ret float [[NEG]]1092;1093 %sel1 = select i1 %cond, float 0.0, float %x1094 call void @use(float %sel1)1095 %neg = fneg float %sel11096 ret float %neg1097}1098 1099; Don't break fmax idioms.1100 1101define float @test_fneg_select_maxnum(float %x) {1102; CHECK-LABEL: @test_fneg_select_maxnum(1103; CHECK-NEXT: [[SEL1:%.*]] = call nsz float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00)1104; CHECK-NEXT: [[NEG:%.*]] = fneg float [[SEL1]]1105; CHECK-NEXT: ret float [[NEG]]1106;1107 %cmp1 = fcmp ogt float %x, 1.01108 %sel1 = select nnan nsz i1 %cmp1, float %x, float 1.01109 %neg = fneg float %sel11110 ret float %neg1111}1112 1113; Check that there's no infinite loop.1114define <vscale x 2 x double> @test_fneg_select_svec(<vscale x 2 x i1> %cond, <vscale x 2 x double> %b) {1115; CHECK-LABEL: @test_fneg_select_svec(1116; CHECK-NEXT: [[TMP2:%.*]] = fneg fast <vscale x 2 x double> [[TMP1:%.*]]1117; CHECK-NEXT: [[TMP3:%.*]] = select fast <vscale x 2 x i1> [[COND:%.*]], <vscale x 2 x double> splat (double -0.000000e+00), <vscale x 2 x double> [[TMP2]]1118; CHECK-NEXT: ret <vscale x 2 x double> [[TMP3]]1119;1120 %1 = select <vscale x 2 x i1> %cond, <vscale x 2 x double> zeroinitializer, <vscale x 2 x double> %b1121 %2 = fneg fast <vscale x 2 x double> %11122 ret <vscale x 2 x double> %21123}1124 1125define <vscale x 2 x double> @test_fneg_select_svec_2(<vscale x 2 x i1> %cond, <vscale x 2 x double> %a) {1126; CHECK-LABEL: @test_fneg_select_svec_2(1127; CHECK-NEXT: [[A_NEG:%.*]] = fneg fast <vscale x 2 x double> [[A:%.*]]1128; CHECK-NEXT: [[TMP1:%.*]] = select fast <vscale x 2 x i1> [[COND:%.*]], <vscale x 2 x double> [[A_NEG]], <vscale x 2 x double> splat (double -0.000000e+00)1129; CHECK-NEXT: ret <vscale x 2 x double> [[TMP1]]1130;1131 %1 = select <vscale x 2 x i1> %cond, <vscale x 2 x double> %a, <vscale x 2 x double> zeroinitializer1132 %2 = fneg fast <vscale x 2 x double> %11133 ret <vscale x 2 x double> %21134}1135 1136define <vscale x 2 x double> @test_fneg_select_svec_3(<vscale x 2 x i1> %cond, <vscale x 2 x double> %b) {1137; CHECK-LABEL: @test_fneg_select_svec_3(1138; CHECK-NEXT: ret <vscale x 2 x double> splat (double -0.000000e+00)1139;1140 %1 = select <vscale x 2 x i1> %cond, <vscale x 2 x double> zeroinitializer, <vscale x 2 x double> zeroinitializer1141 %2 = fneg fast <vscale x 2 x double> %11142 ret <vscale x 2 x double> %21143}1144 1145define float @test_fneg_ninf_mul_with_anyzero(float %a) {1146; CHECK-LABEL: @test_fneg_ninf_mul_with_anyzero(1147; CHECK-NEXT: [[F:%.*]] = fmul float [[A:%.*]], -0.000000e+001148; CHECK-NEXT: ret float [[F]]1149;1150 %mul = fmul float %a, 0.01151 %f = fneg ninf float %mul1152 ret float %f1153}1154 1155define float @test_fsub_ninf_mul_with_anyzero(float %a) {1156; CHECK-LABEL: @test_fsub_ninf_mul_with_anyzero(1157; CHECK-NEXT: [[F2:%.*]] = fmul nsz float [[A:%.*]], -0.000000e+001158; CHECK-NEXT: ret float [[F2]]1159;1160 %f1 = fmul nsz float %a, 0.0000001161 %f2 = fsub ninf float -0.000000, %f11162 ret float %f21163}1164 1165define float @test_fneg_nnan_mul_with_anyzero(float %a) {1166; CHECK-LABEL: @test_fneg_nnan_mul_with_anyzero(1167; CHECK-NEXT: [[TMP1:%.*]] = fneg nnan float [[A:%.*]]1168; CHECK-NEXT: [[F2:%.*]] = call nnan float @llvm.copysign.f32(float 0.000000e+00, float [[TMP1]])1169; CHECK-NEXT: ret float [[F2]]1170;1171 %f1 = fmul ninf float %a, 0.0000001172 %f2 = fneg nnan float %f11173 ret float %f21174}1175 1176define float @test_fneg_nsz_mul_with_anyzero(float %a) {1177; CHECK-LABEL: @test_fneg_nsz_mul_with_anyzero(1178; CHECK-NEXT: [[F2:%.*]] = fmul nsz float [[A:%.*]], -0.000000e+001179; CHECK-NEXT: ret float [[F2]]1180;1181 %f1 = fmul ninf float %a, 0.0000001182 %f2 = fneg nsz float %f11183 ret float %f21184}1185 1186define float @test_fneg_ninf_mul_nnan_with_const(float %a) {1187; CHECK-LABEL: @test_fneg_ninf_mul_nnan_with_const(1188; CHECK-NEXT: [[TMP1:%.*]] = fneg float [[A:%.*]]1189; CHECK-NEXT: [[F2:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[TMP1]])1190; CHECK-NEXT: ret float [[F2]]1191;1192 %f1 = fmul nnan float %a, 0.0000001193 %f2 = fneg ninf float %f11194 ret float %f21195}1196 1197define float @test_fneg_ninf_mul_nsz_with_const(float %a) {1198; CHECK-LABEL: @test_fneg_ninf_mul_nsz_with_const(1199; CHECK-NEXT: [[F2:%.*]] = fmul nsz float [[A:%.*]], -0.000000e+001200; CHECK-NEXT: ret float [[F2]]1201;1202 %f1 = fmul nsz float %a, 0.0000001203 %f2 = fneg ninf float %f11204 ret float %f21205}1206 1207define <2 x float> @test_fneg_mul_combine_nnan_ninf_with_vec_const(<2 x float> %a) {1208; CHECK-LABEL: @test_fneg_mul_combine_nnan_ninf_with_vec_const(1209; CHECK-NEXT: [[F2:%.*]] = fmul nnan <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>1210; CHECK-NEXT: ret <2 x float> [[F2]]1211;1212 %f1 = fmul nnan <2 x float> %a, <float 0.000000, float -0.000000>1213 %f2 = fneg ninf <2 x float> %f11214 ret <2 x float> %f21215}1216 1217define <2 x float> @test_fneg_mul_combine_nsz_ninf_with_vec_const(<2 x float> %a) {1218; CHECK-LABEL: @test_fneg_mul_combine_nsz_ninf_with_vec_const(1219; CHECK-NEXT: [[F2:%.*]] = fmul nsz <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>1220; CHECK-NEXT: ret <2 x float> [[F2]]1221;1222 %f1 = fmul nsz <2 x float> %a, <float 0.000000, float -0.000000>1223 %f2 = fneg ninf <2 x float> %f11224 ret <2 x float> %f21225}1226 1227define <2 x float> @test_fneg_ninf_nnan_mul_with_vec_const(<2 x float> %a) {1228; CHECK-LABEL: @test_fneg_ninf_nnan_mul_with_vec_const(1229; CHECK-NEXT: [[F2:%.*]] = fmul nnan <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>1230; CHECK-NEXT: ret <2 x float> [[F2]]1231;1232 %f1 = fmul <2 x float> %a, <float 0.000000, float -0.000000>1233 %f2 = fneg nnan ninf <2 x float> %f11234 ret <2 x float> %f21235}1236 1237define <2 x float> @test_fneg_mul_combine_nnan_ninf_with_vec_const2(<2 x float> %a) {1238; CHECK-LABEL: @test_fneg_mul_combine_nnan_ninf_with_vec_const2(1239; CHECK-NEXT: [[F2:%.*]] = fmul nnan ninf <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>1240; CHECK-NEXT: ret <2 x float> [[F2]]1241;1242 %f1 = fmul ninf <2 x float> %a, <float 0.000000, float -0.000000>1243 %f2 = fneg nnan ninf <2 x float> %f11244 ret <2 x float> %f21245}1246 1247define <2 x float> @test_fneg_mul_combine_reassoc_ninf_with_vec_const1(<2 x float> %a) {1248; CHECK-LABEL: @test_fneg_mul_combine_reassoc_ninf_with_vec_const1(1249; CHECK-NEXT: [[F2:%.*]] = fmul <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>1250; CHECK-NEXT: ret <2 x float> [[F2]]1251;1252 %f1 = fmul reassoc <2 x float> %a, <float 0.000000, float -0.000000>1253 %f2 = fneg ninf <2 x float> %f11254 ret <2 x float> %f21255}1256 1257define <2 x float> @test_fneg_mul_combine_reassoc_ninf_with_vec_const2(<2 x float> %a) {1258; CHECK-LABEL: @test_fneg_mul_combine_reassoc_ninf_with_vec_const2(1259; CHECK-NEXT: [[F2:%.*]] = fmul ninf <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>1260; CHECK-NEXT: ret <2 x float> [[F2]]1261;1262 %f1 = fmul ninf <2 x float> %a, <float 0.000000, float -0.000000>1263 %f2 = fneg reassoc ninf <2 x float> %f11264 ret <2 x float> %f21265}1266 1267define <2 x float> @test_fneg_mul_combine_reassoc_ninf_with_vec_const3(<2 x float> %a) {1268; CHECK-LABEL: @test_fneg_mul_combine_reassoc_ninf_with_vec_const3(1269; CHECK-NEXT: [[F2:%.*]] = fmul reassoc <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>1270; CHECK-NEXT: ret <2 x float> [[F2]]1271;1272 %f1 = fmul reassoc <2 x float> %a, <float 0.000000, float -0.000000>1273 %f2 = fneg reassoc ninf <2 x float> %f11274 ret <2 x float> %f21275}1276 1277define <2 x float> @test_fneg_mul_combine_contract_ninf_with_vec_const1(<2 x float> %a) {1278; CHECK-LABEL: @test_fneg_mul_combine_contract_ninf_with_vec_const1(1279; CHECK-NEXT: [[F2:%.*]] = fmul <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>1280; CHECK-NEXT: ret <2 x float> [[F2]]1281;1282 %f1 = fmul contract <2 x float> %a, <float 0.000000, float -0.000000>1283 %f2 = fneg ninf <2 x float> %f11284 ret <2 x float> %f21285}1286 1287define <2 x float> @test_fneg_mul_combine_contract_ninf_with_vec_const2(<2 x float> %a) {1288; CHECK-LABEL: @test_fneg_mul_combine_contract_ninf_with_vec_const2(1289; CHECK-NEXT: [[F2:%.*]] = fmul ninf <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>1290; CHECK-NEXT: ret <2 x float> [[F2]]1291;1292 %f1 = fmul ninf <2 x float> %a, <float 0.000000, float -0.000000>1293 %f2 = fneg contract ninf <2 x float> %f11294 ret <2 x float> %f21295}1296 1297define <2 x float> @test_fneg_mul_combine_contract_ninf_with_vec_const3(<2 x float> %a) {1298; CHECK-LABEL: @test_fneg_mul_combine_contract_ninf_with_vec_const3(1299; CHECK-NEXT: [[F2:%.*]] = fmul contract <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>1300; CHECK-NEXT: ret <2 x float> [[F2]]1301;1302 %f1 = fmul contract <2 x float> %a, <float 0.000000, float -0.000000>1303 %f2 = fneg contract ninf <2 x float> %f11304 ret <2 x float> %f21305}1306 1307!0 = !{}1308