xref: /llvm-project/llvm/test/Transforms/InstCombine/fneg.ll (revision 02328e0465c256293950542f1a85eb55bcbc9d45)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3; RUN: opt < %s -passes=instcombine -use-constant-fp-for-fixed-length-splat -S | FileCheck %s
4
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 %a
15  %r = fneg float %f
16  ret float %r
17}
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+01
24; CHECK-NEXT:    ret float [[R]]
25;
26  %m = fmul float %x, 42.0
27  %r = fsub float -0.0, %m
28  ret float %r
29}
30
31define float @fmul_fneg(float %x) {
32; CHECK-LABEL: @fmul_fneg(
33; CHECK-NEXT:    [[R:%.*]] = fmul float [[X:%.*]], -4.200000e+01
34; CHECK-NEXT:    ret float [[R]]
35;
36  %m = fmul float %x, 42.0
37  %r = fneg float %m
38  ret float %r
39}
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 reassoc nsz float [[X:%.*]], -4.200000e+01
46; CHECK-NEXT:    ret float [[R]]
47;
48  %m = fmul float %x, 42.0
49  %r = fsub reassoc nsz float -0.0, %m
50  ret float %r
51}
52
53define float @fmul_fneg_fmf(float %x) {
54; CHECK-LABEL: @fmul_fneg_fmf(
55; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz float [[X:%.*]], -4.200000e+01
56; CHECK-NEXT:    ret float [[R]]
57;
58  %m = fmul float %x, 42.0
59  %r = fneg reassoc nsz float %m
60  ret float %r
61}
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+01
68; 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.0
73  %r = fsub float -0.0, %m
74  call void @use(float %m)
75  ret float %r
76}
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+01
81; 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.0
86  %r = fneg float %m
87  call void @use(float %m)
88  ret float %r
89}
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>, %m
100  ret <4 x double> %r
101}
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> %m
110  ret <4 x double> %r
111}
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+01
118; CHECK-NEXT:    ret float [[R]]
119;
120  %d = fdiv float %x, -42.0
121  %r = fsub float -0.0, %d
122  ret float %r
123}
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+01
128; CHECK-NEXT:    ret float [[R]]
129;
130  %d = fdiv float %x, -42.0
131  %r = fneg float %d
132  ret float %r
133}
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+01
140; CHECK-NEXT:    ret float [[R]]
141;
142  %d = fdiv float %x, -42.0
143  %r = fsub nnan float -0.0, %d
144  ret float %r
145}
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+01
150; CHECK-NEXT:    ret float [[R]]
151;
152  %d = fdiv float %x, -42.0
153  %r = fneg nnan float %d
154  ret float %r
155}
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+01
162; 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.0
167  %r = fsub float -0.0, %d
168  call void @use(float %d)
169  ret float %r
170}
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+01
175; 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.0
180  %r = fneg float %d
181  call void @use(float %d)
182  ret float %r
183}
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>, %d
194  ret <4 x double> %r
195}
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> %d
204  ret <4 x double> %r
205}
206
207; -(C / X) --> (-C) / X
208
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, %x
215  %r = fsub float -0.0, %d
216  ret float %r
217}
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, %x
225  %r = fneg float %d
226  ret float %r
227}
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, %x
237  %r = fneg fast float %d
238  ret float %r
239}
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, %x
247  %r = fneg fast float %d
248  ret float %r
249}
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, %x
257  %r = fneg nsz float %d
258  ret float %r
259}
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, %x
267  %r = fneg nsz float %d
268  ret float %r
269}
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, %x
277  %r = fneg ninf float %d
278  ret float %r
279}
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, %x
287  %r = fneg ninf float %d
288  ret float %r
289}
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, %x
297  %r = fneg nnan float %d
298  ret float %r
299}
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, %x
307  %r = fneg nnan float %d
308  ret float %r
309}
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, %x
321  %r = fsub float -0.0, %d
322  call void @use(float %d)
323  ret float %r
324}
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, %x
334  %r = fneg float %d
335  call void @use(float %d)
336  ret float %r
337}
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>, %x
347  %r = fsub <4 x double> <double -0.0, double -0.0, double -0.0, double -0.0>, %d
348  ret <4 x double> %r
349}
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>, %x
357  %r = fneg <4 x double> %d
358  ret <4 x double> %r
359}
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> %x
371  %n2 = fneg <2 x double> %y
372  %sel = select i1 %cond, <2 x double> %n1, <2 x double> %n2
373  ret <2 x double> %sel
374}
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 %x
387  call void @use(float %n1)
388  %n2 = fneg float %y
389  %sel = select i1 %cond, float %n1, float %n2
390  ret float %sel
391}
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 %x
402  %n2 = fneg float %y
403  call void @use(float %n2)
404  %sel = select i1 %cond, float %n1, float %n2
405  ret float %sel
406}
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, %x
419  call void @use(float %n1)
420  %n2 = fsub float -0.0, %y
421  %sel = select i1 %cond, float %n1, float %n2
422  ret float %sel
423}
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 %x
437  call void @use(float %n1)
438  %n2 = fneg float %y
439  call void @use(float %n2)
440  %sel = select i1 %cond, float %n1, float %n2
441  ret float %sel
442}
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 %x
451  %n2 = fneg ninf double %y
452  %sel = select i1 %cond, double %n1, double %n2
453  ret double %sel
454}
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 %x
463  %n2 = fneg ninf double %y
464  %sel = select i1 %cond, double %n1, double %n2
465  ret double %sel
466}
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 %x
475  %n2 = fneg ninf double %y
476  %sel = select ninf i1 %cond, double %n1, double %n2
477  ret double %sel
478}
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 %x
487  %n2 = fneg ninf double %y
488  %sel = select nsz nnan ninf i1 %cond, double %n1, double %n2
489  ret double %sel
490}
491
492; Negative test
493
494define float @fneg_fadd_constant(float %x) {
495; CHECK-LABEL: @fneg_fadd_constant(
496; CHECK-NEXT:    [[A:%.*]] = fadd float [[X:%.*]], 4.200000e+01
497; CHECK-NEXT:    [[R:%.*]] = fneg float [[A]]
498; CHECK-NEXT:    ret float [[R]]
499;
500  %a = fadd float %x, 42.0
501  %r = fneg float %a
502  ret float %r
503}
504
505; Negative test
506
507define float @fake_nsz_fadd_constant(float %x) {
508; CHECK-LABEL: @fake_nsz_fadd_constant(
509; CHECK-NEXT:    [[A:%.*]] = fadd float [[X:%.*]], 4.200000e+01
510; CHECK-NEXT:    [[R:%.*]] = fneg float [[A]]
511; CHECK-NEXT:    ret float [[R]]
512;
513  %a = fadd float %x, 42.0
514  %r = fsub float -0.0, %a
515  ret float %r
516}
517
518; -(X + C) --> -C - X
519
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.0
526  %r = fneg nsz float %a
527  ret float %r
528}
529
530; -(X + C) --> -C - X
531
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.0
538  %r = fsub fast float -0.0, %a
539  ret float %r
540}
541
542; Negative test
543
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+01
547; 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.0
552  call void @use(float %a)
553  %r = fneg nsz float %a
554  ret float %r
555}
556
557; Negative test
558
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+01
562; 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.0
567  call void @use(float %a)
568  %r = fsub fast float -0.0, %a
569  ret float %r
570}
571
572; -(X + C) --> -C - X
573
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> %a
581  ret <2 x float> %r
582}
583
584; -(X + C) --> -C - X
585
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>, %a
593  ret <2 x float> %r
594}
595
596@g = external global i16, align 1
597
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 %a
606  ret float %r
607}
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, %a
617  ret float %r
618}
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 %x
627  %s = select i1 %b, float %nx, float %y
628  %r = fneg float %s
629  ret float %r
630}
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> %y
639  %s = select ninf <2 x i1> %b, <2 x float> %x, <2 x float> %ny
640  %r = fneg nsz nnan <2 x float> %s
641  ret <2 x float> %r
642}
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 %y
651  %s = select i1 %b, float %x, float %ny
652  %r = fneg ninf nnan nsz float %s
653  ret float %r
654}
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 %y
665  %s = select i1 %b, float %x, float %ny
666  %r = fneg nsz ninf nnan float %s
667  ret float %r
668}
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 %y
677  %s = select nsz i1 %b, float %x, float %ny
678  %r = fneg ninf nnan nsz float %s
679  ret float %r
680}
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 %x
691  %s = select i1 %b, float %x, float %nx
692  %r = fneg nsz ninf nnan float %s
693  ret float %r
694}
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 %x
703  %s = select i1 %b, float %x, float %nx
704  %r = fneg nsz ninf nnan float %s
705  ret float %r
706}
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 nnan ninf nsz float @llvm.fabs.f32(float [[A:%.*]])
713; CHECK-NEXT:    ret float [[FNEG1]]
714;
715  %fneg = fneg float %a
716  %cmp = fcmp ogt float %a, %fneg
717  %sel = select i1 %cmp, float %fneg, float %a
718  %fneg1 = fneg nnan ninf nsz float %sel
719  ret float %fneg1
720}
721
722define float @fnabs(float %a) {
723; CHECK-LABEL: @fnabs(
724; CHECK-NEXT:    [[TMP1:%.*]] = call fast 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 %a
729  %cmp = fcmp olt float %a, %fneg
730  %sel = select i1 %cmp, float %fneg, float %a
731  %fneg1 = fneg fast float %sel
732  ret float %fneg1
733}
734
735define float @fnabs_1(float %a) {
736; CHECK-LABEL: @fnabs_1(
737; CHECK-NEXT:    [[TMP1:%.*]] = call fast 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 %a
742  %cmp = fcmp ogt float %a, %fneg
743  %sel = select i1 %cmp, float %a, float %fneg
744  %fneg1 = fneg fast float %sel
745  ret float %fneg1
746}
747
748; This is not fabs because that could produce a different signbit for a NAN input.
749; PR59279
750
751define float @fnabs_2_nsz(float %a) {
752; CHECK-LABEL: @fnabs_2_nsz(
753; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt float [[A:%.*]], 0.000000e+00
754; 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 %a
759  %cmp = fcmp olt float %a, %fneg
760  %sel = select nsz i1 %cmp, float %fneg, float %a
761  %fneg1 = fneg float %sel
762  ret float %fneg1
763}
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 %a
772  %cmp = fcmp olt float %a, %fneg
773  %sel = select nsz nnan i1 %cmp, float %fneg, float %a
774  %fneg1 = fneg float %sel
775  ret float %fneg1
776}
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 %x
784  %ny = fneg float %y
785  %s = select i1 %b, float %nx, float %ny
786  %r = fneg float %s
787  ret float %r
788}
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 %x
799  call void @use(float %nx)
800  %s = select fast i1 %b, float %nx, float %y
801  %r = fneg float %s
802  ret float %r
803}
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 %x
814  %s = select ninf i1 %b, float %nx, float %y
815  %r = fneg fast float %s
816  ret float %r
817}
818
819; Negative test
820
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 %x
830  %s = select i1 %b, float %nx, float %y
831  call void @use(float %s)
832  %r = fneg float %s
833  ret float %r
834}
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 %ldexp
844  ret float %neg
845}
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, %ldexp
855  ret float %neg
856}
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, %ldexp
866  ret float %neg
867}
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, %ldexp
877  ret float %neg
878}
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, %ldexp
888  ret float %neg
889}
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> %ldexp
899  ret <2 x float> %neg
900}
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 4
906; 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 %ptr
911  %neg = fneg float %ldexp
912  ret float %neg
913}
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 %ldexp
923  ret float %neg
924}
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 %ldexp
934  ret float %neg
935}
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 %ldexp
945  ret float %neg
946}
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 %ldexp
956  ret float %neg
957}
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 %ldexp
967  ret float %neg
968}
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 %ldexp
978  ret float %neg
979}
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 !0
988  %neg = fneg float %ldexp
989  ret float %neg
990}
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+00
995; CHECK-NEXT:    ret float [[NEG]]
996;
997  %sel1 = select i1 %cond, float 0.0, float -0.0
998  %neg = fneg float %sel1
999  ret float %neg
1000}
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> %sel1
1009  ret <2 x float> %neg
1010}
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+00
1016; CHECK-NEXT:    ret float [[NEG]]
1017;
1018  %sel1 = select i1 %cond, float %x, float -0.0
1019  %neg = fneg float %sel1
1020  ret float %neg
1021}
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+00
1029; CHECK-NEXT:    ret float [[NEG]]
1030;
1031  %sel1 = select nnan ninf nsz i1 %cond, float %x, float 1.0
1032  %neg = fneg float %sel1
1033  ret float %neg
1034}
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+00
1040; CHECK-NEXT:    ret float [[NEG]]
1041;
1042  %sel1 = select i1 %cond, float %x, float 1.0
1043  %neg = fneg nnan ninf nsz float %sel1
1044  ret float %neg
1045}
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 %x
1054  %neg = fneg float %sel1
1055  ret float %neg
1056}
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 %absx
1069  %neg = fneg float %sel1
1070  ret float %neg
1071}
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 %x
1081  %abs = call float @llvm.fabs.f32(float %sel1)
1082  %neg = fneg float %abs
1083  ret float %neg
1084}
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 %x
1094  call void @use(float %sel1)
1095  %neg = fneg float %sel1
1096  ret float %neg
1097}
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.0
1108  %sel1 = select nnan nsz i1 %cmp1, float %x, float 1.0
1109  %neg = fneg float %sel1
1110  ret float %neg
1111}
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> %b
1121  %2 = fneg fast <vscale x 2 x double> %1
1122  ret <vscale x 2 x double> %2
1123}
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> zeroinitializer
1132  %2 = fneg fast <vscale x 2 x double> %1
1133  ret <vscale x 2 x double> %2
1134}
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> zeroinitializer
1141  %2 = fneg fast <vscale x 2 x double> %1
1142  ret <vscale x 2 x double> %2
1143}
1144
1145!0 = !{}
1146