xref: /llvm-project/llvm/test/Transforms/InstSimplify/floating-point-arithmetic.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
3
4; fneg (fneg X) ==> X
5define float @fneg_fneg_var(float %a) {
6; CHECK-LABEL: @fneg_fneg_var(
7; CHECK-NEXT:    ret float [[A:%.*]]
8;
9  %r  = fneg float %a
10  %r1 = fneg float %r
11  ret float %r1
12}
13
14; fneg (fsub -0.0, X) ==> X
15define float @fsub_-0_x(float %a) {
16; CHECK-LABEL: @fsub_-0_x(
17; CHECK-NEXT:    ret float [[A:%.*]]
18;
19  %t1 = fsub float -0.0, %a
20  %ret = fneg float %t1
21  ret float %ret
22}
23
24define <2 x float> @fsub_-0_x_vec(<2 x float> %a) {
25; CHECK-LABEL: @fsub_-0_x_vec(
26; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
27;
28  %t1 = fsub <2 x float> <float -0.0, float -0.0>, %a
29  %ret = fneg <2 x float> %t1
30  ret <2 x float> %ret
31}
32
33define <2 x float> @fsub_-0_x_vec_poison_elts(<2 x float> %a) {
34; CHECK-LABEL: @fsub_-0_x_vec_poison_elts(
35; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
36;
37  %t1 = fsub <2 x float> <float -0.0, float poison>, %a
38  %ret = fneg <2 x float> %t1
39  ret <2 x float> %ret
40}
41
42define <2 x float> @fsub_negzero_vec_poison_elts(<2 x float> %x) {
43; CHECK-LABEL: @fsub_negzero_vec_poison_elts(
44; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
45;
46  %r = fsub nsz <2 x float> %x, <float poison, float -0.0>
47  ret <2 x float> %r
48}
49
50; fsub -0.0, (fsub -0.0, X) ==> X
51define float @fsub_-0_-0_x(float %a) {
52; CHECK-LABEL: @fsub_-0_-0_x(
53; CHECK-NEXT:    ret float [[A:%.*]]
54;
55  %t1 = fsub float -0.0, %a
56  %ret = fsub float -0.0, %t1
57  ret float %ret
58}
59
60; fsub -0.0, (fneg X) ==> X
61define float @fneg_x(float %a) {
62; CHECK-LABEL: @fneg_x(
63; CHECK-NEXT:    ret float [[A:%.*]]
64;
65  %t1 = fneg float %a
66  %ret = fsub float -0.0, %t1
67  ret float %ret
68}
69
70define <2 x float> @fsub_-0_-0_x_vec(<2 x float> %a) {
71; CHECK-LABEL: @fsub_-0_-0_x_vec(
72; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
73;
74  %t1 = fsub <2 x float> <float -0.0, float -0.0>, %a
75  %ret = fsub <2 x float> <float -0.0, float -0.0>, %t1
76  ret <2 x float> %ret
77}
78
79define <2 x float> @fneg_x_vec(<2 x float> %a) {
80; CHECK-LABEL: @fneg_x_vec(
81; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
82;
83  %t1 = fneg <2 x float> %a
84  %ret = fsub <2 x float> <float -0.0, float -0.0>, %t1
85  ret <2 x float> %ret
86}
87
88define <2 x float> @fsub_-0_-0_x_vec_poison_elts(<2 x float> %a) {
89; CHECK-LABEL: @fsub_-0_-0_x_vec_poison_elts(
90; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
91;
92  %t1 = fsub <2 x float> <float poison, float -0.0>, %a
93  %ret = fsub <2 x float> <float -0.0, float poison>, %t1
94  ret <2 x float> %ret
95}
96
97define <2 x float> @fneg_x_vec_poison_elts(<2 x float> %a) {
98; CHECK-LABEL: @fneg_x_vec_poison_elts(
99; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
100;
101  %t1 = fneg <2 x float> %a
102  %ret = fsub <2 x float> <float -0.0, float poison>, %t1
103  ret <2 x float> %ret
104}
105
106; fsub -0.0, (fsub 0.0, X) != X
107define float @fsub_-0_0_x(float %a) {
108; CHECK-LABEL: @fsub_-0_0_x(
109; CHECK-NEXT:    [[T1:%.*]] = fsub float 0.000000e+00, [[A:%.*]]
110; CHECK-NEXT:    [[RET:%.*]] = fsub float -0.000000e+00, [[T1]]
111; CHECK-NEXT:    ret float [[RET]]
112;
113  %t1 = fsub float 0.0, %a
114  %ret = fsub float -0.0, %t1
115  ret float %ret
116}
117
118; fsub 0.0, (fsub -0.0, X) != X
119define float @fsub_0_-0_x(float %a) {
120; CHECK-LABEL: @fsub_0_-0_x(
121; CHECK-NEXT:    [[T1:%.*]] = fsub float -0.000000e+00, [[A:%.*]]
122; CHECK-NEXT:    [[RET:%.*]] = fsub float 0.000000e+00, [[T1]]
123; CHECK-NEXT:    ret float [[RET]]
124;
125  %t1 = fsub float -0.0, %a
126  %ret = fsub float 0.0, %t1
127  ret float %ret
128}
129
130; fsub X, 0 ==> X
131define float @fsub_x_0(float %x) {
132; CHECK-LABEL: @fsub_x_0(
133; CHECK-NEXT:    ret float [[X:%.*]]
134;
135  %r = fsub float %x, 0.0
136  ret float %r
137}
138
139define <2 x float> @fsub_x_0_vec_poison(<2 x float> %x) {
140; CHECK-LABEL: @fsub_x_0_vec_poison(
141; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
142;
143  %r = fsub <2 x float> %x, <float poison, float 0.0>
144  ret <2 x float> %r
145}
146
147; fadd X, -0 ==> X
148define float @fadd_x_n0(float %a) {
149; CHECK-LABEL: @fadd_x_n0(
150; CHECK-NEXT:    ret float [[A:%.*]]
151;
152  %ret = fadd float %a, -0.0
153  ret float %ret
154}
155
156define <2 x float> @fadd_x_n0_vec_poison_elt(<2 x float> %a) {
157; CHECK-LABEL: @fadd_x_n0_vec_poison_elt(
158; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
159;
160  %ret = fadd <2 x float> %a, <float -0.0, float poison>
161  ret <2 x float> %ret
162}
163
164; fmul X, 1.0 ==> X
165define double @fmul_X_1(double %a) {
166; CHECK-LABEL: @fmul_X_1(
167; CHECK-NEXT:    ret double [[A:%.*]]
168;
169  %b = fmul double 1.0, %a
170  ret double %b
171}
172
173define half @fmul_nnan_ninf_nneg_0.0(i15 %x) {
174; CHECK-LABEL: @fmul_nnan_ninf_nneg_0.0(
175; CHECK-NEXT:    ret half 0xH0000
176;
177  %f = uitofp i15 %x to half
178  %r = fmul half %f, 0.0
179  ret half %r
180}
181
182define half @fmul_nnan_ninf_nneg_n0.0(i15 %x) {
183; CHECK-LABEL: @fmul_nnan_ninf_nneg_n0.0(
184; CHECK-NEXT:    ret half 0xH8000
185;
186  %f = uitofp i15 %x to half
187  %r = fmul half %f, -0.0
188  ret half %r
189}
190
191; negative test - the int could be big enough to round to INF
192
193define half @fmul_nnan_nneg_0.0(i16 %x) {
194; CHECK-LABEL: @fmul_nnan_nneg_0.0(
195; CHECK-NEXT:    [[F:%.*]] = uitofp i16 [[X:%.*]] to half
196; CHECK-NEXT:    [[R:%.*]] = fmul half [[F]], 0xH0000
197; CHECK-NEXT:    ret half [[R]]
198;
199  %f = uitofp i16 %x to half
200  %r = fmul half %f, 0.0
201  ret half %r
202}
203
204define double @fmul_nnan_ninf_nneg_n0.0_commute(i127 %x) {
205; CHECK-LABEL: @fmul_nnan_ninf_nneg_n0.0_commute(
206; CHECK-NEXT:    ret double -0.000000e+00
207;
208  %f = uitofp i127 %x to float
209  %e = fpext float %f to double
210  %r = fmul double -0.0, %e
211  ret double %r
212}
213
214define float @src_mul_nzero_neg(float nofpclass(inf nan pzero psub pnorm) %f) {
215; CHECK-LABEL: @src_mul_nzero_neg(
216; CHECK-NEXT:    ret float 0.000000e+00
217;
218  %r = fmul float %f, -0.0
219  ret float %r
220}
221
222define <2 x float> @src_mul_zero_neg(<2 x float> nofpclass(inf nan pzero psub pnorm) %f) {
223; CHECK-LABEL: @src_mul_zero_neg(
224; CHECK-NEXT:    ret <2 x float> splat (float -0.000000e+00)
225;
226  %r = fmul <2 x float> <float 0.0, float 0.0>, %f
227  ret <2 x float> %r
228}
229
230define <2 x float> @src_mul_zero_and_nzero_neg(<2 x float> nofpclass(inf nan pzero psub pnorm) %f) {
231; CHECK-LABEL: @src_mul_zero_and_nzero_neg(
232; CHECK-NEXT:    ret <2 x float> <float 0.000000e+00, float -0.000000e+00>
233;
234  %r = fmul <2 x float> <float -0.0, float 0.0>, %f
235  ret <2 x float> %r
236}
237
238
239define float @src_muladd_zero_neg(float nofpclass(inf nan pzero psub pnorm) %f, float %add) {
240; CHECK-LABEL: @src_muladd_zero_neg(
241; CHECK-NEXT:    [[R:%.*]] = call float @llvm.fmuladd.f32(float [[F:%.*]], float 0.000000e+00, float [[ADD:%.*]])
242; CHECK-NEXT:    ret float [[R]]
243;
244  %r = call float @llvm.fmuladd.f32(float %f, float 0.0, float %add)
245  ret float %r
246}
247
248define float @src_fma_nzero_neg(float nofpclass(inf nan pzero psub pnorm) %f, float %add) {
249; CHECK-LABEL: @src_fma_nzero_neg(
250; CHECK-NEXT:    [[R:%.*]] = call float @llvm.fma.f32(float -0.000000e+00, float [[F:%.*]], float [[ADD:%.*]])
251; CHECK-NEXT:    ret float [[R]]
252;
253  %r = call float @llvm.fma.f32(float -0.0, float %f, float %add)
254  ret float %r
255}
256
257
258; Make sure we can infer %x can't be 0 based on assumes.
259define { float, float } @test_fmul_0_assumed_finite(float %x) {
260; CHECK-LABEL: @test_fmul_0_assumed_finite(
261; CHECK-NEXT:    [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
262; CHECK-NEXT:    [[IS_FINITE_X:%.*]] = fcmp one float [[FABS_X]], 0x7FF0000000000000
263; CHECK-NEXT:    call void @llvm.assume(i1 [[IS_FINITE_X]])
264; CHECK-NEXT:    ret { float, float } { float 0.000000e+00, float -0.000000e+00 }
265;
266  %fabs.x = call float @llvm.fabs.f32(float %x)
267  %is.finite.x = fcmp one float %fabs.x, 0x7FF0000000000000
268  call void @llvm.assume(i1 %is.finite.x)
269  %mul.0 = fmul float %fabs.x, 0.0
270  %mul.neg0 = fmul float %fabs.x, -0.0
271  %ins.0 = insertvalue { float, float } poison, float %mul.0, 0
272  %ins.1 = insertvalue { float, float } %ins.0, float %mul.neg0, 1
273  ret { float, float } %ins.1
274}
275
276; negative test - the int could be big enough to round to INF
277
278define double @fmul_nnan_ninf_nneg_0.0_commute(i128 %x) {
279; CHECK-LABEL: @fmul_nnan_ninf_nneg_0.0_commute(
280; CHECK-NEXT:    [[F:%.*]] = uitofp i128 [[X:%.*]] to float
281; CHECK-NEXT:    [[E:%.*]] = fpext float [[F]] to double
282; CHECK-NEXT:    [[R:%.*]] = fmul double 0.000000e+00, [[E]]
283; CHECK-NEXT:    ret double [[R]]
284;
285  %f = uitofp i128 %x to float
286  %e = fpext float %f to double
287  %r = fmul double 0.0, %e
288  ret double %r
289}
290
291; PR2642
292define <4 x float> @fmul_X_1_vec(<4 x float> %x) {
293; CHECK-LABEL: @fmul_X_1_vec(
294; CHECK-NEXT:    ret <4 x float> [[X:%.*]]
295;
296  %m = fmul <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0>
297  ret <4 x float> %m
298}
299
300; fdiv X, 1.0 ==> X
301define float @fdiv_x_1(float %a) {
302; CHECK-LABEL: @fdiv_x_1(
303; CHECK-NEXT:    ret float [[A:%.*]]
304;
305  %ret = fdiv float %a, 1.0
306  ret float %ret
307}
308
309; We can't optimize away the fadd in this test because the input
310; value to the function and subsequently to the fadd may be -0.0.
311; In that one special case, the result of the fadd should be +0.0
312; rather than the first parameter of the fadd.
313
314; Fragile test warning: We need 6 sqrt calls to trigger the bug
315; because the internal logic has a magic recursion limit of 6.
316; This is presented without any explanation or ability to customize.
317
318declare float @sqrtf(float)
319
320define float @PR22688(float %x) {
321; CHECK-LABEL: @PR22688(
322; CHECK-NEXT:    [[TMP1:%.*]] = call float @sqrtf(float [[X:%.*]])
323; CHECK-NEXT:    [[TMP2:%.*]] = call float @sqrtf(float [[TMP1]])
324; CHECK-NEXT:    [[TMP3:%.*]] = call float @sqrtf(float [[TMP2]])
325; CHECK-NEXT:    [[TMP4:%.*]] = call float @sqrtf(float [[TMP3]])
326; CHECK-NEXT:    [[TMP5:%.*]] = call float @sqrtf(float [[TMP4]])
327; CHECK-NEXT:    [[TMP6:%.*]] = call float @sqrtf(float [[TMP5]])
328; CHECK-NEXT:    [[TMP7:%.*]] = fadd float [[TMP6]], 0.000000e+00
329; CHECK-NEXT:    ret float [[TMP7]]
330;
331  %1 = call float @sqrtf(float %x)
332  %2 = call float @sqrtf(float %1)
333  %3 = call float @sqrtf(float %2)
334  %4 = call float @sqrtf(float %3)
335  %5 = call float @sqrtf(float %4)
336  %6 = call float @sqrtf(float %5)
337  %7 = fadd float %6, 0.0
338  ret float %7
339}
340
341declare float @llvm.fabs.f32(float)
342declare double @llvm.fabs.f64(double)
343declare float @llvm.canonicalize.f32(float)
344declare float @llvm.floor.f32(float)
345declare float @llvm.ceil.f32(float)
346declare float @llvm.trunc.f32(float)
347declare float @llvm.rint.f32(float)
348declare float @llvm.nearbyint.f32(float)
349declare float @llvm.round.f32(float)
350declare float @llvm.roundeven.f32(float)
351declare float @llvm.fptrunc.round.f32.f64(double, metadata)
352declare float @llvm.arithmetic.fence.f32(float)
353declare float @llvm.copysign.f32(float, float)
354declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
355declare float @llvm.sqrt.f32(float)
356declare float @llvm.maxnum.f32(float, float)
357declare void @llvm.assume(i1 noundef)
358
359
360define float @fabs_select_positive_constants(i32 %c) {
361; CHECK-LABEL: @fabs_select_positive_constants(
362; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
363; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00
364; CHECK-NEXT:    ret float [[SELECT]]
365;
366  %cmp = icmp eq i32 %c, 0
367  %select = select i1 %cmp, float 1.0, float 2.0
368  %fabs = call float @llvm.fabs.f32(float %select)
369  ret float %fabs
370}
371
372define <2 x float> @fabs_select_positive_constants_vector(i32 %c) {
373; CHECK-LABEL: @fabs_select_positive_constants_vector(
374; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
375; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 1.000000e+00), <2 x float> splat (float 2.000000e+00)
376; CHECK-NEXT:    ret <2 x float> [[SELECT]]
377;
378  %cmp = icmp eq i32 %c, 0
379  %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0>
380  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
381  ret <2 x float> %fabs
382}
383
384define float @fabs_select_constant_variable(i32 %c, float %x) {
385; CHECK-LABEL: @fabs_select_constant_variable(
386; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
387; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float [[X:%.*]]
388; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
389; CHECK-NEXT:    ret float [[FABS]]
390;
391  %cmp = icmp eq i32 %c, 0
392  %select = select i1 %cmp, float 1.0, float %x
393  %fabs = call float @llvm.fabs.f32(float %select)
394  ret float %fabs
395}
396
397define <2 x float> @fabs_select_constant_variable_vector(i32 %c, <2 x float> %x) {
398; CHECK-LABEL: @fabs_select_constant_variable_vector(
399; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
400; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 1.000000e+00), <2 x float> [[X:%.*]]
401; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
402; CHECK-NEXT:    ret <2 x float> [[FABS]]
403;
404  %cmp = icmp eq i32 %c, 0
405  %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> %x
406  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
407  ret <2 x float> %fabs
408}
409
410define float @fabs_select_neg0_pos0(i32 %c) {
411; CHECK-LABEL: @fabs_select_neg0_pos0(
412; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
413; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float 0.000000e+00
414; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
415; CHECK-NEXT:    ret float [[FABS]]
416;
417  %cmp = icmp eq i32 %c, 0
418  %select = select i1 %cmp, float -0.0, float 0.0
419  %fabs = call float @llvm.fabs.f32(float %select)
420  ret float %fabs
421}
422
423define <2 x float> @fabs_select_neg0_pos0_vector(i32 %c) {
424; CHECK-LABEL: @fabs_select_neg0_pos0_vector(
425; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
426; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float -0.000000e+00), <2 x float> zeroinitializer
427; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
428; CHECK-NEXT:    ret <2 x float> [[FABS]]
429;
430  %cmp = icmp eq i32 %c, 0
431  %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float 0.0, float 0.0>
432  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
433  ret <2 x float> %fabs
434}
435
436define float @fabs_select_neg0_neg1(i32 %c) {
437; CHECK-LABEL: @fabs_select_neg0_neg1(
438; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
439; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float -1.000000e+00
440; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
441; CHECK-NEXT:    ret float [[FABS]]
442;
443  %cmp = icmp eq i32 %c, 0
444  %select = select i1 %cmp, float -0.0, float -1.0
445  %fabs = call float @llvm.fabs.f32(float %select)
446  ret float %fabs
447}
448
449define <2 x float> @fabs_select_neg0_neg1_vector(i32 %c) {
450; CHECK-LABEL: @fabs_select_neg0_neg1_vector(
451; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
452; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float -0.000000e+00), <2 x float> splat (float -1.000000e+00)
453; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
454; CHECK-NEXT:    ret <2 x float> [[FABS]]
455;
456  %cmp = icmp eq i32 %c, 0
457  %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float -1.0, float -1.0>
458  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
459  ret <2 x float> %fabs
460}
461
462define float @fabs_select_nan_nan(i32 %c) {
463; CHECK-LABEL: @fabs_select_nan_nan(
464; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
465; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0x7FF8000000000000, float 0x7FF8000100000000
466; CHECK-NEXT:    ret float [[SELECT]]
467;
468  %cmp = icmp eq i32 %c, 0
469  %select = select i1 %cmp, float 0x7FF8000000000000, float 0x7FF8000100000000
470  %fabs = call float @llvm.fabs.f32(float %select)
471  ret float %fabs
472}
473
474define <2 x float> @fabs_select_nan_nan_vector(i32 %c) {
475; CHECK-LABEL: @fabs_select_nan_nan_vector(
476; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
477; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 0x7FF8000000000000), <2 x float> splat (float 0x7FF8000100000000)
478; CHECK-NEXT:    ret <2 x float> [[SELECT]]
479;
480  %cmp = icmp eq i32 %c, 0
481  %select = select i1 %cmp, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
482  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
483  ret <2 x float> %fabs
484}
485
486define float @fabs_select_negnan_nan(i32 %c) {
487; CHECK-LABEL: @fabs_select_negnan_nan(
488; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
489; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000000000000
490; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
491; CHECK-NEXT:    ret float [[FABS]]
492;
493  %cmp = icmp eq i32 %c, 0
494  %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000000000000
495  %fabs = call float @llvm.fabs.f32(float %select)
496  ret float %fabs
497}
498
499define <2 x float> @fabs_select_negnan_nan_vector(i32 %c) {
500; CHECK-LABEL: @fabs_select_negnan_nan_vector(
501; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
502; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 0xFFF8000000000000), <2 x float> splat (float 0x7FF8000000000000)
503; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
504; CHECK-NEXT:    ret <2 x float> [[FABS]]
505;
506  %cmp = icmp eq i32 %c, 0
507  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>
508  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
509  ret <2 x float> %fabs
510}
511
512define float @fabs_select_negnan_negnan(i32 %c) {
513; CHECK-LABEL: @fabs_select_negnan_negnan(
514; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
515; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000100000000
516; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
517; CHECK-NEXT:    ret float [[FABS]]
518;
519  %cmp = icmp eq i32 %c, 0
520  %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000100000000
521  %fabs = call float @llvm.fabs.f32(float %select)
522  ret float %fabs
523}
524
525define <2 x float> @fabs_select_negnan_negnan_vector(i32 %c) {
526; CHECK-LABEL: @fabs_select_negnan_negnan_vector(
527; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
528; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 0xFFF8000000000000), <2 x float> splat (float 0x7FF8000100000000)
529; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
530; CHECK-NEXT:    ret <2 x float> [[FABS]]
531;
532  %cmp = icmp eq i32 %c, 0
533  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
534  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
535  ret <2 x float> %fabs
536}
537
538define float @fabs_select_negnan_negzero(i32 %c) {
539; CHECK-LABEL: @fabs_select_negnan_negzero(
540; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
541; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float -0.000000e+00
542; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
543; CHECK-NEXT:    ret float [[FABS]]
544;
545  %cmp = icmp eq i32 %c, 0
546  %select = select i1 %cmp, float 0xFFF8000000000000, float -0.0
547  %fabs = call float @llvm.fabs.f32(float %select)
548  ret float %fabs
549}
550
551define <2 x float> @fabs_select_negnan_negzero_vector(i32 %c) {
552; CHECK-LABEL: @fabs_select_negnan_negzero_vector(
553; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
554; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 0xFFF8000000000000), <2 x float> splat (float -0.000000e+00)
555; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
556; CHECK-NEXT:    ret <2 x float> [[FABS]]
557;
558  %cmp = icmp eq i32 %c, 0
559  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.0, float -0.0>
560  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
561  ret <2 x float> %fabs
562}
563
564define float @fabs_select_negnan_zero(i32 %c) {
565; CHECK-LABEL: @fabs_select_negnan_zero(
566; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
567; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0.000000e+00
568; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
569; CHECK-NEXT:    ret float [[FABS]]
570;
571  %cmp = icmp eq i32 %c, 0
572  %select = select i1 %cmp, float 0xFFF8000000000000, float 0.0
573  %fabs = call float @llvm.fabs.f32(float %select)
574  ret float %fabs
575}
576
577define <2 x float> @fabs_select_negnan_zero_vector(i32 %c) {
578; CHECK-LABEL: @fabs_select_negnan_zero_vector(
579; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
580; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 0xFFF8000000000000), <2 x float> zeroinitializer
581; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
582; CHECK-NEXT:    ret <2 x float> [[FABS]]
583;
584  %cmp = icmp eq i32 %c, 0
585  %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0.0, float 0.0>
586  %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
587  ret <2 x float> %fabs
588}
589
590; The fabs can't be eliminated because llvm.sqrt.f32 may return -0 or NaN with
591; an arbitrary sign bit.
592define float @fabs_sqrt(float %a) {
593; CHECK-LABEL: @fabs_sqrt(
594; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]])
595; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
596; CHECK-NEXT:    ret float [[FABS]]
597;
598  %sqrt = call float @llvm.sqrt.f32(float %a)
599  %fabs = call float @llvm.fabs.f32(float %sqrt)
600  ret float %fabs
601}
602
603; The fabs can't be eliminated because the nnan sqrt may still return -0.
604define float @fabs_sqrt_nnan(float %a) {
605; CHECK-LABEL: @fabs_sqrt_nnan(
606; CHECK-NEXT:    [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
607; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
608; CHECK-NEXT:    ret float [[FABS]]
609;
610  %sqrt = call nnan float @llvm.sqrt.f32(float %a)
611  %fabs = call float @llvm.fabs.f32(float %sqrt)
612  ret float %fabs
613}
614
615; The fabs can't be eliminated because the nsz sqrt may still return NaN.
616define float @fabs_sqrt_nsz(float %a) {
617; CHECK-LABEL: @fabs_sqrt_nsz(
618; CHECK-NEXT:    [[SQRT:%.*]] = call nsz float @llvm.sqrt.f32(float [[A:%.*]])
619; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
620; CHECK-NEXT:    ret float [[FABS]]
621;
622  %sqrt = call nsz float @llvm.sqrt.f32(float %a)
623  %fabs = call float @llvm.fabs.f32(float %sqrt)
624  ret float %fabs
625}
626
627; The fabs can be eliminated because we're nsz and nnan.
628define float @fabs_sqrt_nnan_nsz(float %a) {
629; CHECK-LABEL: @fabs_sqrt_nnan_nsz(
630; CHECK-NEXT:    [[SQRT:%.*]] = call nnan nsz float @llvm.sqrt.f32(float [[A:%.*]])
631; CHECK-NEXT:    ret float [[SQRT]]
632;
633  %sqrt = call nnan nsz float @llvm.sqrt.f32(float %a)
634  %fabs = call float @llvm.fabs.f32(float %sqrt)
635  ret float %fabs
636}
637
638; The second fabs can be eliminated because the operand to sqrt cannot be -0.
639define float @fabs_sqrt_nnan_fabs(float %a) {
640; CHECK-LABEL: @fabs_sqrt_nnan_fabs(
641; CHECK-NEXT:    [[B:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]])
642; CHECK-NEXT:    [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[B]])
643; CHECK-NEXT:    ret float [[SQRT]]
644;
645  %b = call float @llvm.fabs.f32(float %a)
646  %sqrt = call nnan float @llvm.sqrt.f32(float %b)
647  %fabs = call float @llvm.fabs.f32(float %sqrt)
648  ret float %fabs
649}
650
651define float @fabs_select_positive_constants_vector_extract(i32 %c) {
652; CHECK-LABEL: @fabs_select_positive_constants_vector_extract(
653; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
654; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> splat (float 1.000000e+00), <2 x float> splat (float 2.000000e+00)
655; CHECK-NEXT:    [[EXTRACT:%.*]] = extractelement <2 x float> [[SELECT]], i32 0
656; CHECK-NEXT:    ret float [[EXTRACT]]
657;
658  %cmp = icmp eq i32 %c, 0
659  %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0>
660  %extract = extractelement <2 x float> %select, i32 0
661  %fabs = call float @llvm.fabs.f32(float %extract)
662  ret float %fabs
663}
664
665; Y - (Y - X) --> X
666
667define float @fsub_fsub_common_op(float %x, float %y) {
668; CHECK-LABEL: @fsub_fsub_common_op(
669; CHECK-NEXT:    ret float [[X:%.*]]
670;
671  %s = fsub float %y, %x
672  %r = fsub reassoc nsz float %y, %s
673  ret float %r
674}
675
676define <2 x float> @fsub_fsub_common_op_vec(<2 x float> %x, <2 x float> %y) {
677; CHECK-LABEL: @fsub_fsub_common_op_vec(
678; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
679;
680  %s = fsub <2 x float> %y, %x
681  %r = fsub reassoc nsz <2 x float> %y, %s
682  ret <2 x float> %r
683}
684
685; Negative test - fsub is not commutative.
686; Y - (X - Y) --> (Y - X) + Y (canonicalized)
687
688define float @fsub_fsub_wrong_common_op(float %x, float %y) {
689; CHECK-LABEL: @fsub_fsub_wrong_common_op(
690; CHECK-NEXT:    [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
691; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[S]]
692; CHECK-NEXT:    ret float [[R]]
693;
694  %s = fsub float %x, %y
695  %r = fsub reassoc nsz float %y, %s
696  ret float %r
697}
698
699; Negative test - negated operand needed.
700; (Y - X) - Y --> -X
701
702define float @fsub_fsub_common_op_wrong_commute(float %x, float %y) {
703; CHECK-LABEL: @fsub_fsub_common_op_wrong_commute(
704; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
705; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]]
706; CHECK-NEXT:    ret float [[R]]
707;
708  %s = fsub float %y, %x
709  %r = fsub reassoc nsz float %s, %y
710  ret float %r
711}
712
713; Negative test - fsub is not commutative.
714; (X - Y) - Y --> ?
715
716define float @fsub_fsub_wrong_common_op_wrong_commute(float %x, float %y) {
717; CHECK-LABEL: @fsub_fsub_wrong_common_op_wrong_commute(
718; CHECK-NEXT:    [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
719; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]]
720; CHECK-NEXT:    ret float [[R]]
721;
722  %s = fsub float %x, %y
723  %r = fsub reassoc nsz float %s, %y
724  ret float %r
725}
726
727; (Y + X) - Y --> X
728
729define float @fadd_fsub_common_op(float %x, float %y) {
730; CHECK-LABEL: @fadd_fsub_common_op(
731; CHECK-NEXT:    ret float [[X:%.*]]
732;
733  %a = fadd float %y, %x
734  %r = fsub reassoc nsz float %a, %y
735  ret float %r
736}
737
738; (X + Y) - Y --> X
739
740define <2 x float> @fadd_fsub_common_op_commute_vec(<2 x float> %x, <2 x float> %y) {
741; CHECK-LABEL: @fadd_fsub_common_op_commute_vec(
742; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
743;
744  %a = fadd <2 x float> %x, %y
745  %r = fsub reassoc nsz <2 x float> %a, %y
746  ret <2 x float> %r
747}
748
749; Negative test - negated operand needed.
750; Y - (Y + X) --> -X
751
752define float @fadd_fsub_common_op_wrong_commute(float %x, float %y) {
753; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute(
754; CHECK-NEXT:    [[A:%.*]] = fadd float [[Y:%.*]], [[X:%.*]]
755; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]]
756; CHECK-NEXT:    ret float [[R]]
757;
758  %a = fadd float %y, %x
759  %r = fsub reassoc nsz float %y, %a
760  ret float %r
761}
762
763; Negative test - negated operand needed.
764; Y - (X + Y) --> -X
765
766define float @fadd_fsub_common_op_wrong_commute_commute(float %x, float %y) {
767; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute_commute(
768; CHECK-NEXT:    [[A:%.*]] = fadd float [[X:%.*]], [[Y:%.*]]
769; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]]
770; CHECK-NEXT:    ret float [[R]]
771;
772  %a = fadd float %x, %y
773  %r = fsub reassoc nsz float %y, %a
774  ret float %r
775}
776
777; Y + (X - Y) --> X
778
779define <2 x float> @fsub_fadd_common_op_vec(<2 x float> %x, <2 x float> %y) {
780; CHECK-LABEL: @fsub_fadd_common_op_vec(
781; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
782;
783  %s = fsub <2 x float> %x, %y
784  %r = fadd reassoc nsz <2 x float> %y, %s
785  ret <2 x float> %r
786}
787
788; (X - Y) + Y --> X
789
790define float @fsub_fadd_common_op_commute(float %x, float %y) {
791; CHECK-LABEL: @fsub_fadd_common_op_commute(
792; CHECK-NEXT:    ret float [[X:%.*]]
793;
794  %s = fsub float %x, %y
795  %r = fadd reassoc nsz float %s, %y
796  ret float %r
797}
798
799; Negative test.
800; Y + (Y - X) --> ?
801
802define float @fsub_fadd_common_op_wrong_commute(float %x, float %y) {
803; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute(
804; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
805; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[Y]], [[S]]
806; CHECK-NEXT:    ret float [[R]]
807;
808  %s = fsub float %y, %x
809  %r = fadd reassoc nsz float %y, %s
810  ret float %r
811}
812
813; Negative test.
814; (Y - X) + Y --> ?
815
816define float @fsub_fadd_common_op_wrong_commute_commute(float %x, float %y) {
817; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute_commute(
818; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
819; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[S]], [[Y]]
820; CHECK-NEXT:    ret float [[R]]
821;
822  %s = fsub float %y, %x
823  %r = fadd reassoc nsz float %s, %y
824  ret float %r
825}
826
827; PR46627 - https://bugs.llvm.org/show_bug.cgi?id=46627
828
829define float @maxnum_with_poszero_op(float %a) {
830; CHECK-LABEL: @maxnum_with_poszero_op(
831; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 0.000000e+00)
832; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
833; CHECK-NEXT:    ret float [[FABS]]
834;
835  %max = call float @llvm.maxnum.f32(float %a, float 0.0)
836  %fabs = call float @llvm.fabs.f32(float %max)
837  ret float %fabs
838}
839
840define float @maxnum_with_poszero_op_commute(float %a) {
841; CHECK-LABEL: @maxnum_with_poszero_op_commute(
842; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]])
843; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float 0.000000e+00, float [[SQRT]])
844; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
845; CHECK-NEXT:    ret float [[FABS]]
846;
847  %sqrt = call float @llvm.sqrt.f32(float %a)
848  %max = call float @llvm.maxnum.f32(float 0.0, float %sqrt)
849  %fabs = call float @llvm.fabs.f32(float %max)
850  ret float %fabs
851}
852
853define float @maxnum_with_negzero_op(float %a) {
854; CHECK-LABEL: @maxnum_with_negzero_op(
855; CHECK-NEXT:    [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
856; CHECK-NEXT:    [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]])
857; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float -0.000000e+00, float [[FABSA]])
858; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
859; CHECK-NEXT:    ret float [[FABS]]
860;
861  %nnan = call nnan float @llvm.sqrt.f32(float %a)
862  %fabsa = call float @llvm.fabs.f32(float %nnan)
863  %max = call float @llvm.maxnum.f32(float -0.0, float %fabsa)
864  %fabs = call float @llvm.fabs.f32(float %max)
865  ret float %fabs
866}
867
868define float @maxnum_with_negzero_op_commute(float %a) {
869; CHECK-LABEL: @maxnum_with_negzero_op_commute(
870; CHECK-NEXT:    [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
871; CHECK-NEXT:    [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]])
872; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[FABSA]], float -0.000000e+00)
873; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
874; CHECK-NEXT:    ret float [[FABS]]
875;
876  %nnan = call nnan float @llvm.sqrt.f32(float %a)
877  %fabsa = call float @llvm.fabs.f32(float %nnan)
878  %max = call float @llvm.maxnum.f32(float %fabsa, float -0.0)
879  %fabs = call float @llvm.fabs.f32(float %max)
880  ret float %fabs
881}
882
883; If an operand is strictly greater than 0.0, we know the sign of the result of maxnum.
884
885define float @maxnum_with_pos_one_op(float %a) {
886; CHECK-LABEL: @maxnum_with_pos_one_op(
887; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 1.000000e+00)
888; CHECK-NEXT:    ret float [[MAX]]
889;
890  %max = call float @llvm.maxnum.f32(float %a, float 1.0)
891  %fabs = call float @llvm.fabs.f32(float %max)
892  ret float %fabs
893}
894
895define double @fadd_nnan_inf_op0(double %x) {
896; CHECK-LABEL: @fadd_nnan_inf_op0(
897; CHECK-NEXT:    ret double 0x7FF0000000000000
898;
899  %r = fadd nnan double 0x7ff0000000000000, %x
900  ret double %r
901}
902
903define double @fadd_nnan_inf_op1(double %x) {
904; CHECK-LABEL: @fadd_nnan_inf_op1(
905; CHECK-NEXT:    ret double 0x7FF0000000000000
906;
907  %r = fadd nnan double %x, 0x7ff0000000000000
908  ret double %r
909}
910
911define <2 x double> @fadd_nnan_neginf_op1(<2 x double> %x) {
912; CHECK-LABEL: @fadd_nnan_neginf_op1(
913; CHECK-NEXT:    ret <2 x double> <double 0xFFF0000000000000, double poison>
914;
915  %r = fadd nnan <2 x double> %x, <double 0xfff0000000000000, double poison>
916  ret <2 x double> %r
917}
918
919define double @fadd_nnan_neginf_op0(double %x) {
920; CHECK-LABEL: @fadd_nnan_neginf_op0(
921; CHECK-NEXT:    ret double 0xFFF0000000000000
922;
923  %r = fadd nnan double 0xfff0000000000000, %x
924  ret double %r
925}
926
927; negative test - requires nnan
928
929define double @fadd_inf_op0(double %x) {
930; CHECK-LABEL: @fadd_inf_op0(
931; CHECK-NEXT:    [[R:%.*]] = fadd double 0x7FF0000000000000, [[X:%.*]]
932; CHECK-NEXT:    ret double [[R]]
933;
934  %r = fadd double 0x7ff0000000000000, %x
935  ret double %r
936}
937
938define double @fsub_nnan_inf_op0(double %x) {
939; CHECK-LABEL: @fsub_nnan_inf_op0(
940; CHECK-NEXT:    ret double 0x7FF0000000000000
941;
942  %r = fsub nnan double 0x7ff0000000000000, %x
943  ret double %r
944}
945
946; flip sign
947
948define double @fsub_nnan_inf_op1(double %x) {
949; CHECK-LABEL: @fsub_nnan_inf_op1(
950; CHECK-NEXT:    ret double 0xFFF0000000000000
951;
952  %r = fsub nnan double %x, 0x7ff0000000000000
953  ret double %r
954}
955
956define <2 x double> @fsub_nnan_inf_op1_vec(<2 x double> %x) {
957; CHECK-LABEL: @fsub_nnan_inf_op1_vec(
958; CHECK-NEXT:    ret <2 x double> <double 0x7FF0000000000000, double poison>
959;
960  %r = fsub nnan <2 x double> %x, <double 0xfff0000000000000, double poison>
961  ret <2 x double> %r
962}
963
964define <2 x double> @fsub_nnan_neginf_op0(<2 x double> %x) {
965; CHECK-LABEL: @fsub_nnan_neginf_op0(
966; CHECK-NEXT:    ret <2 x double> <double 0xFFF0000000000000, double poison>
967;
968  %r = fsub nnan <2 x double> <double 0xfff0000000000000, double poison>, %x
969  ret <2 x double> %r
970}
971
972; flip sign
973
974define double @fsub_nnan_neginf_op1(double %x) {
975; CHECK-LABEL: @fsub_nnan_neginf_op1(
976; CHECK-NEXT:    ret double 0x7FF0000000000000
977;
978  %r = fsub nnan double %x, 0xfff0000000000000
979  ret double %r
980}
981
982; negative test - requires nnan
983
984define double @fsub_inf_op0(double %x) {
985; CHECK-LABEL: @fsub_inf_op0(
986; CHECK-NEXT:    [[R:%.*]] = fsub double 0x7FF0000000000000, [[X:%.*]]
987; CHECK-NEXT:    ret double [[R]]
988;
989  %r = fsub double 0x7ff0000000000000, %x
990  ret double %r
991}
992
993define i1 @canonicalize_known_positive(float %a) {
994; CHECK-LABEL: @canonicalize_known_positive(
995; CHECK-NEXT:    ret i1 true
996;
997  %fabs = call float @llvm.fabs.f32(float %a)
998  %known.positive = call float @llvm.canonicalize.f32(float %fabs)
999  %cmp = fcmp nnan oge float %known.positive, 0.0
1000  ret i1 %cmp
1001}
1002
1003define i1 @canonicalize_unknown_positive(float %unknown) {
1004; CHECK-LABEL: @canonicalize_unknown_positive(
1005; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[UNKNOWN:%.*]], 0.000000e+00
1006; CHECK-NEXT:    ret i1 [[CMP]]
1007;
1008  %cmp = fcmp nnan oge float %unknown, 0.0
1009  ret i1 %cmp
1010}
1011
1012define i1 @arithmetic_fence_known_positive(float %a) {
1013; CHECK-LABEL: @arithmetic_fence_known_positive(
1014; CHECK-NEXT:    ret i1 true
1015;
1016  %fabs = call float @llvm.fabs.f32(float %a)
1017  %known.positive = call float @llvm.arithmetic.fence.f32(float %fabs)
1018  %cmp = fcmp nnan oge float %known.positive, 0.0
1019  ret i1 %cmp
1020}
1021
1022define i1 @arithmetic_fence_unknown_positive(float %unknown) {
1023; CHECK-LABEL: @arithmetic_fence_unknown_positive(
1024; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[UNKNOWN:%.*]])
1025; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[KNOWN_POSITIVE]], 0.000000e+00
1026; CHECK-NEXT:    ret i1 [[CMP]]
1027;
1028  %known.positive = call float @llvm.arithmetic.fence.f32(float %unknown)
1029  %cmp = fcmp nnan oge float %known.positive, 0.0
1030  ret i1 %cmp
1031}
1032
1033define i1 @copysign_known_positive_maybe_neg0(float %unknown, float %sign) {
1034; CHECK-LABEL: @copysign_known_positive_maybe_neg0(
1035; CHECK-NEXT:    [[SQRT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float [[SIGN:%.*]])
1036; CHECK-NEXT:    [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[UNKNOWN:%.*]], float [[SQRT]])
1037; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[COPYSIGN]], 0.000000e+00
1038; CHECK-NEXT:    ret i1 [[CMP]]
1039;
1040  %sqrt = call ninf nnan float @llvm.sqrt.f32(float %sign)
1041  %copysign = call float @llvm.copysign.f32(float %unknown, float %sqrt)
1042  %cmp = fcmp nnan oge float %copysign, 0.0
1043  ret i1 %cmp
1044}
1045
1046define i1 @copysign_known_positive(float %unknown, float %sign) {
1047; CHECK-LABEL: @copysign_known_positive(
1048; CHECK-NEXT:    ret i1 true
1049;
1050  %sqrt = call ninf nnan nsz float @llvm.sqrt.f32(float %sign)
1051  %copysign = call float @llvm.copysign.f32(float %unknown, float %sqrt)
1052  %cmp = fcmp nnan oge float %copysign, 0.0
1053  ret i1 %cmp
1054}
1055
1056define i1 @copysign_unknown_positive(float %unknown, float %unknown.sign) {
1057; CHECK-LABEL: @copysign_unknown_positive(
1058; CHECK-NEXT:    [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[UNKNOWN:%.*]], float [[UNKNOWN_SIGN:%.*]])
1059; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[COPYSIGN]], 0.000000e+00
1060; CHECK-NEXT:    ret i1 [[CMP]]
1061;
1062  %copysign = call float @llvm.copysign.f32(float %unknown, float %unknown.sign)
1063  %cmp = fcmp nnan oge float %copysign, 0.0
1064  ret i1 %cmp
1065}
1066
1067; https://alive2.llvm.org/ce/z/Y-EyY3
1068define i1 @floor_known_positive(float %a) {
1069; CHECK-LABEL: @floor_known_positive(
1070; CHECK-NEXT:    ret i1 true
1071;
1072  %fabs = call float @llvm.fabs.f32(float %a)
1073  %known.positive = call float @llvm.floor.f32(float %fabs)
1074  %cmp = fcmp nnan oge float %known.positive, 0.0
1075  ret i1 %cmp
1076}
1077
1078define i1 @floor_unknown_positive(float %unknown) {
1079; CHECK-LABEL: @floor_unknown_positive(
1080; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.floor.f32(float [[UNKNOWN:%.*]])
1081; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
1082; CHECK-NEXT:    ret i1 [[CMP]]
1083;
1084  %op = call float @llvm.floor.f32(float %unknown)
1085  %cmp = fcmp nnan oge float %op, 0.0
1086  ret i1 %cmp
1087}
1088
1089; https://alive2.llvm.org/ce/z/3tBUoW
1090define i1 @ceil_known_positive(float %a) {
1091; CHECK-LABEL: @ceil_known_positive(
1092; CHECK-NEXT:    ret i1 true
1093;
1094  %fabs = call float @llvm.fabs.f32(float %a)
1095  %known.positive = call float @llvm.ceil.f32(float %fabs)
1096  %cmp = fcmp nnan oge float %known.positive, 0.0
1097  ret i1 %cmp
1098}
1099
1100define i1 @ceil_unknown_positive(float %unknown) {
1101; CHECK-LABEL: @ceil_unknown_positive(
1102; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.ceil.f32(float [[UNKNOWN:%.*]])
1103; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
1104; CHECK-NEXT:    ret i1 [[CMP]]
1105;
1106
1107  %op = call float @llvm.ceil.f32(float %unknown)
1108  %cmp = fcmp nnan oge float %op, 0.0
1109  ret i1 %cmp
1110}
1111
1112; https://alive2.llvm.org/ce/z/RbyJPX
1113define i1 @trunc_known_positive(float %a) {
1114; CHECK-LABEL: @trunc_known_positive(
1115; CHECK-NEXT:    ret i1 true
1116;
1117  %fabs = call float @llvm.fabs.f32(float %a)
1118  %known.positive = call float @llvm.trunc.f32(float %fabs)
1119  %cmp = fcmp nnan oge float %known.positive, 0.0
1120  ret i1 %cmp
1121}
1122
1123define i1 @trunc_unknown_positive(float %unknown) {
1124; CHECK-LABEL: @trunc_unknown_positive(
1125; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.trunc.f32(float [[UNKNOWN:%.*]])
1126; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
1127; CHECK-NEXT:    ret i1 [[CMP]]
1128;
1129  %op = call float @llvm.trunc.f32(float %unknown)
1130  %cmp = fcmp nnan oge float %op, 0.0
1131  ret i1 %cmp
1132}
1133
1134; https://alive2.llvm.org/ce/z/bjC2Jm
1135define i1 @rint_known_positive(float %a) {
1136; CHECK-LABEL: @rint_known_positive(
1137; CHECK-NEXT:    ret i1 true
1138;
1139  %fabs = call float @llvm.fabs.f32(float %a)
1140  %known.positive = call float @llvm.rint.f32(float %fabs)
1141  %cmp = fcmp nnan oge float %known.positive, 0.0
1142  ret i1 %cmp
1143}
1144
1145define i1 @rint_unknown_positive(float %unknown) {
1146; CHECK-LABEL: @rint_unknown_positive(
1147; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.rint.f32(float [[UNKNOWN:%.*]])
1148; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
1149; CHECK-NEXT:    ret i1 [[CMP]]
1150;
1151  %op = call float @llvm.rint.f32(float %unknown)
1152  %cmp = fcmp nnan oge float %op, 0.0
1153  ret i1 %cmp
1154}
1155
1156; https://alive2.llvm.org/ce/z/dFiL9n
1157define i1 @nearbyint_known_positive(float %a) {
1158; CHECK-LABEL: @nearbyint_known_positive(
1159; CHECK-NEXT:    ret i1 true
1160;
1161  %fabs = call float @llvm.fabs.f32(float %a)
1162  %known.positive = call float @llvm.nearbyint.f32(float %fabs)
1163  %cmp = fcmp nnan oge float %known.positive, 0.0
1164  ret i1 %cmp
1165}
1166
1167define i1 @nearbyint_unknown_positive(float %unknown) {
1168; CHECK-LABEL: @nearbyint_unknown_positive(
1169; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.nearbyint.f32(float [[UNKNOWN:%.*]])
1170; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
1171; CHECK-NEXT:    ret i1 [[CMP]]
1172;
1173  %op = call float @llvm.nearbyint.f32(float %unknown)
1174  %cmp = fcmp nnan oge float %op, 0.0
1175  ret i1 %cmp
1176}
1177
1178; https://alive2.llvm.org/ce/z/kPhS-d
1179define i1 @round_known_positive(float %a) {
1180; CHECK-LABEL: @round_known_positive(
1181; CHECK-NEXT:    ret i1 true
1182;
1183  %fabs = call float @llvm.fabs.f32(float %a)
1184  %known.positive = call float @llvm.round.f32(float %fabs)
1185  %cmp = fcmp nnan oge float %known.positive, 0.0
1186  ret i1 %cmp
1187}
1188
1189define i1 @round_unknown_positive(float %unknown) {
1190; CHECK-LABEL: @round_unknown_positive(
1191; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.round.f32(float [[UNKNOWN:%.*]])
1192; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
1193; CHECK-NEXT:    ret i1 [[CMP]]
1194;
1195  %op = call float @llvm.round.f32(float %unknown)
1196  %cmp = fcmp nnan oge float %op, 0.0
1197  ret i1 %cmp
1198}
1199
1200; https://alive2.llvm.org/ce/z/Z_tfsu
1201define i1 @roundeven_known_positive(float %a) {
1202; CHECK-LABEL: @roundeven_known_positive(
1203; CHECK-NEXT:    ret i1 true
1204;
1205  %fabs = call float @llvm.fabs.f32(float %a)
1206  %known.positive = call float @llvm.roundeven.f32(float %fabs)
1207  %cmp = fcmp nnan oge float %known.positive, 0.0
1208  ret i1 %cmp
1209}
1210
1211define i1 @roundeven_unknown_positive(float %unknown) {
1212; CHECK-LABEL: @roundeven_unknown_positive(
1213; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.roundeven.f32(float [[UNKNOWN:%.*]])
1214; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
1215; CHECK-NEXT:    ret i1 [[CMP]]
1216;
1217  %op = call float @llvm.roundeven.f32(float %unknown)
1218  %cmp = fcmp nnan oge float %op, 0.0
1219  ret i1 %cmp
1220}
1221
1222define i1 @fptrunc_round_known_positive(double %a) {
1223; CHECK-LABEL: @fptrunc_round_known_positive(
1224; CHECK-NEXT:    ret i1 true
1225;
1226  %fabs = call double @llvm.fabs.f64(double %a)
1227  %known.positive = call float @llvm.fptrunc.round.f32.f64(double %fabs, metadata !"round.downward")
1228  %cmp = fcmp nnan oge float %known.positive, 0.0
1229  ret i1 %cmp
1230}
1231
1232define i1 @fptrunc_round_unknown_positive(double %unknown) {
1233; CHECK-LABEL: @fptrunc_round_unknown_positive(
1234; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.fptrunc.round.f32.f64(double [[UNKNOWN:%.*]], metadata !"round.downward")
1235; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
1236; CHECK-NEXT:    ret i1 [[CMP]]
1237;
1238  %op = call float @llvm.fptrunc.round.f32.f64(double %unknown, metadata !"round.downward")
1239  %cmp = fcmp nnan oge float %op, 0.0
1240  ret i1 %cmp
1241}
1242