[DAGCombiner] Add target hook function to decide folding (mul (add x, c1), c2)
[llvm-project.git] / llvm / test / Transforms / InstCombine / fcmp.ll
blobc9941ec46c993b6eca87d1921216edb946439da4
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
18   ret i1 %cmp
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
28   ret i1 %cmp
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>
38   ret <2 x i1> %cmp
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.
49   ret i1 %cmp
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.
60   ret i1 %cmp
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
70   ret i1 %cmp
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]]
78   %neg = fneg float %x
79   %cmp = fcmp ogt float %neg, 1.0
80   ret i1 %cmp
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>
90   ret <2 x i1> %cmp
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>
100   ret <2 x i1> %cmp
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>
110   ret <2 x i1> %cmp
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
122   ret i1 %r
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
132   ret i1 %r
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>
144   ret <2 x i1> %r
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
155   ret i1 %cmp
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
166   ret i1 %cmp
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
177   ret i1 %cmp
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
188   ret i1 %cmp
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
199   ret <2 x i1> %cmp
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
210   ret <2 x i1> %cmp
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
221   ret <2 x i1> %cmp
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
232   ret <2 x i1> %cmp
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
243   ret <2 x i1> %cmp
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
254   ret <2 x i1> %cmp
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
265   ret <2 x i1> %cmp
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
275   ret i1 %cmp
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
288   ret float %conv2
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
298   ret i1 %cmp
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
307   ret i1 %cmp
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
317   ret <2 x i1> %cmp
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
327   ret <2 x i1> %cmp
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
337   ret i1 %cmp
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
347   ret i1 %cmp
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
357   ret i1 %cmp
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
367   ret i1 %cmp
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
376   ret <2 x i1> %cmp
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
386   ret i1 %cmp
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
396   ret i1 %cmp
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
406   ret i1 %cmp
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
416   ret <2 x i1> %cmp
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
426   ret <2 x i1> %cmp
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
436   ret <2 x i1> %cmp
439 ; Don't crash.
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
450   ret i32 %conv
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
460   ret i32 %conv
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
469   ret i32 %conv
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
482   ret i1 %cmp
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
490   ret i1 %cmp
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
501   ret i1 %cmp
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
512   ret i1 %cmp
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
523   ret i1 %cmp
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
534   ret i1 %cmp
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
546   ret i1 %cmp
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
558   ret i1 %cmp
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
570   ret i1 %cmp
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>
581   ret <2 x i1> %cmp
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
592   ret i1 %r
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>
605   ret <2 x i1> %r
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
618   ret i1 %r
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
633   ret i1 %r
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
646   ret i1 %r
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
659   ret i1 %r
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
672   ret i1 %r