Follow up to d0858bffa11, add missing REQUIRES x86
[llvm-project.git] / llvm / test / Transforms / InstSimplify / floating-point-arithmetic.ll
blobb8244b1d508c629ea4bdd3f5e5c664c77db22de9
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_undef_elts(<2 x float> %a) {
34 ; CHECK-LABEL: @fsub_-0_x_vec_undef_elts(
35 ; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
37   %t1 = fsub <2 x float> <float -0.0, float undef>, %a
38   %ret = fneg <2 x float> %t1
39   ret <2 x float> %ret
42 define <2 x float> @fsub_negzero_vec_undef_elts(<2 x float> %x) {
43 ; CHECK-LABEL: @fsub_negzero_vec_undef_elts(
44 ; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
46   %r = fsub nsz <2 x float> %x, <float undef, 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_undef_elts(<2 x float> %a) {
89 ; CHECK-LABEL: @fsub_-0_-0_x_vec_undef_elts(
90 ; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
92   %t1 = fsub <2 x float> <float undef, float -0.0>, %a
93   %ret = fsub <2 x float> <float -0.0, float undef>, %t1
94   ret <2 x float> %ret
97 define <2 x float> @fneg_x_vec_undef_elts(<2 x float> %a) {
98 ; CHECK-LABEL: @fneg_x_vec_undef_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 undef>, %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_undef(<2 x float> %x) {
140 ; CHECK-LABEL: @fsub_x_0_vec_undef(
141 ; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
143   %r = fsub <2 x float> %x, <float undef, 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_undef_elt(<2 x float> %a) {
157 ; CHECK-LABEL: @fadd_x_n0_vec_undef_elt(
158 ; CHECK-NEXT:    ret <2 x float> [[A:%.*]]
160   %ret = fadd <2 x float> %a, <float -0.0, float undef>
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 ; Make sure we can infer %x can't be 0 based on assumes.
215 define { float, float } @test_fmul_0_assumed_finite(float %x) {
216 ; CHECK-LABEL: @test_fmul_0_assumed_finite(
217 ; CHECK-NEXT:    [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
218 ; CHECK-NEXT:    [[IS_FINITE_X:%.*]] = fcmp one float [[FABS_X]], 0x7FF0000000000000
219 ; CHECK-NEXT:    call void @llvm.assume(i1 [[IS_FINITE_X]])
220 ; CHECK-NEXT:    ret { float, float } { float 0.000000e+00, float -0.000000e+00 }
222   %fabs.x = call float @llvm.fabs.f32(float %x)
223   %is.finite.x = fcmp one float %fabs.x, 0x7FF0000000000000
224   call void @llvm.assume(i1 %is.finite.x)
225   %mul.0 = fmul float %fabs.x, 0.0
226   %mul.neg0 = fmul float %fabs.x, -0.0
227   %ins.0 = insertvalue { float, float } poison, float %mul.0, 0
228   %ins.1 = insertvalue { float, float } %ins.0, float %mul.neg0, 1
229   ret { float, float } %ins.1
232 ; negative test - the int could be big enough to round to INF
234 define double @fmul_nnan_ninf_nneg_0.0_commute(i128 %x) {
235 ; CHECK-LABEL: @fmul_nnan_ninf_nneg_0.0_commute(
236 ; CHECK-NEXT:    [[F:%.*]] = uitofp i128 [[X:%.*]] to float
237 ; CHECK-NEXT:    [[E:%.*]] = fpext float [[F]] to double
238 ; CHECK-NEXT:    [[R:%.*]] = fmul double 0.000000e+00, [[E]]
239 ; CHECK-NEXT:    ret double [[R]]
241   %f = uitofp i128 %x to float
242   %e = fpext float %f to double
243   %r = fmul double 0.0, %e
244   ret double %r
247 ; PR2642
248 define <4 x float> @fmul_X_1_vec(<4 x float> %x) {
249 ; CHECK-LABEL: @fmul_X_1_vec(
250 ; CHECK-NEXT:    ret <4 x float> [[X:%.*]]
252   %m = fmul <4 x float> %x, <float 1.0, float 1.0, float 1.0, float 1.0>
253   ret <4 x float> %m
256 ; fdiv X, 1.0 ==> X
257 define float @fdiv_x_1(float %a) {
258 ; CHECK-LABEL: @fdiv_x_1(
259 ; CHECK-NEXT:    ret float [[A:%.*]]
261   %ret = fdiv float %a, 1.0
262   ret float %ret
265 ; We can't optimize away the fadd in this test because the input
266 ; value to the function and subsequently to the fadd may be -0.0.
267 ; In that one special case, the result of the fadd should be +0.0
268 ; rather than the first parameter of the fadd.
270 ; Fragile test warning: We need 6 sqrt calls to trigger the bug
271 ; because the internal logic has a magic recursion limit of 6.
272 ; This is presented without any explanation or ability to customize.
274 declare float @sqrtf(float)
276 define float @PR22688(float %x) {
277 ; CHECK-LABEL: @PR22688(
278 ; CHECK-NEXT:    [[TMP1:%.*]] = call float @sqrtf(float [[X:%.*]])
279 ; CHECK-NEXT:    [[TMP2:%.*]] = call float @sqrtf(float [[TMP1]])
280 ; CHECK-NEXT:    [[TMP3:%.*]] = call float @sqrtf(float [[TMP2]])
281 ; CHECK-NEXT:    [[TMP4:%.*]] = call float @sqrtf(float [[TMP3]])
282 ; CHECK-NEXT:    [[TMP5:%.*]] = call float @sqrtf(float [[TMP4]])
283 ; CHECK-NEXT:    [[TMP6:%.*]] = call float @sqrtf(float [[TMP5]])
284 ; CHECK-NEXT:    [[TMP7:%.*]] = fadd float [[TMP6]], 0.000000e+00
285 ; CHECK-NEXT:    ret float [[TMP7]]
287   %1 = call float @sqrtf(float %x)
288   %2 = call float @sqrtf(float %1)
289   %3 = call float @sqrtf(float %2)
290   %4 = call float @sqrtf(float %3)
291   %5 = call float @sqrtf(float %4)
292   %6 = call float @sqrtf(float %5)
293   %7 = fadd float %6, 0.0
294   ret float %7
297 declare float @llvm.fabs.f32(float)
298 declare double @llvm.fabs.f64(double)
299 declare float @llvm.canonicalize.f32(float)
300 declare float @llvm.floor.f32(float)
301 declare float @llvm.ceil.f32(float)
302 declare float @llvm.trunc.f32(float)
303 declare float @llvm.rint.f32(float)
304 declare float @llvm.nearbyint.f32(float)
305 declare float @llvm.round.f32(float)
306 declare float @llvm.roundeven.f32(float)
307 declare float @llvm.fptrunc.round.f32.f64(double, metadata)
308 declare float @llvm.arithmetic.fence.f32(float)
309 declare float @llvm.copysign.f32(float, float)
310 declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
311 declare float @llvm.sqrt.f32(float)
312 declare float @llvm.maxnum.f32(float, float)
313 declare void @llvm.assume(i1 noundef)
316 define float @fabs_select_positive_constants(i32 %c) {
317 ; CHECK-LABEL: @fabs_select_positive_constants(
318 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
319 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float 2.000000e+00
320 ; CHECK-NEXT:    ret float [[SELECT]]
322   %cmp = icmp eq i32 %c, 0
323   %select = select i1 %cmp, float 1.0, float 2.0
324   %fabs = call float @llvm.fabs.f32(float %select)
325   ret float %fabs
328 define <2 x float> @fabs_select_positive_constants_vector(i32 %c) {
329 ; CHECK-LABEL: @fabs_select_positive_constants_vector(
330 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
331 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> <float 2.000000e+00, float 2.000000e+00>
332 ; CHECK-NEXT:    ret <2 x float> [[SELECT]]
334   %cmp = icmp eq i32 %c, 0
335   %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0>
336   %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
337   ret <2 x float> %fabs
340 define float @fabs_select_constant_variable(i32 %c, float %x) {
341 ; CHECK-LABEL: @fabs_select_constant_variable(
342 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
343 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 1.000000e+00, float [[X:%.*]]
344 ; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
345 ; CHECK-NEXT:    ret float [[FABS]]
347   %cmp = icmp eq i32 %c, 0
348   %select = select i1 %cmp, float 1.0, float %x
349   %fabs = call float @llvm.fabs.f32(float %select)
350   ret float %fabs
353 define <2 x float> @fabs_select_constant_variable_vector(i32 %c, <2 x float> %x) {
354 ; CHECK-LABEL: @fabs_select_constant_variable_vector(
355 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
356 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> [[X:%.*]]
357 ; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
358 ; CHECK-NEXT:    ret <2 x float> [[FABS]]
360   %cmp = icmp eq i32 %c, 0
361   %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> %x
362   %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
363   ret <2 x float> %fabs
366 define float @fabs_select_neg0_pos0(i32 %c) {
367 ; CHECK-LABEL: @fabs_select_neg0_pos0(
368 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
369 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float 0.000000e+00
370 ; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
371 ; CHECK-NEXT:    ret float [[FABS]]
373   %cmp = icmp eq i32 %c, 0
374   %select = select i1 %cmp, float -0.0, float 0.0
375   %fabs = call float @llvm.fabs.f32(float %select)
376   ret float %fabs
379 define <2 x float> @fabs_select_neg0_pos0_vector(i32 %c) {
380 ; CHECK-LABEL: @fabs_select_neg0_pos0_vector(
381 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
382 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> zeroinitializer
383 ; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
384 ; CHECK-NEXT:    ret <2 x float> [[FABS]]
386   %cmp = icmp eq i32 %c, 0
387   %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float 0.0, float 0.0>
388   %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
389   ret <2 x float> %fabs
392 define float @fabs_select_neg0_neg1(i32 %c) {
393 ; CHECK-LABEL: @fabs_select_neg0_neg1(
394 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
395 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float -0.000000e+00, float -1.000000e+00
396 ; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
397 ; CHECK-NEXT:    ret float [[FABS]]
399   %cmp = icmp eq i32 %c, 0
400   %select = select i1 %cmp, float -0.0, float -1.0
401   %fabs = call float @llvm.fabs.f32(float %select)
402   ret float %fabs
405 define <2 x float> @fabs_select_neg0_neg1_vector(i32 %c) {
406 ; CHECK-LABEL: @fabs_select_neg0_neg1_vector(
407 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
408 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float -0.000000e+00, float -0.000000e+00>, <2 x float> <float -1.000000e+00, float -1.000000e+00>
409 ; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
410 ; CHECK-NEXT:    ret <2 x float> [[FABS]]
412   %cmp = icmp eq i32 %c, 0
413   %select = select i1 %cmp, <2 x float> <float -0.0, float -0.0>, <2 x float> <float -1.0, float -1.0>
414   %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
415   ret <2 x float> %fabs
418 define float @fabs_select_nan_nan(i32 %c) {
419 ; CHECK-LABEL: @fabs_select_nan_nan(
420 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
421 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0x7FF8000000000000, float 0x7FF8000100000000
422 ; CHECK-NEXT:    ret float [[SELECT]]
424   %cmp = icmp eq i32 %c, 0
425   %select = select i1 %cmp, float 0x7FF8000000000000, float 0x7FF8000100000000
426   %fabs = call float @llvm.fabs.f32(float %select)
427   ret float %fabs
430 define <2 x float> @fabs_select_nan_nan_vector(i32 %c) {
431 ; CHECK-LABEL: @fabs_select_nan_nan_vector(
432 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
433 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
434 ; CHECK-NEXT:    ret <2 x float> [[SELECT]]
436   %cmp = icmp eq i32 %c, 0
437   %select = select i1 %cmp, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
438   %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
439   ret <2 x float> %fabs
442 define float @fabs_select_negnan_nan(i32 %c) {
443 ; CHECK-LABEL: @fabs_select_negnan_nan(
444 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
445 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000000000000
446 ; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
447 ; CHECK-NEXT:    ret float [[FABS]]
449   %cmp = icmp eq i32 %c, 0
450   %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000000000000
451   %fabs = call float @llvm.fabs.f32(float %select)
452   ret float %fabs
455 define <2 x float> @fabs_select_negnan_nan_vector(i32 %c) {
456 ; CHECK-LABEL: @fabs_select_negnan_nan_vector(
457 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
458 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>
459 ; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
460 ; CHECK-NEXT:    ret <2 x float> [[FABS]]
462   %cmp = icmp eq i32 %c, 0
463   %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000000000000, float 0x7FF8000000000000>
464   %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
465   ret <2 x float> %fabs
468 define float @fabs_select_negnan_negnan(i32 %c) {
469 ; CHECK-LABEL: @fabs_select_negnan_negnan(
470 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
471 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0x7FF8000100000000
472 ; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
473 ; CHECK-NEXT:    ret float [[FABS]]
475   %cmp = icmp eq i32 %c, 0
476   %select = select i1 %cmp, float 0xFFF8000000000000, float 0x7FF8000100000000
477   %fabs = call float @llvm.fabs.f32(float %select)
478   ret float %fabs
481 define <2 x float> @fabs_select_negnan_negnan_vector(i32 %c) {
482 ; CHECK-LABEL: @fabs_select_negnan_negnan_vector(
483 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
484 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
485 ; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
486 ; CHECK-NEXT:    ret <2 x float> [[FABS]]
488   %cmp = icmp eq i32 %c, 0
489   %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0x7FF8000100000000, float 0x7FF8000100000000>
490   %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
491   ret <2 x float> %fabs
494 define float @fabs_select_negnan_negzero(i32 %c) {
495 ; CHECK-LABEL: @fabs_select_negnan_negzero(
496 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
497 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float -0.000000e+00
498 ; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
499 ; CHECK-NEXT:    ret float [[FABS]]
501   %cmp = icmp eq i32 %c, 0
502   %select = select i1 %cmp, float 0xFFF8000000000000, float -0.0
503   %fabs = call float @llvm.fabs.f32(float %select)
504   ret float %fabs
507 define <2 x float> @fabs_select_negnan_negzero_vector(i32 %c) {
508 ; CHECK-LABEL: @fabs_select_negnan_negzero_vector(
509 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
510 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.000000e+00, float -0.000000e+00>
511 ; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
512 ; CHECK-NEXT:    ret <2 x float> [[FABS]]
514   %cmp = icmp eq i32 %c, 0
515   %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float -0.0, float -0.0>
516   %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
517   ret <2 x float> %fabs
520 define float @fabs_select_negnan_zero(i32 %c) {
521 ; CHECK-LABEL: @fabs_select_negnan_zero(
522 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
523 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], float 0xFFF8000000000000, float 0.000000e+00
524 ; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
525 ; CHECK-NEXT:    ret float [[FABS]]
527   %cmp = icmp eq i32 %c, 0
528   %select = select i1 %cmp, float 0xFFF8000000000000, float 0.0
529   %fabs = call float @llvm.fabs.f32(float %select)
530   ret float %fabs
533 define <2 x float> @fabs_select_negnan_zero_vector(i32 %c) {
534 ; CHECK-LABEL: @fabs_select_negnan_zero_vector(
535 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
536 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> zeroinitializer
537 ; CHECK-NEXT:    [[FABS:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[SELECT]])
538 ; CHECK-NEXT:    ret <2 x float> [[FABS]]
540   %cmp = icmp eq i32 %c, 0
541   %select = select i1 %cmp, <2 x float> <float 0xFFF8000000000000, float 0xFFF8000000000000>, <2 x float> <float 0.0, float 0.0>
542   %fabs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %select)
543   ret <2 x float> %fabs
546 ; The fabs can't be eliminated because llvm.sqrt.f32 may return -0 or NaN with
547 ; an arbitrary sign bit.
548 define float @fabs_sqrt(float %a) {
549 ; CHECK-LABEL: @fabs_sqrt(
550 ; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]])
551 ; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
552 ; CHECK-NEXT:    ret float [[FABS]]
554   %sqrt = call float @llvm.sqrt.f32(float %a)
555   %fabs = call float @llvm.fabs.f32(float %sqrt)
556   ret float %fabs
559 ; The fabs can't be eliminated because the nnan sqrt may still return -0.
560 define float @fabs_sqrt_nnan(float %a) {
561 ; CHECK-LABEL: @fabs_sqrt_nnan(
562 ; CHECK-NEXT:    [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
563 ; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
564 ; CHECK-NEXT:    ret float [[FABS]]
566   %sqrt = call nnan float @llvm.sqrt.f32(float %a)
567   %fabs = call float @llvm.fabs.f32(float %sqrt)
568   ret float %fabs
571 ; The fabs can't be eliminated because the nsz sqrt may still return NaN.
572 define float @fabs_sqrt_nsz(float %a) {
573 ; CHECK-LABEL: @fabs_sqrt_nsz(
574 ; CHECK-NEXT:    [[SQRT:%.*]] = call nsz float @llvm.sqrt.f32(float [[A:%.*]])
575 ; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SQRT]])
576 ; CHECK-NEXT:    ret float [[FABS]]
578   %sqrt = call nsz float @llvm.sqrt.f32(float %a)
579   %fabs = call float @llvm.fabs.f32(float %sqrt)
580   ret float %fabs
583 ; The fabs can be eliminated because we're nsz and nnan.
584 define float @fabs_sqrt_nnan_nsz(float %a) {
585 ; CHECK-LABEL: @fabs_sqrt_nnan_nsz(
586 ; CHECK-NEXT:    [[SQRT:%.*]] = call nnan nsz float @llvm.sqrt.f32(float [[A:%.*]])
587 ; CHECK-NEXT:    ret float [[SQRT]]
589   %sqrt = call nnan nsz float @llvm.sqrt.f32(float %a)
590   %fabs = call float @llvm.fabs.f32(float %sqrt)
591   ret float %fabs
594 ; The second fabs can be eliminated because the operand to sqrt cannot be -0.
595 define float @fabs_sqrt_nnan_fabs(float %a) {
596 ; CHECK-LABEL: @fabs_sqrt_nnan_fabs(
597 ; CHECK-NEXT:    [[B:%.*]] = call float @llvm.fabs.f32(float [[A:%.*]])
598 ; CHECK-NEXT:    [[SQRT:%.*]] = call nnan float @llvm.sqrt.f32(float [[B]])
599 ; CHECK-NEXT:    ret float [[SQRT]]
601   %b = call float @llvm.fabs.f32(float %a)
602   %sqrt = call nnan float @llvm.sqrt.f32(float %b)
603   %fabs = call float @llvm.fabs.f32(float %sqrt)
604   ret float %fabs
607 define float @fabs_select_positive_constants_vector_extract(i32 %c) {
608 ; CHECK-LABEL: @fabs_select_positive_constants_vector_extract(
609 ; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
610 ; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[CMP]], <2 x float> <float 1.000000e+00, float 1.000000e+00>, <2 x float> <float 2.000000e+00, float 2.000000e+00>
611 ; CHECK-NEXT:    [[EXTRACT:%.*]] = extractelement <2 x float> [[SELECT]], i32 0
612 ; CHECK-NEXT:    ret float [[EXTRACT]]
614   %cmp = icmp eq i32 %c, 0
615   %select = select i1 %cmp, <2 x float> <float 1.0, float 1.0>, <2 x float> <float 2.0, float 2.0>
616   %extract = extractelement <2 x float> %select, i32 0
617   %fabs = call float @llvm.fabs.f32(float %extract)
618   ret float %fabs
621 ; Y - (Y - X) --> X
623 define float @fsub_fsub_common_op(float %x, float %y) {
624 ; CHECK-LABEL: @fsub_fsub_common_op(
625 ; CHECK-NEXT:    ret float [[X:%.*]]
627   %s = fsub float %y, %x
628   %r = fsub reassoc nsz float %y, %s
629   ret float %r
632 define <2 x float> @fsub_fsub_common_op_vec(<2 x float> %x, <2 x float> %y) {
633 ; CHECK-LABEL: @fsub_fsub_common_op_vec(
634 ; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
636   %s = fsub <2 x float> %y, %x
637   %r = fsub reassoc nsz <2 x float> %y, %s
638   ret <2 x float> %r
641 ; Negative test - fsub is not commutative.
642 ; Y - (X - Y) --> (Y - X) + Y (canonicalized)
644 define float @fsub_fsub_wrong_common_op(float %x, float %y) {
645 ; CHECK-LABEL: @fsub_fsub_wrong_common_op(
646 ; CHECK-NEXT:    [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
647 ; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[S]]
648 ; CHECK-NEXT:    ret float [[R]]
650   %s = fsub float %x, %y
651   %r = fsub reassoc nsz float %y, %s
652   ret float %r
655 ; Negative test - negated operand needed.
656 ; (Y - X) - Y --> -X
658 define float @fsub_fsub_common_op_wrong_commute(float %x, float %y) {
659 ; CHECK-LABEL: @fsub_fsub_common_op_wrong_commute(
660 ; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
661 ; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]]
662 ; CHECK-NEXT:    ret float [[R]]
664   %s = fsub float %y, %x
665   %r = fsub reassoc nsz float %s, %y
666   ret float %r
669 ; Negative test - fsub is not commutative.
670 ; (X - Y) - Y --> ?
672 define float @fsub_fsub_wrong_common_op_wrong_commute(float %x, float %y) {
673 ; CHECK-LABEL: @fsub_fsub_wrong_common_op_wrong_commute(
674 ; CHECK-NEXT:    [[S:%.*]] = fsub float [[X:%.*]], [[Y:%.*]]
675 ; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[S]], [[Y]]
676 ; CHECK-NEXT:    ret float [[R]]
678   %s = fsub float %x, %y
679   %r = fsub reassoc nsz float %s, %y
680   ret float %r
683 ; (Y + X) - Y --> X
685 define float @fadd_fsub_common_op(float %x, float %y) {
686 ; CHECK-LABEL: @fadd_fsub_common_op(
687 ; CHECK-NEXT:    ret float [[X:%.*]]
689   %a = fadd float %y, %x
690   %r = fsub reassoc nsz float %a, %y
691   ret float %r
694 ; (X + Y) - Y --> X
696 define <2 x float> @fadd_fsub_common_op_commute_vec(<2 x float> %x, <2 x float> %y) {
697 ; CHECK-LABEL: @fadd_fsub_common_op_commute_vec(
698 ; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
700   %a = fadd <2 x float> %x, %y
701   %r = fsub reassoc nsz <2 x float> %a, %y
702   ret <2 x float> %r
705 ; Negative test - negated operand needed.
706 ; Y - (Y + X) --> -X
708 define float @fadd_fsub_common_op_wrong_commute(float %x, float %y) {
709 ; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute(
710 ; CHECK-NEXT:    [[A:%.*]] = fadd float [[Y:%.*]], [[X:%.*]]
711 ; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]]
712 ; CHECK-NEXT:    ret float [[R]]
714   %a = fadd float %y, %x
715   %r = fsub reassoc nsz float %y, %a
716   ret float %r
719 ; Negative test - negated operand needed.
720 ; Y - (X + Y) --> -X
722 define float @fadd_fsub_common_op_wrong_commute_commute(float %x, float %y) {
723 ; CHECK-LABEL: @fadd_fsub_common_op_wrong_commute_commute(
724 ; CHECK-NEXT:    [[A:%.*]] = fadd float [[X:%.*]], [[Y:%.*]]
725 ; CHECK-NEXT:    [[R:%.*]] = fsub reassoc nsz float [[Y]], [[A]]
726 ; CHECK-NEXT:    ret float [[R]]
728   %a = fadd float %x, %y
729   %r = fsub reassoc nsz float %y, %a
730   ret float %r
733 ; Y + (X - Y) --> X
735 define <2 x float> @fsub_fadd_common_op_vec(<2 x float> %x, <2 x float> %y) {
736 ; CHECK-LABEL: @fsub_fadd_common_op_vec(
737 ; CHECK-NEXT:    ret <2 x float> [[X:%.*]]
739   %s = fsub <2 x float> %x, %y
740   %r = fadd reassoc nsz <2 x float> %y, %s
741   ret <2 x float> %r
744 ; (X - Y) + Y --> X
746 define float @fsub_fadd_common_op_commute(float %x, float %y) {
747 ; CHECK-LABEL: @fsub_fadd_common_op_commute(
748 ; CHECK-NEXT:    ret float [[X:%.*]]
750   %s = fsub float %x, %y
751   %r = fadd reassoc nsz float %s, %y
752   ret float %r
755 ; Negative test.
756 ; Y + (Y - X) --> ?
758 define float @fsub_fadd_common_op_wrong_commute(float %x, float %y) {
759 ; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute(
760 ; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
761 ; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[Y]], [[S]]
762 ; CHECK-NEXT:    ret float [[R]]
764   %s = fsub float %y, %x
765   %r = fadd reassoc nsz float %y, %s
766   ret float %r
769 ; Negative test.
770 ; (Y - X) + Y --> ?
772 define float @fsub_fadd_common_op_wrong_commute_commute(float %x, float %y) {
773 ; CHECK-LABEL: @fsub_fadd_common_op_wrong_commute_commute(
774 ; CHECK-NEXT:    [[S:%.*]] = fsub float [[Y:%.*]], [[X:%.*]]
775 ; CHECK-NEXT:    [[R:%.*]] = fadd reassoc nsz float [[S]], [[Y]]
776 ; CHECK-NEXT:    ret float [[R]]
778   %s = fsub float %y, %x
779   %r = fadd reassoc nsz float %s, %y
780   ret float %r
783 ; PR46627 - https://bugs.llvm.org/show_bug.cgi?id=46627
785 define float @maxnum_with_poszero_op(float %a) {
786 ; CHECK-LABEL: @maxnum_with_poszero_op(
787 ; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 0.000000e+00)
788 ; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
789 ; CHECK-NEXT:    ret float [[FABS]]
791   %max = call float @llvm.maxnum.f32(float %a, float 0.0)
792   %fabs = call float @llvm.fabs.f32(float %max)
793   ret float %fabs
796 define float @maxnum_with_poszero_op_commute(float %a) {
797 ; CHECK-LABEL: @maxnum_with_poszero_op_commute(
798 ; CHECK-NEXT:    [[SQRT:%.*]] = call float @llvm.sqrt.f32(float [[A:%.*]])
799 ; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float 0.000000e+00, float [[SQRT]])
800 ; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
801 ; CHECK-NEXT:    ret float [[FABS]]
803   %sqrt = call float @llvm.sqrt.f32(float %a)
804   %max = call float @llvm.maxnum.f32(float 0.0, float %sqrt)
805   %fabs = call float @llvm.fabs.f32(float %max)
806   ret float %fabs
809 define float @maxnum_with_negzero_op(float %a) {
810 ; CHECK-LABEL: @maxnum_with_negzero_op(
811 ; CHECK-NEXT:    [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
812 ; CHECK-NEXT:    [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]])
813 ; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float -0.000000e+00, float [[FABSA]])
814 ; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
815 ; CHECK-NEXT:    ret float [[FABS]]
817   %nnan = call nnan float @llvm.sqrt.f32(float %a)
818   %fabsa = call float @llvm.fabs.f32(float %nnan)
819   %max = call float @llvm.maxnum.f32(float -0.0, float %fabsa)
820   %fabs = call float @llvm.fabs.f32(float %max)
821   ret float %fabs
824 define float @maxnum_with_negzero_op_commute(float %a) {
825 ; CHECK-LABEL: @maxnum_with_negzero_op_commute(
826 ; CHECK-NEXT:    [[NNAN:%.*]] = call nnan float @llvm.sqrt.f32(float [[A:%.*]])
827 ; CHECK-NEXT:    [[FABSA:%.*]] = call float @llvm.fabs.f32(float [[NNAN]])
828 ; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[FABSA]], float -0.000000e+00)
829 ; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MAX]])
830 ; CHECK-NEXT:    ret float [[FABS]]
832   %nnan = call nnan float @llvm.sqrt.f32(float %a)
833   %fabsa = call float @llvm.fabs.f32(float %nnan)
834   %max = call float @llvm.maxnum.f32(float %fabsa, float -0.0)
835   %fabs = call float @llvm.fabs.f32(float %max)
836   ret float %fabs
839 ; If an operand is strictly greater than 0.0, we know the sign of the result of maxnum.
841 define float @maxnum_with_pos_one_op(float %a) {
842 ; CHECK-LABEL: @maxnum_with_pos_one_op(
843 ; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[A:%.*]], float 1.000000e+00)
844 ; CHECK-NEXT:    ret float [[MAX]]
846   %max = call float @llvm.maxnum.f32(float %a, float 1.0)
847   %fabs = call float @llvm.fabs.f32(float %max)
848   ret float %fabs
851 define double @fadd_nnan_inf_op0(double %x) {
852 ; CHECK-LABEL: @fadd_nnan_inf_op0(
853 ; CHECK-NEXT:    ret double 0x7FF0000000000000
855   %r = fadd nnan double 0x7ff0000000000000, %x
856   ret double %r
859 define double @fadd_nnan_inf_op1(double %x) {
860 ; CHECK-LABEL: @fadd_nnan_inf_op1(
861 ; CHECK-NEXT:    ret double 0x7FF0000000000000
863   %r = fadd nnan double %x, 0x7ff0000000000000
864   ret double %r
867 define <2 x double> @fadd_nnan_neginf_op1(<2 x double> %x) {
868 ; CHECK-LABEL: @fadd_nnan_neginf_op1(
869 ; CHECK-NEXT:    ret <2 x double> <double 0xFFF0000000000000, double poison>
871   %r = fadd nnan <2 x double> %x, <double 0xfff0000000000000, double poison>
872   ret <2 x double> %r
875 define double @fadd_nnan_neginf_op0(double %x) {
876 ; CHECK-LABEL: @fadd_nnan_neginf_op0(
877 ; CHECK-NEXT:    ret double 0xFFF0000000000000
879   %r = fadd nnan double 0xfff0000000000000, %x
880   ret double %r
883 ; negative test - requires nnan
885 define double @fadd_inf_op0(double %x) {
886 ; CHECK-LABEL: @fadd_inf_op0(
887 ; CHECK-NEXT:    [[R:%.*]] = fadd double 0x7FF0000000000000, [[X:%.*]]
888 ; CHECK-NEXT:    ret double [[R]]
890   %r = fadd double 0x7ff0000000000000, %x
891   ret double %r
894 define double @fsub_nnan_inf_op0(double %x) {
895 ; CHECK-LABEL: @fsub_nnan_inf_op0(
896 ; CHECK-NEXT:    ret double 0x7FF0000000000000
898   %r = fsub nnan double 0x7ff0000000000000, %x
899   ret double %r
902 ; flip sign
904 define double @fsub_nnan_inf_op1(double %x) {
905 ; CHECK-LABEL: @fsub_nnan_inf_op1(
906 ; CHECK-NEXT:    ret double 0xFFF0000000000000
908   %r = fsub nnan double %x, 0x7ff0000000000000
909   ret double %r
912 define <2 x double> @fsub_nnan_inf_op1_vec(<2 x double> %x) {
913 ; CHECK-LABEL: @fsub_nnan_inf_op1_vec(
914 ; CHECK-NEXT:    ret <2 x double> <double 0x7FF0000000000000, double poison>
916   %r = fsub nnan <2 x double> %x, <double 0xfff0000000000000, double poison>
917   ret <2 x double> %r
920 define <2 x double> @fsub_nnan_neginf_op0(<2 x double> %x) {
921 ; CHECK-LABEL: @fsub_nnan_neginf_op0(
922 ; CHECK-NEXT:    ret <2 x double> <double 0xFFF0000000000000, double poison>
924   %r = fsub nnan <2 x double> <double 0xfff0000000000000, double poison>, %x
925   ret <2 x double> %r
928 ; flip sign
930 define double @fsub_nnan_neginf_op1(double %x) {
931 ; CHECK-LABEL: @fsub_nnan_neginf_op1(
932 ; CHECK-NEXT:    ret double 0x7FF0000000000000
934   %r = fsub nnan double %x, 0xfff0000000000000
935   ret double %r
938 ; negative test - requires nnan
940 define double @fsub_inf_op0(double %x) {
941 ; CHECK-LABEL: @fsub_inf_op0(
942 ; CHECK-NEXT:    [[R:%.*]] = fsub double 0x7FF0000000000000, [[X:%.*]]
943 ; CHECK-NEXT:    ret double [[R]]
945   %r = fsub double 0x7ff0000000000000, %x
946   ret double %r
949 define i1 @canonicalize_known_positive(float %a) {
950 ; CHECK-LABEL: @canonicalize_known_positive(
951 ; CHECK-NEXT:    ret i1 true
953   %fabs = call float @llvm.fabs.f32(float %a)
954   %known.positive = call float @llvm.canonicalize.f32(float %fabs)
955   %cmp = fcmp nnan oge float %known.positive, 0.0
956   ret i1 %cmp
959 define i1 @canonicalize_unknown_positive(float %unknown) {
960 ; CHECK-LABEL: @canonicalize_unknown_positive(
961 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[UNKNOWN:%.*]], 0.000000e+00
962 ; CHECK-NEXT:    ret i1 [[CMP]]
964   %cmp = fcmp nnan oge float %unknown, 0.0
965   ret i1 %cmp
968 define i1 @arithmetic_fence_known_positive(float %a) {
969 ; CHECK-LABEL: @arithmetic_fence_known_positive(
970 ; CHECK-NEXT:    ret i1 true
972   %fabs = call float @llvm.fabs.f32(float %a)
973   %known.positive = call float @llvm.arithmetic.fence.f32(float %fabs)
974   %cmp = fcmp nnan oge float %known.positive, 0.0
975   ret i1 %cmp
978 define i1 @arithmetic_fence_unknown_positive(float %unknown) {
979 ; CHECK-LABEL: @arithmetic_fence_unknown_positive(
980 ; CHECK-NEXT:    [[KNOWN_POSITIVE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[UNKNOWN:%.*]])
981 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[KNOWN_POSITIVE]], 0.000000e+00
982 ; CHECK-NEXT:    ret i1 [[CMP]]
984   %known.positive = call float @llvm.arithmetic.fence.f32(float %unknown)
985   %cmp = fcmp nnan oge float %known.positive, 0.0
986   ret i1 %cmp
989 define i1 @copysign_known_positive_maybe_neg0(float %unknown, float %sign) {
990 ; CHECK-LABEL: @copysign_known_positive_maybe_neg0(
991 ; CHECK-NEXT:    [[SQRT:%.*]] = call nnan ninf float @llvm.sqrt.f32(float [[SIGN:%.*]])
992 ; CHECK-NEXT:    [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[UNKNOWN:%.*]], float [[SQRT]])
993 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[COPYSIGN]], 0.000000e+00
994 ; CHECK-NEXT:    ret i1 [[CMP]]
996   %sqrt = call ninf nnan float @llvm.sqrt.f32(float %sign)
997   %copysign = call float @llvm.copysign.f32(float %unknown, float %sqrt)
998   %cmp = fcmp nnan oge float %copysign, 0.0
999   ret i1 %cmp
1002 define i1 @copysign_known_positive(float %unknown, float %sign) {
1003 ; CHECK-LABEL: @copysign_known_positive(
1004 ; CHECK-NEXT:    ret i1 true
1006   %sqrt = call ninf nnan nsz float @llvm.sqrt.f32(float %sign)
1007   %copysign = call float @llvm.copysign.f32(float %unknown, float %sqrt)
1008   %cmp = fcmp nnan oge float %copysign, 0.0
1009   ret i1 %cmp
1012 define i1 @copysign_unknown_positive(float %unknown, float %unknown.sign) {
1013 ; CHECK-LABEL: @copysign_unknown_positive(
1014 ; CHECK-NEXT:    [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[UNKNOWN:%.*]], float [[UNKNOWN_SIGN:%.*]])
1015 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[COPYSIGN]], 0.000000e+00
1016 ; CHECK-NEXT:    ret i1 [[CMP]]
1018   %copysign = call float @llvm.copysign.f32(float %unknown, float %unknown.sign)
1019   %cmp = fcmp nnan oge float %copysign, 0.0
1020   ret i1 %cmp
1023 ; https://alive2.llvm.org/ce/z/Y-EyY3
1024 define i1 @floor_known_positive(float %a) {
1025 ; CHECK-LABEL: @floor_known_positive(
1026 ; CHECK-NEXT:    ret i1 true
1028   %fabs = call float @llvm.fabs.f32(float %a)
1029   %known.positive = call float @llvm.floor.f32(float %fabs)
1030   %cmp = fcmp nnan oge float %known.positive, 0.0
1031   ret i1 %cmp
1034 define i1 @floor_unknown_positive(float %unknown) {
1035 ; CHECK-LABEL: @floor_unknown_positive(
1036 ; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.floor.f32(float [[UNKNOWN:%.*]])
1037 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
1038 ; CHECK-NEXT:    ret i1 [[CMP]]
1040   %op = call float @llvm.floor.f32(float %unknown)
1041   %cmp = fcmp nnan oge float %op, 0.0
1042   ret i1 %cmp
1045 ; https://alive2.llvm.org/ce/z/3tBUoW
1046 define i1 @ceil_known_positive(float %a) {
1047 ; CHECK-LABEL: @ceil_known_positive(
1048 ; CHECK-NEXT:    ret i1 true
1050   %fabs = call float @llvm.fabs.f32(float %a)
1051   %known.positive = call float @llvm.ceil.f32(float %fabs)
1052   %cmp = fcmp nnan oge float %known.positive, 0.0
1053   ret i1 %cmp
1056 define i1 @ceil_unknown_positive(float %unknown) {
1057 ; CHECK-LABEL: @ceil_unknown_positive(
1058 ; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.ceil.f32(float [[UNKNOWN:%.*]])
1059 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
1060 ; CHECK-NEXT:    ret i1 [[CMP]]
1063   %op = call float @llvm.ceil.f32(float %unknown)
1064   %cmp = fcmp nnan oge float %op, 0.0
1065   ret i1 %cmp
1068 ; https://alive2.llvm.org/ce/z/RbyJPX
1069 define i1 @trunc_known_positive(float %a) {
1070 ; CHECK-LABEL: @trunc_known_positive(
1071 ; CHECK-NEXT:    ret i1 true
1073   %fabs = call float @llvm.fabs.f32(float %a)
1074   %known.positive = call float @llvm.trunc.f32(float %fabs)
1075   %cmp = fcmp nnan oge float %known.positive, 0.0
1076   ret i1 %cmp
1079 define i1 @trunc_unknown_positive(float %unknown) {
1080 ; CHECK-LABEL: @trunc_unknown_positive(
1081 ; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.trunc.f32(float [[UNKNOWN:%.*]])
1082 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
1083 ; CHECK-NEXT:    ret i1 [[CMP]]
1085   %op = call float @llvm.trunc.f32(float %unknown)
1086   %cmp = fcmp nnan oge float %op, 0.0
1087   ret i1 %cmp
1090 ; https://alive2.llvm.org/ce/z/bjC2Jm
1091 define i1 @rint_known_positive(float %a) {
1092 ; CHECK-LABEL: @rint_known_positive(
1093 ; CHECK-NEXT:    ret i1 true
1095   %fabs = call float @llvm.fabs.f32(float %a)
1096   %known.positive = call float @llvm.rint.f32(float %fabs)
1097   %cmp = fcmp nnan oge float %known.positive, 0.0
1098   ret i1 %cmp
1101 define i1 @rint_unknown_positive(float %unknown) {
1102 ; CHECK-LABEL: @rint_unknown_positive(
1103 ; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.rint.f32(float [[UNKNOWN:%.*]])
1104 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
1105 ; CHECK-NEXT:    ret i1 [[CMP]]
1107   %op = call float @llvm.rint.f32(float %unknown)
1108   %cmp = fcmp nnan oge float %op, 0.0
1109   ret i1 %cmp
1112 ; https://alive2.llvm.org/ce/z/dFiL9n
1113 define i1 @nearbyint_known_positive(float %a) {
1114 ; CHECK-LABEL: @nearbyint_known_positive(
1115 ; CHECK-NEXT:    ret i1 true
1117   %fabs = call float @llvm.fabs.f32(float %a)
1118   %known.positive = call float @llvm.nearbyint.f32(float %fabs)
1119   %cmp = fcmp nnan oge float %known.positive, 0.0
1120   ret i1 %cmp
1123 define i1 @nearbyint_unknown_positive(float %unknown) {
1124 ; CHECK-LABEL: @nearbyint_unknown_positive(
1125 ; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.nearbyint.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.nearbyint.f32(float %unknown)
1130   %cmp = fcmp nnan oge float %op, 0.0
1131   ret i1 %cmp
1134 ; https://alive2.llvm.org/ce/z/kPhS-d
1135 define i1 @round_known_positive(float %a) {
1136 ; CHECK-LABEL: @round_known_positive(
1137 ; CHECK-NEXT:    ret i1 true
1139   %fabs = call float @llvm.fabs.f32(float %a)
1140   %known.positive = call float @llvm.round.f32(float %fabs)
1141   %cmp = fcmp nnan oge float %known.positive, 0.0
1142   ret i1 %cmp
1145 define i1 @round_unknown_positive(float %unknown) {
1146 ; CHECK-LABEL: @round_unknown_positive(
1147 ; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.round.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.round.f32(float %unknown)
1152   %cmp = fcmp nnan oge float %op, 0.0
1153   ret i1 %cmp
1156 ; https://alive2.llvm.org/ce/z/Z_tfsu
1157 define i1 @roundeven_known_positive(float %a) {
1158 ; CHECK-LABEL: @roundeven_known_positive(
1159 ; CHECK-NEXT:    ret i1 true
1161   %fabs = call float @llvm.fabs.f32(float %a)
1162   %known.positive = call float @llvm.roundeven.f32(float %fabs)
1163   %cmp = fcmp nnan oge float %known.positive, 0.0
1164   ret i1 %cmp
1167 define i1 @roundeven_unknown_positive(float %unknown) {
1168 ; CHECK-LABEL: @roundeven_unknown_positive(
1169 ; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.roundeven.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.roundeven.f32(float %unknown)
1174   %cmp = fcmp nnan oge float %op, 0.0
1175   ret i1 %cmp
1178 define i1 @fptrunc_round_known_positive(double %a) {
1179 ; CHECK-LABEL: @fptrunc_round_known_positive(
1180 ; CHECK-NEXT:    ret i1 true
1182   %fabs = call double @llvm.fabs.f64(double %a)
1183   %known.positive = call float @llvm.fptrunc.round.f32.f64(double %fabs, metadata !"round.downward")
1184   %cmp = fcmp nnan oge float %known.positive, 0.0
1185   ret i1 %cmp
1188 define i1 @fptrunc_round_unknown_positive(double %unknown) {
1189 ; CHECK-LABEL: @fptrunc_round_unknown_positive(
1190 ; CHECK-NEXT:    [[OP:%.*]] = call float @llvm.fptrunc.round.f32.f64(double [[UNKNOWN:%.*]], metadata !"round.downward")
1191 ; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan oge float [[OP]], 0.000000e+00
1192 ; CHECK-NEXT:    ret i1 [[CMP]]
1194   %op = call float @llvm.fptrunc.round.f32.f64(double %unknown, metadata !"round.downward")
1195   %cmp = fcmp nnan oge float %op, 0.0
1196   ret i1 %cmp