[RISCV] Change func to funct in RISCVInstrInfoXqci.td. NFC (#119669)
[llvm-project.git] / llvm / test / Transforms / InstSimplify / floating-point-arithmetic.ll
blobd3178a103d42cda07b847acf7ee1bd838e55730a
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
4 ; fneg (fneg X) ==> X
5 define float @fneg_fneg_var(float %a) {
6 ; CHECK-LABEL: @fneg_fneg_var(
7 ; CHECK-NEXT:    ret float [[A:%.*]]
9   %r  = fneg float %a
10   %r1 = fneg float %r
11   ret float %r1
14 ; fneg (fsub -0.0, X) ==> X
15 define float @fsub_-0_x(float %a) {
16 ; CHECK-LABEL: @fsub_-0_x(
17 ; CHECK-NEXT:    ret float [[A:%.*]]
19   %t1 = fsub float -0.0, %a
20   %ret = fneg float %t1
21   ret float %ret
24 define <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:%.*]]
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
33 define <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:%.*]]
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
42 define <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:%.*]]
46   %r = fsub nsz <2 x float> %x, <float poison, float -0.0>
47   ret <2 x float> %r
50 ; fsub -0.0, (fsub -0.0, X) ==> X
51 define float @fsub_-0_-0_x(float %a) {
52 ; CHECK-LABEL: @fsub_-0_-0_x(
53 ; CHECK-NEXT:    ret float [[A:%.*]]
55   %t1 = fsub float -0.0, %a
56   %ret = fsub float -0.0, %t1
57   ret float %ret
60 ; fsub -0.0, (fneg X) ==> X
61 define float @fneg_x(float %a) {
62 ; CHECK-LABEL: @fneg_x(
63 ; CHECK-NEXT:    ret float [[A:%.*]]
65   %t1 = fneg float %a
66   %ret = fsub float -0.0, %t1
67   ret float %ret
70 define <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:%.*]]
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
79 define <2 x float> @fneg_x_vec(<2 x float> %a) {
80 ; CHECK-LABEL: @fneg_x_vec(
81 ; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
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
88 define <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:%.*]]
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
97 define <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:%.*]]
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
106 ; fsub -0.0, (fsub 0.0, X) != X
107 define 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]]
113   %t1 = fsub float 0.0, %a
114   %ret = fsub float -0.0, %t1
115   ret float %ret
118 ; fsub 0.0, (fsub -0.0, X) != X
119 define 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]]
125   %t1 = fsub float -0.0, %a
126   %ret = fsub float 0.0, %t1
127   ret float %ret
130 ; fsub X, 0 ==> X
131 define float @fsub_x_0(float %x) {
132 ; CHECK-LABEL: @fsub_x_0(
133 ; CHECK-NEXT:    ret float [[X:%.*]]
135   %r = fsub float %x, 0.0
136   ret float %r
139 define <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:%.*]]
143   %r = fsub <2 x float> %x, <float poison, float 0.0>
144   ret <2 x float> %r
147 ; fadd X, -0 ==> X
148 define float @fadd_x_n0(float %a) {
149 ; CHECK-LABEL: @fadd_x_n0(
150 ; CHECK-NEXT:    ret float [[A:%.*]]
152   %ret = fadd float %a, -0.0
153   ret float %ret
156 define <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:%.*]]
160   %ret = fadd <2 x float> %a, <float -0.0, float poison>
161   ret <2 x float> %ret
164 ; fmul X, 1.0 ==> X
165 define double @fmul_X_1(double %a) {
166 ; CHECK-LABEL: @fmul_X_1(
167 ; CHECK-NEXT:    ret double [[A:%.*]]
169   %b = fmul double 1.0, %a
170   ret double %b
173 define half @fmul_nnan_ninf_nneg_0.0(i15 %x) {
174 ; CHECK-LABEL: @fmul_nnan_ninf_nneg_0.0(
175 ; CHECK-NEXT:    ret half 0xH0000
177   %f = uitofp i15 %x to half
178   %r = fmul half %f, 0.0
179   ret half %r
182 define half @fmul_nnan_ninf_nneg_n0.0(i15 %x) {
183 ; CHECK-LABEL: @fmul_nnan_ninf_nneg_n0.0(
184 ; CHECK-NEXT:    ret half 0xH8000
186   %f = uitofp i15 %x to half
187   %r = fmul half %f, -0.0
188   ret half %r
191 ; negative test - the int could be big enough to round to INF
193 define 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]]
199   %f = uitofp i16 %x to half
200   %r = fmul half %f, 0.0
201   ret half %r
204 define 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
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
214 define 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
218   %r = fmul float %f, -0.0
219   ret float %r
222 define <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)
226   %r = fmul <2 x float> <float 0.0, float 0.0>, %f
227   ret <2 x float> %r
230 define <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>
234   %r = fmul <2 x float> <float -0.0, float 0.0>, %f
235   ret <2 x float> %r
239 define 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]]
244   %r = call float @llvm.fmuladd.f32(float %f, float 0.0, float %add)
245   ret float %r
248 define 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]]
253   %r = call float @llvm.fma.f32(float -0.0, float %f, float %add)
254   ret float %r
258 ; Make sure we can infer %x can't be 0 based on assumes.
259 define { 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 }
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
276 ; negative test - the int could be big enough to round to INF
278 define 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]]
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
291 ; PR2642
292 define <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:%.*]]
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
300 ; fdiv X, 1.0 ==> X
301 define float @fdiv_x_1(float %a) {
302 ; CHECK-LABEL: @fdiv_x_1(
303 ; CHECK-NEXT:    ret float [[A:%.*]]
305   %ret = fdiv float %a, 1.0
306   ret float %ret
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.
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.
318 declare float @sqrtf(float)
320 define 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]]
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
341 declare float @llvm.fabs.f32(float)
342 declare double @llvm.fabs.f64(double)
343 declare float @llvm.canonicalize.f32(float)
344 declare float @llvm.floor.f32(float)
345 declare float @llvm.ceil.f32(float)
346 declare float @llvm.trunc.f32(float)
347 declare float @llvm.rint.f32(float)
348 declare float @llvm.nearbyint.f32(float)
349 declare float @llvm.round.f32(float)
350 declare float @llvm.roundeven.f32(float)
351 declare float @llvm.fptrunc.round.f32.f64(double, metadata)
352 declare float @llvm.arithmetic.fence.f32(float)
353 declare float @llvm.copysign.f32(float, float)
354 declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
355 declare float @llvm.sqrt.f32(float)
356 declare float @llvm.maxnum.f32(float, float)
357 declare void @llvm.assume(i1 noundef)
360 define 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]]
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
372 define <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]]
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
384 define 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]]
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
397 define <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]]
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
410 define 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]]
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
423 define <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]]
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
436 define 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]]
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
449 define <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]]
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
462 define 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]]
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
474 define <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]]
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
486 define 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]]
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
499 define <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]]
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
512 define 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]]
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
525 define <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]]
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
538 define 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]]
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
551 define <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]]
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
564 define 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]]
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
577 define <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]]
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
590 ; The fabs can't be eliminated because llvm.sqrt.f32 may return -0 or NaN with
591 ; an arbitrary sign bit.
592 define 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]]
598   %sqrt = call float @llvm.sqrt.f32(float %a)
599   %fabs = call float @llvm.fabs.f32(float %sqrt)
600   ret float %fabs
603 ; The fabs can't be eliminated because the nnan sqrt may still return -0.
604 define 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]]
610   %sqrt = call nnan float @llvm.sqrt.f32(float %a)
611   %fabs = call float @llvm.fabs.f32(float %sqrt)
612   ret float %fabs
615 ; The fabs can't be eliminated because the nsz sqrt may still return NaN.
616 define 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]]
622   %sqrt = call nsz float @llvm.sqrt.f32(float %a)
623   %fabs = call float @llvm.fabs.f32(float %sqrt)
624   ret float %fabs
627 ; The fabs can be eliminated because we're nsz and nnan.
628 define 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]]
633   %sqrt = call nnan nsz float @llvm.sqrt.f32(float %a)
634   %fabs = call float @llvm.fabs.f32(float %sqrt)
635   ret float %fabs
638 ; The second fabs can be eliminated because the operand to sqrt cannot be -0.
639 define 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]]
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
651 define 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]]
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
665 ; Y - (Y - X) --> X
667 define float @fsub_fsub_common_op(float %x, float %y) {
668 ; CHECK-LABEL: @fsub_fsub_common_op(
669 ; CHECK-NEXT:    ret float [[X:%.*]]
671   %s = fsub float %y, %x
672   %r = fsub reassoc nsz float %y, %s
673   ret float %r
676 define <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:%.*]]
680   %s = fsub <2 x float> %y, %x
681   %r = fsub reassoc nsz <2 x float> %y, %s
682   ret <2 x float> %r
685 ; Negative test - fsub is not commutative.
686 ; Y - (X - Y) --> (Y - X) + Y (canonicalized)
688 define 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]]
694   %s = fsub float %x, %y
695   %r = fsub reassoc nsz float %y, %s
696   ret float %r
699 ; Negative test - negated operand needed.
700 ; (Y - X) - Y --> -X
702 define 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]]
708   %s = fsub float %y, %x
709   %r = fsub reassoc nsz float %s, %y
710   ret float %r
713 ; Negative test - fsub is not commutative.
714 ; (X - Y) - Y --> ?
716 define 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]]
722   %s = fsub float %x, %y
723   %r = fsub reassoc nsz float %s, %y
724   ret float %r
727 ; (Y + X) - Y --> X
729 define float @fadd_fsub_common_op(float %x, float %y) {
730 ; CHECK-LABEL: @fadd_fsub_common_op(
731 ; CHECK-NEXT:    ret float [[X:%.*]]
733   %a = fadd float %y, %x
734   %r = fsub reassoc nsz float %a, %y
735   ret float %r
738 ; (X + Y) - Y --> X
740 define <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:%.*]]
744   %a = fadd <2 x float> %x, %y
745   %r = fsub reassoc nsz <2 x float> %a, %y
746   ret <2 x float> %r
749 ; Negative test - negated operand needed.
750 ; Y - (Y + X) --> -X
752 define 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]]
758   %a = fadd float %y, %x
759   %r = fsub reassoc nsz float %y, %a
760   ret float %r
763 ; Negative test - negated operand needed.
764 ; Y - (X + Y) --> -X
766 define 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]]
772   %a = fadd float %x, %y
773   %r = fsub reassoc nsz float %y, %a
774   ret float %r
777 ; Y + (X - Y) --> X
779 define <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:%.*]]
783   %s = fsub <2 x float> %x, %y
784   %r = fadd reassoc nsz <2 x float> %y, %s
785   ret <2 x float> %r
788 ; (X - Y) + Y --> X
790 define float @fsub_fadd_common_op_commute(float %x, float %y) {
791 ; CHECK-LABEL: @fsub_fadd_common_op_commute(
792 ; CHECK-NEXT:    ret float [[X:%.*]]
794   %s = fsub float %x, %y
795   %r = fadd reassoc nsz float %s, %y
796   ret float %r
799 ; Negative test.
800 ; Y + (Y - X) --> ?
802 define 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]]
808   %s = fsub float %y, %x
809   %r = fadd reassoc nsz float %y, %s
810   ret float %r
813 ; Negative test.
814 ; (Y - X) + Y --> ?
816 define 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]]
822   %s = fsub float %y, %x
823   %r = fadd reassoc nsz float %s, %y
824   ret float %r
827 ; PR46627 - https://bugs.llvm.org/show_bug.cgi?id=46627
829 define 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]]
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
840 define 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]]
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
853 define 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]]
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
868 define 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]]
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
883 ; If an operand is strictly greater than 0.0, we know the sign of the result of maxnum.
885 define 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]]
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
895 define double @fadd_nnan_inf_op0(double %x) {
896 ; CHECK-LABEL: @fadd_nnan_inf_op0(
897 ; CHECK-NEXT:    ret double 0x7FF0000000000000
899   %r = fadd nnan double 0x7ff0000000000000, %x
900   ret double %r
903 define double @fadd_nnan_inf_op1(double %x) {
904 ; CHECK-LABEL: @fadd_nnan_inf_op1(
905 ; CHECK-NEXT:    ret double 0x7FF0000000000000
907   %r = fadd nnan double %x, 0x7ff0000000000000
908   ret double %r
911 define <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>
915   %r = fadd nnan <2 x double> %x, <double 0xfff0000000000000, double poison>
916   ret <2 x double> %r
919 define double @fadd_nnan_neginf_op0(double %x) {
920 ; CHECK-LABEL: @fadd_nnan_neginf_op0(
921 ; CHECK-NEXT:    ret double 0xFFF0000000000000
923   %r = fadd nnan double 0xfff0000000000000, %x
924   ret double %r
927 ; negative test - requires nnan
929 define 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]]
934   %r = fadd double 0x7ff0000000000000, %x
935   ret double %r
938 define double @fsub_nnan_inf_op0(double %x) {
939 ; CHECK-LABEL: @fsub_nnan_inf_op0(
940 ; CHECK-NEXT:    ret double 0x7FF0000000000000
942   %r = fsub nnan double 0x7ff0000000000000, %x
943   ret double %r
946 ; flip sign
948 define double @fsub_nnan_inf_op1(double %x) {
949 ; CHECK-LABEL: @fsub_nnan_inf_op1(
950 ; CHECK-NEXT:    ret double 0xFFF0000000000000
952   %r = fsub nnan double %x, 0x7ff0000000000000
953   ret double %r
956 define <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>
960   %r = fsub nnan <2 x double> %x, <double 0xfff0000000000000, double poison>
961   ret <2 x double> %r
964 define <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>
968   %r = fsub nnan <2 x double> <double 0xfff0000000000000, double poison>, %x
969   ret <2 x double> %r
972 ; flip sign
974 define double @fsub_nnan_neginf_op1(double %x) {
975 ; CHECK-LABEL: @fsub_nnan_neginf_op1(
976 ; CHECK-NEXT:    ret double 0x7FF0000000000000
978   %r = fsub nnan double %x, 0xfff0000000000000
979   ret double %r
982 ; negative test - requires nnan
984 define 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]]
989   %r = fsub double 0x7ff0000000000000, %x
990   ret double %r
993 define i1 @canonicalize_known_positive(float %a) {
994 ; CHECK-LABEL: @canonicalize_known_positive(
995 ; CHECK-NEXT:    ret i1 true
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
1003 define 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]]
1008   %cmp = fcmp nnan oge float %unknown, 0.0
1009   ret i1 %cmp
1012 define i1 @arithmetic_fence_known_positive(float %a) {
1013 ; CHECK-LABEL: @arithmetic_fence_known_positive(
1014 ; CHECK-NEXT:    ret i1 true
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
1022 define 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]]
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
1033 define 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]]
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
1046 define i1 @copysign_known_positive(float %unknown, float %sign) {
1047 ; CHECK-LABEL: @copysign_known_positive(
1048 ; CHECK-NEXT:    ret i1 true
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
1056 define 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]]
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
1067 ; https://alive2.llvm.org/ce/z/Y-EyY3
1068 define i1 @floor_known_positive(float %a) {
1069 ; CHECK-LABEL: @floor_known_positive(
1070 ; CHECK-NEXT:    ret i1 true
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
1078 define 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]]
1084   %op = call float @llvm.floor.f32(float %unknown)
1085   %cmp = fcmp nnan oge float %op, 0.0
1086   ret i1 %cmp
1089 ; https://alive2.llvm.org/ce/z/3tBUoW
1090 define i1 @ceil_known_positive(float %a) {
1091 ; CHECK-LABEL: @ceil_known_positive(
1092 ; CHECK-NEXT:    ret i1 true
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
1100 define 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]]
1107   %op = call float @llvm.ceil.f32(float %unknown)
1108   %cmp = fcmp nnan oge float %op, 0.0
1109   ret i1 %cmp
1112 ; https://alive2.llvm.org/ce/z/RbyJPX
1113 define i1 @trunc_known_positive(float %a) {
1114 ; CHECK-LABEL: @trunc_known_positive(
1115 ; CHECK-NEXT:    ret i1 true
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
1123 define 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]]
1129   %op = call float @llvm.trunc.f32(float %unknown)
1130   %cmp = fcmp nnan oge float %op, 0.0
1131   ret i1 %cmp
1134 ; https://alive2.llvm.org/ce/z/bjC2Jm
1135 define i1 @rint_known_positive(float %a) {
1136 ; CHECK-LABEL: @rint_known_positive(
1137 ; CHECK-NEXT:    ret i1 true
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
1145 define 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]]
1151   %op = call float @llvm.rint.f32(float %unknown)
1152   %cmp = fcmp nnan oge float %op, 0.0
1153   ret i1 %cmp
1156 ; https://alive2.llvm.org/ce/z/dFiL9n
1157 define i1 @nearbyint_known_positive(float %a) {
1158 ; CHECK-LABEL: @nearbyint_known_positive(
1159 ; CHECK-NEXT:    ret i1 true
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
1167 define 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]]
1173   %op = call float @llvm.nearbyint.f32(float %unknown)
1174   %cmp = fcmp nnan oge float %op, 0.0
1175   ret i1 %cmp
1178 ; https://alive2.llvm.org/ce/z/kPhS-d
1179 define i1 @round_known_positive(float %a) {
1180 ; CHECK-LABEL: @round_known_positive(
1181 ; CHECK-NEXT:    ret i1 true
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
1189 define 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]]
1195   %op = call float @llvm.round.f32(float %unknown)
1196   %cmp = fcmp nnan oge float %op, 0.0
1197   ret i1 %cmp
1200 ; https://alive2.llvm.org/ce/z/Z_tfsu
1201 define i1 @roundeven_known_positive(float %a) {
1202 ; CHECK-LABEL: @roundeven_known_positive(
1203 ; CHECK-NEXT:    ret i1 true
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
1211 define 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]]
1217   %op = call float @llvm.roundeven.f32(float %unknown)
1218   %cmp = fcmp nnan oge float %op, 0.0
1219   ret i1 %cmp
1222 define i1 @fptrunc_round_known_positive(double %a) {
1223 ; CHECK-LABEL: @fptrunc_round_known_positive(
1224 ; CHECK-NEXT:    ret i1 true
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
1232 define 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]]
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