1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt -S -instcombine < %s | FileCheck %s
4 declare half @llvm.fabs.f16(half)
5 declare double @llvm.fabs.f64(double)
6 declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
7 declare double @llvm.copysign.f64(double, double)
8 declare <2 x double> @llvm.copysign.v2f64(<2 x double>, <2 x double>)
10 define i1 @fpext_fpext(float %x, float %y) {
11 ; CHECK-LABEL: @fpext_fpext(
12 ; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]]
13 ; CHECK-NEXT: ret i1 [[CMP]]
15 %ext1 = fpext float %x to double
16 %ext2 = fpext float %y to double
17 %cmp = fcmp nnan ogt double %ext1, %ext2
21 define i1 @fpext_constant(float %a) {
22 ; CHECK-LABEL: @fpext_constant(
23 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt float [[A:%.*]], 1.000000e+00
24 ; CHECK-NEXT: ret i1 [[CMP]]
26 %ext = fpext float %a to double
27 %cmp = fcmp ninf ogt double %ext, 1.000000e+00
31 define <2 x i1> @fpext_constant_vec_splat(<2 x half> %a) {
32 ; CHECK-LABEL: @fpext_constant_vec_splat(
33 ; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ole <2 x half> [[A:%.*]], <half 0xH5140, half 0xH5140>
34 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
36 %ext = fpext <2 x half> %a to <2 x double>
37 %cmp = fcmp nnan ole <2 x double> %ext, <double 42.0, double 42.0>
41 define i1 @fpext_constant_lossy(float %a) {
42 ; CHECK-LABEL: @fpext_constant_lossy(
43 ; CHECK-NEXT: [[EXT:%.*]] = fpext float [[A:%.*]] to double
44 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[EXT]], 0x3FF0000000000001
45 ; CHECK-NEXT: ret i1 [[CMP]]
47 %ext = fpext float %a to double
48 %cmp = fcmp ogt double %ext, 0x3FF0000000000001 ; more precision than float.
52 define i1 @fpext_constant_denorm(float %a) {
53 ; CHECK-LABEL: @fpext_constant_denorm(
54 ; CHECK-NEXT: [[EXT:%.*]] = fpext float [[A:%.*]] to double
55 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt double [[EXT]], 0x36A0000000000000
56 ; CHECK-NEXT: ret i1 [[CMP]]
58 %ext = fpext float %a to double
59 %cmp = fcmp ogt double %ext, 0x36A0000000000000 ; denormal in float.
63 define i1 @fneg_constant_swap_pred(float %x) {
64 ; CHECK-LABEL: @fneg_constant_swap_pred(
65 ; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], -1.000000e+00
66 ; CHECK-NEXT: ret i1 [[CMP]]
68 %neg = fsub float -0.0, %x
69 %cmp = fcmp ogt float %neg, 1.0
73 define i1 @unary_fneg_constant_swap_pred(float %x) {
74 ; CHECK-LABEL: @unary_fneg_constant_swap_pred(
75 ; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], -1.000000e+00
76 ; CHECK-NEXT: ret i1 [[CMP]]
79 %cmp = fcmp ogt float %neg, 1.0
83 define <2 x i1> @fneg_constant_swap_pred_vec(<2 x float> %x) {
84 ; CHECK-LABEL: @fneg_constant_swap_pred_vec(
85 ; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x float> [[X:%.*]], <float -1.000000e+00, float -2.000000e+00>
86 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
88 %neg = fsub <2 x float> <float -0.0, float -0.0>, %x
89 %cmp = fcmp ogt <2 x float> %neg, <float 1.0, float 2.0>
93 define <2 x i1> @unary_fneg_constant_swap_pred_vec(<2 x float> %x) {
94 ; CHECK-LABEL: @unary_fneg_constant_swap_pred_vec(
95 ; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x float> [[X:%.*]], <float -1.000000e+00, float -2.000000e+00>
96 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
98 %neg = fneg <2 x float> %x
99 %cmp = fcmp ogt <2 x float> %neg, <float 1.0, float 2.0>
103 define <2 x i1> @fneg_constant_swap_pred_vec_undef(<2 x float> %x) {
104 ; CHECK-LABEL: @fneg_constant_swap_pred_vec_undef(
105 ; CHECK-NEXT: [[CMP:%.*]] = fcmp olt <2 x float> [[X:%.*]], <float -1.000000e+00, float -2.000000e+00>
106 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
108 %neg = fsub <2 x float> <float undef, float -0.0>, %x
109 %cmp = fcmp ogt <2 x float> %neg, <float 1.0, float 2.0>
113 ; The new fcmp should have the same FMF as the original.
115 define i1 @fneg_fmf(float %x) {
116 ; CHECK-LABEL: @fneg_fmf(
117 ; CHECK-NEXT: [[R:%.*]] = fcmp fast oeq float [[X:%.*]], -4.200000e+01
118 ; CHECK-NEXT: ret i1 [[R]]
120 %n = fsub fast float -0.0, %x
121 %r = fcmp fast oeq float %n, 42.0
125 define i1 @unary_fneg_fmf(float %x) {
126 ; CHECK-LABEL: @unary_fneg_fmf(
127 ; CHECK-NEXT: [[R:%.*]] = fcmp fast oeq float [[X:%.*]], -4.200000e+01
128 ; CHECK-NEXT: ret i1 [[R]]
130 %n = fneg fast float %x
131 %r = fcmp fast oeq float %n, 42.0
135 ; The new fcmp should have the same FMF as the original, vector edition.
137 define <2 x i1> @fcmp_fneg_fmf_vec(<2 x float> %x) {
138 ; CHECK-LABEL: @fcmp_fneg_fmf_vec(
139 ; CHECK-NEXT: [[R:%.*]] = fcmp reassoc nnan ule <2 x float> [[X:%.*]], <float -4.200000e+01, float 1.900000e+01>
140 ; CHECK-NEXT: ret <2 x i1> [[R]]
142 %n = fsub nsz <2 x float> zeroinitializer, %x
143 %r = fcmp nnan reassoc uge <2 x float> %n, <float 42.0, float -19.0>
147 define i1 @fneg_fneg_swap_pred(float %x, float %y) {
148 ; CHECK-LABEL: @fneg_fneg_swap_pred(
149 ; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]]
150 ; CHECK-NEXT: ret i1 [[CMP]]
152 %neg1 = fsub float -0.0, %x
153 %neg2 = fsub float -0.0, %y
154 %cmp = fcmp nnan olt float %neg1, %neg2
158 define i1 @unary_fneg_unary_fneg_swap_pred(float %x, float %y) {
159 ; CHECK-LABEL: @unary_fneg_unary_fneg_swap_pred(
160 ; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]]
161 ; CHECK-NEXT: ret i1 [[CMP]]
163 %neg1 = fneg float %x
164 %neg2 = fneg float %y
165 %cmp = fcmp nnan olt float %neg1, %neg2
169 define i1 @unary_fneg_fneg_swap_pred(float %x, float %y) {
170 ; CHECK-LABEL: @unary_fneg_fneg_swap_pred(
171 ; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]]
172 ; CHECK-NEXT: ret i1 [[CMP]]
174 %neg1 = fneg float %x
175 %neg2 = fsub float -0.0, %y
176 %cmp = fcmp nnan olt float %neg1, %neg2
180 define i1 @fneg_unary_fneg_swap_pred(float %x, float %y) {
181 ; CHECK-LABEL: @fneg_unary_fneg_swap_pred(
182 ; CHECK-NEXT: [[CMP:%.*]] = fcmp nnan ogt float [[X:%.*]], [[Y:%.*]]
183 ; CHECK-NEXT: ret i1 [[CMP]]
185 %neg1 = fsub float -0.0, %x
186 %neg2 = fneg float %y
187 %cmp = fcmp nnan olt float %neg1, %neg2
191 define <2 x i1> @fneg_fneg_swap_pred_vec(<2 x float> %x, <2 x float> %y) {
192 ; CHECK-LABEL: @fneg_fneg_swap_pred_vec(
193 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt <2 x float> [[X:%.*]], [[Y:%.*]]
194 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
196 %neg1 = fsub <2 x float> <float -0.0, float -0.0>, %x
197 %neg2 = fsub <2 x float> <float -0.0, float -0.0>, %y
198 %cmp = fcmp ninf olt <2 x float> %neg1, %neg2
202 define <2 x i1> @unary_fneg_unary_fneg_swap_pred_vec(<2 x float> %x, <2 x float> %y) {
203 ; CHECK-LABEL: @unary_fneg_unary_fneg_swap_pred_vec(
204 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt <2 x float> [[X:%.*]], [[Y:%.*]]
205 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
207 %neg1 = fneg <2 x float> %x
208 %neg2 = fneg <2 x float> %y
209 %cmp = fcmp ninf olt <2 x float> %neg1, %neg2
213 define <2 x i1> @unary_fneg_fneg_swap_pred_vec(<2 x float> %x, <2 x float> %y) {
214 ; CHECK-LABEL: @unary_fneg_fneg_swap_pred_vec(
215 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt <2 x float> [[X:%.*]], [[Y:%.*]]
216 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
218 %neg1 = fneg <2 x float> %x
219 %neg2 = fsub <2 x float> <float -0.0, float -0.0>, %y
220 %cmp = fcmp ninf olt <2 x float> %neg1, %neg2
224 define <2 x i1> @fneg_unary_fneg_swap_pred_vec(<2 x float> %x, <2 x float> %y) {
225 ; CHECK-LABEL: @fneg_unary_fneg_swap_pred_vec(
226 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt <2 x float> [[X:%.*]], [[Y:%.*]]
227 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
229 %neg1 = fsub <2 x float> <float -0.0, float -0.0>, %x
230 %neg2 = fneg <2 x float> %y
231 %cmp = fcmp ninf olt <2 x float> %neg1, %neg2
235 define <2 x i1> @fneg_fneg_swap_pred_vec_undef(<2 x float> %x, <2 x float> %y) {
236 ; CHECK-LABEL: @fneg_fneg_swap_pred_vec_undef(
237 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <2 x float> [[X:%.*]], [[Y:%.*]]
238 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
240 %neg1 = fsub <2 x float> <float -0.0, float undef>, %x
241 %neg2 = fsub <2 x float> <float undef, float -0.0>, %y
242 %cmp = fcmp olt <2 x float> %neg1, %neg2
246 define <2 x i1> @unary_fneg_fneg_swap_pred_vec_undef(<2 x float> %x, <2 x float> %y) {
247 ; CHECK-LABEL: @unary_fneg_fneg_swap_pred_vec_undef(
248 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <2 x float> [[X:%.*]], [[Y:%.*]]
249 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
251 %neg1 = fneg <2 x float> %x
252 %neg2 = fsub <2 x float> <float undef, float -0.0>, %y
253 %cmp = fcmp olt <2 x float> %neg1, %neg2
257 define <2 x i1> @fneg_unary_fneg_swap_pred_vec_undef(<2 x float> %x, <2 x float> %y) {
258 ; CHECK-LABEL: @fneg_unary_fneg_swap_pred_vec_undef(
259 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt <2 x float> [[X:%.*]], [[Y:%.*]]
260 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
262 %neg1 = fsub <2 x float> <float -0.0, float undef>, %x
263 %neg2 = fneg <2 x float> %y
264 %cmp = fcmp olt <2 x float> %neg1, %neg2
268 define i1 @test7(float %x) {
269 ; CHECK-LABEL: @test7(
270 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[X:%.*]], 0.000000e+00
271 ; CHECK-NEXT: ret i1 [[CMP]]
273 %ext = fpext float %x to ppc_fp128
274 %cmp = fcmp ogt ppc_fp128 %ext, 0xM00000000000000000000000000000000
278 define float @test8(float %x) {
279 ; CHECK-LABEL: @test8(
280 ; CHECK-NEXT: [[CMP:%.*]] = fcmp olt float [[X:%.*]], 0.000000e+00
281 ; CHECK-NEXT: [[CONV2:%.*]] = uitofp i1 [[CMP]] to float
282 ; CHECK-NEXT: ret float [[CONV2]]
284 %conv = fpext float %x to double
285 %cmp = fcmp olt double %conv, 0.000000e+00
286 %conv1 = zext i1 %cmp to i32
287 %conv2 = sitofp i32 %conv1 to float
289 ; Float comparison to zero shouldn't cast to double.
292 define i1 @fabs_uge(double %a) {
293 ; CHECK-LABEL: @fabs_uge(
294 ; CHECK-NEXT: ret i1 true
296 %call = call double @llvm.fabs.f64(double %a)
297 %cmp = fcmp uge double %call, 0.0
301 define i1 @fabs_olt(half %a) {
302 ; CHECK-LABEL: @fabs_olt(
303 ; CHECK-NEXT: ret i1 false
305 %call = call half @llvm.fabs.f16(half %a)
306 %cmp = fcmp olt half %call, 0.0
310 define <2 x i1> @fabs_ole(<2 x float> %a) {
311 ; CHECK-LABEL: @fabs_ole(
312 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf oeq <2 x float> [[A:%.*]], zeroinitializer
313 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
315 %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
316 %cmp = fcmp ninf ole <2 x float> %call, zeroinitializer
320 define <2 x i1> @fabs_ule(<2 x float> %a) {
321 ; CHECK-LABEL: @fabs_ule(
322 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf arcp ueq <2 x float> [[A:%.*]], zeroinitializer
323 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
325 %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
326 %cmp = fcmp ninf arcp ule <2 x float> %call, zeroinitializer
330 define i1 @fabs_ogt(double %a) {
331 ; CHECK-LABEL: @fabs_ogt(
332 ; CHECK-NEXT: [[CMP:%.*]] = fcmp reassoc one double [[A:%.*]], 0.000000e+00
333 ; CHECK-NEXT: ret i1 [[CMP]]
335 %call = call double @llvm.fabs.f64(double %a)
336 %cmp = fcmp reassoc ogt double %call, 0.0
340 define i1 @fabs_ugt(double %a) {
341 ; CHECK-LABEL: @fabs_ugt(
342 ; CHECK-NEXT: [[CMP:%.*]] = fcmp reassoc ninf une double [[A:%.*]], 0.000000e+00
343 ; CHECK-NEXT: ret i1 [[CMP]]
345 %call = call double @llvm.fabs.f64(double %a)
346 %cmp = fcmp ninf reassoc ugt double %call, 0.0
350 define i1 @fabs_oge(double %a) {
351 ; CHECK-LABEL: @fabs_oge(
352 ; CHECK-NEXT: [[CMP:%.*]] = fcmp afn ord double [[A:%.*]], 0.000000e+00
353 ; CHECK-NEXT: ret i1 [[CMP]]
355 %call = call double @llvm.fabs.f64(double %a)
356 %cmp = fcmp afn oge double %call, 0.0
360 define i1 @fabs_ult(double %a) {
361 ; CHECK-LABEL: @fabs_ult(
362 ; CHECK-NEXT: [[CMP:%.*]] = fcmp reassoc arcp uno double [[A:%.*]], 0.000000e+00
363 ; CHECK-NEXT: ret i1 [[CMP]]
365 %call = call double @llvm.fabs.f64(double %a)
366 %cmp = fcmp reassoc arcp ult double %call, 0.0
370 define <2 x i1> @fabs_ult_nnan(<2 x float> %a) {
371 ; CHECK-LABEL: @fabs_ult_nnan(
372 ; CHECK-NEXT: ret <2 x i1> zeroinitializer
374 %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
375 %cmp = fcmp nnan reassoc arcp ult <2 x float> %call, zeroinitializer
379 define i1 @fabs_une(half %a) {
380 ; CHECK-LABEL: @fabs_une(
381 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf une half [[A:%.*]], 0xH0000
382 ; CHECK-NEXT: ret i1 [[CMP]]
384 %call = call half @llvm.fabs.f16(half %a)
385 %cmp = fcmp ninf une half %call, 0.0
389 define i1 @fabs_oeq(double %a) {
390 ; CHECK-LABEL: @fabs_oeq(
391 ; CHECK-NEXT: [[CMP:%.*]] = fcmp reassoc ninf oeq double [[A:%.*]], 0.000000e+00
392 ; CHECK-NEXT: ret i1 [[CMP]]
394 %call = call double @llvm.fabs.f64(double %a)
395 %cmp = fcmp ninf reassoc oeq double %call, 0.0
399 define i1 @fabs_one(double %a) {
400 ; CHECK-LABEL: @fabs_one(
401 ; CHECK-NEXT: [[CMP:%.*]] = fcmp fast one double [[A:%.*]], 0.000000e+00
402 ; CHECK-NEXT: ret i1 [[CMP]]
404 %call = call double @llvm.fabs.f64(double %a)
405 %cmp = fcmp fast one double %call, 0.0
409 define <2 x i1> @fabs_ueq(<2 x float> %a) {
410 ; CHECK-LABEL: @fabs_ueq(
411 ; CHECK-NEXT: [[CMP:%.*]] = fcmp arcp ueq <2 x float> [[A:%.*]], zeroinitializer
412 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
414 %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
415 %cmp = fcmp arcp ueq <2 x float> %call, zeroinitializer
419 define <2 x i1> @fabs_ord(<2 x float> %a) {
420 ; CHECK-LABEL: @fabs_ord(
421 ; CHECK-NEXT: [[CMP:%.*]] = fcmp arcp ord <2 x float> [[A:%.*]], zeroinitializer
422 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
424 %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
425 %cmp = fcmp arcp ord <2 x float> %call, zeroinitializer
429 define <2 x i1> @fabs_uno(<2 x float> %a) {
430 ; CHECK-LABEL: @fabs_uno(
431 ; CHECK-NEXT: [[CMP:%.*]] = fcmp arcp uno <2 x float> [[A:%.*]], zeroinitializer
432 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
434 %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
435 %cmp = fcmp arcp uno <2 x float> %call, zeroinitializer
440 define i32 @test17(double %a, double (double)* %p) {
441 ; CHECK-LABEL: @test17(
442 ; CHECK-NEXT: [[CALL:%.*]] = tail call double [[P:%.*]](double [[A:%.*]])
443 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ueq double [[CALL]], 0.000000e+00
444 ; CHECK-NEXT: [[CONV:%.*]] = zext i1 [[CMP]] to i32
445 ; CHECK-NEXT: ret i32 [[CONV]]
447 %call = tail call double %p(double %a)
448 %cmp = fcmp ueq double %call, 0.000000e+00
449 %conv = zext i1 %cmp to i32
453 ; Can fold fcmp with undef on one side by choosing NaN for the undef
454 define i32 @test18_undef_unordered(float %a) {
455 ; CHECK-LABEL: @test18_undef_unordered(
456 ; CHECK-NEXT: ret i32 1
458 %cmp = fcmp ueq float %a, undef
459 %conv = zext i1 %cmp to i32
462 ; Can fold fcmp with undef on one side by choosing NaN for the undef
463 define i32 @test18_undef_ordered(float %a) {
464 ; CHECK-LABEL: @test18_undef_ordered(
465 ; CHECK-NEXT: ret i32 0
467 %cmp = fcmp oeq float %a, undef
468 %conv = zext i1 %cmp to i32
472 ; Can fold fcmp with undef on both side
473 ; fcmp u_pred undef, undef -> true
474 ; fcmp o_pred undef, undef -> false
475 ; because whatever you choose for the first undef
476 ; you can choose NaN for the other undef
477 define i1 @test19_undef_unordered() {
478 ; CHECK-LABEL: @test19_undef_unordered(
479 ; CHECK-NEXT: ret i1 true
481 %cmp = fcmp ueq float undef, undef
485 define i1 @test19_undef_ordered() {
486 ; CHECK-LABEL: @test19_undef_ordered(
487 ; CHECK-NEXT: ret i1 false
489 %cmp = fcmp oeq float undef, undef
493 ; Can fold 1.0 / X < 0.0 --> X < 0 with ninf
494 define i1 @test20_recipX_olt_0(float %X) {
495 ; CHECK-LABEL: @test20_recipX_olt_0(
496 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf olt float [[X:%.*]], 0.000000e+00
497 ; CHECK-NEXT: ret i1 [[CMP]]
499 %div = fdiv ninf float 1.0, %X
500 %cmp = fcmp ninf olt float %div, 0.0
504 ; Can fold -2.0 / X <= 0.0 --> X >= 0 with ninf
505 define i1 @test21_recipX_ole_0(float %X) {
506 ; CHECK-LABEL: @test21_recipX_ole_0(
507 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf oge float [[X:%.*]], 0.000000e+00
508 ; CHECK-NEXT: ret i1 [[CMP]]
510 %div = fdiv ninf float -2.0, %X
511 %cmp = fcmp ninf ole float %div, 0.0
515 ; Can fold 2.0 / X > 0.0 --> X > 0 with ninf
516 define i1 @test22_recipX_ogt_0(float %X) {
517 ; CHECK-LABEL: @test22_recipX_ogt_0(
518 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt float [[X:%.*]], 0.000000e+00
519 ; CHECK-NEXT: ret i1 [[CMP]]
521 %div = fdiv ninf float 2.0, %X
522 %cmp = fcmp ninf ogt float %div, 0.0
526 ; Can fold -1.0 / X >= 0.0 --> X <= 0 with ninf
527 define i1 @test23_recipX_oge_0(float %X) {
528 ; CHECK-LABEL: @test23_recipX_oge_0(
529 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ole float [[X:%.*]], 0.000000e+00
530 ; CHECK-NEXT: ret i1 [[CMP]]
532 %div = fdiv ninf float -1.0, %X
533 %cmp = fcmp ninf oge float %div, 0.0
537 ; Do not fold 1.0 / X > 0.0 when ninf is missing
538 define i1 @test24_recipX_noninf_cmp(float %X) {
539 ; CHECK-LABEL: @test24_recipX_noninf_cmp(
540 ; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf float 2.000000e+00, [[X:%.*]]
541 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ogt float [[DIV]], 0.000000e+00
542 ; CHECK-NEXT: ret i1 [[CMP]]
544 %div = fdiv ninf float 2.0, %X
545 %cmp = fcmp ogt float %div, 0.0
549 ; Do not fold 1.0 / X > 0.0 when ninf is missing
550 define i1 @test25_recipX_noninf_div(float %X) {
551 ; CHECK-LABEL: @test25_recipX_noninf_div(
552 ; CHECK-NEXT: [[DIV:%.*]] = fdiv float 2.000000e+00, [[X:%.*]]
553 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ogt float [[DIV]], 0.000000e+00
554 ; CHECK-NEXT: ret i1 [[CMP]]
556 %div = fdiv float 2.0, %X
557 %cmp = fcmp ninf ogt float %div, 0.0
561 ; Do not fold 1.0 / X > 0.0 with unordered predicates
562 define i1 @test26_recipX_unorderd(float %X) {
563 ; CHECK-LABEL: @test26_recipX_unorderd(
564 ; CHECK-NEXT: [[DIV:%.*]] = fdiv ninf float 2.000000e+00, [[X:%.*]]
565 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf ugt float [[DIV]], 0.000000e+00
566 ; CHECK-NEXT: ret i1 [[CMP]]
568 %div = fdiv ninf float 2.0, %X
569 %cmp = fcmp ninf ugt float %div, 0.0
573 ; Fold <-1.0, -1.0> / X > <-0.0, -0.0>
574 define <2 x i1> @test27_recipX_gt_vecsplat(<2 x float> %X) {
575 ; CHECK-LABEL: @test27_recipX_gt_vecsplat(
576 ; CHECK-NEXT: [[CMP:%.*]] = fcmp ninf olt <2 x float> [[X:%.*]], zeroinitializer
577 ; CHECK-NEXT: ret <2 x i1> [[CMP]]
579 %div = fdiv ninf <2 x float> <float -1.0, float -1.0>, %X
580 %cmp = fcmp ninf ogt <2 x float> %div, <float -0.0, float -0.0>
584 define i1 @is_signbit_set(double %x) {
585 ; CHECK-LABEL: @is_signbit_set(
586 ; CHECK-NEXT: [[TMP1:%.*]] = bitcast double [[X:%.*]] to i64
587 ; CHECK-NEXT: [[R:%.*]] = icmp slt i64 [[TMP1]], 0
588 ; CHECK-NEXT: ret i1 [[R]]
590 %s = call double @llvm.copysign.f64(double 1.0, double %x)
591 %r = fcmp olt double %s, 0.0
595 ; Vectors are ok; the sign of zero in the compare doesn't matter; the copysign constant can be any non-zero number.
597 define <2 x i1> @is_signbit_set_anyzero(<2 x double> %x) {
598 ; CHECK-LABEL: @is_signbit_set_anyzero(
599 ; CHECK-NEXT: [[TMP1:%.*]] = bitcast <2 x double> [[X:%.*]] to <2 x i64>
600 ; CHECK-NEXT: [[R:%.*]] = icmp slt <2 x i64> [[TMP1]], zeroinitializer
601 ; CHECK-NEXT: ret <2 x i1> [[R]]
603 %s = call <2 x double> @llvm.copysign.v2f64(<2 x double> <double 42.0, double 42.0>, <2 x double> %x)
604 %r = fcmp olt <2 x double> %s, <double -0.0, double 0.0>
608 ; TODO: Handle different predicates.
610 define i1 @is_signbit_clear(double %x) {
611 ; CHECK-LABEL: @is_signbit_clear(
612 ; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double -4.200000e+01, double [[X:%.*]])
613 ; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 0.000000e+00
614 ; CHECK-NEXT: ret i1 [[R]]
616 %s = call double @llvm.copysign.f64(double -42.0, double %x)
617 %r = fcmp ogt double %s, 0.0
621 ; Negative test - uses
623 define i1 @is_signbit_set_extra_use(double %x, double* %p) {
624 ; CHECK-LABEL: @is_signbit_set_extra_use(
625 ; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 1.000000e+00, double [[X:%.*]])
626 ; CHECK-NEXT: store double [[S]], double* [[P:%.*]], align 8
627 ; CHECK-NEXT: [[R:%.*]] = fcmp olt double [[S]], 0.000000e+00
628 ; CHECK-NEXT: ret i1 [[R]]
630 %s = call double @llvm.copysign.f64(double 1.0, double %x)
631 store double %s, double* %p
632 %r = fcmp olt double %s, 0.0
636 ; TODO: Handle non-zero compare constant.
638 define i1 @is_signbit_clear_nonzero(double %x) {
639 ; CHECK-LABEL: @is_signbit_clear_nonzero(
640 ; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double -4.200000e+01, double [[X:%.*]])
641 ; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 1.000000e+00
642 ; CHECK-NEXT: ret i1 [[R]]
644 %s = call double @llvm.copysign.f64(double -42.0, double %x)
645 %r = fcmp ogt double %s, 1.0
649 ; TODO: Handle zero copysign constant.
651 define i1 @is_signbit_set_simplify_zero(double %x) {
652 ; CHECK-LABEL: @is_signbit_set_simplify_zero(
653 ; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 0.000000e+00, double [[X:%.*]])
654 ; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 0.000000e+00
655 ; CHECK-NEXT: ret i1 [[R]]
657 %s = call double @llvm.copysign.f64(double 0.0, double %x)
658 %r = fcmp ogt double %s, 0.0
662 ; TODO: Handle NaN copysign constant.
664 define i1 @is_signbit_set_simplify_nan(double %x) {
665 ; CHECK-LABEL: @is_signbit_set_simplify_nan(
666 ; CHECK-NEXT: [[S:%.*]] = call double @llvm.copysign.f64(double 0xFFFFFFFFFFFFFFFF, double [[X:%.*]])
667 ; CHECK-NEXT: [[R:%.*]] = fcmp ogt double [[S]], 0.000000e+00
668 ; CHECK-NEXT: ret i1 [[R]]
670 %s = call double @llvm.copysign.f64(double 0xffffffffffffffff, double %x)
671 %r = fcmp ogt double %s, 0.0