1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3
4declare half @llvm.fabs.f16(half)
5declare double @llvm.fabs.f64(double)
6declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
7declare double @llvm.copysign.f64(double, double)
8declare <2 x double> @llvm.copysign.v2f64(<2 x double>, <2 x double>)
9
10define 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]]
14;
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
19}
20
21define 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]]
25;
26  %ext = fpext float %a to double
27  %cmp = fcmp ninf ogt double %ext, 1.000000e+00
28  ret i1 %cmp
29}
30
31define <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]]
35;
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
39}
40
41define 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]]
46;
47  %ext = fpext float %a to double
48  %cmp = fcmp ogt double %ext, 0x3FF0000000000001 ; more precision than float.
49  ret i1 %cmp
50}
51
52define 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]]
57;
58  %ext = fpext float %a to double
59  %cmp = fcmp ogt double %ext, 0x36A0000000000000 ; denormal in float.
60  ret i1 %cmp
61}
62
63define 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]]
67;
68  %neg = fsub float -0.0, %x
69  %cmp = fcmp ogt float %neg, 1.0
70  ret i1 %cmp
71}
72
73define 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]]
77;
78  %neg = fneg float %x
79  %cmp = fcmp ogt float %neg, 1.0
80  ret i1 %cmp
81}
82
83define <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]]
87;
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
91}
92
93define <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]]
97;
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
101}
102
103define <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]]
107;
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
111}
112
113; The new fcmp should have the same FMF as the original.
114
115define 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]]
119;
120  %n = fsub fast float -0.0, %x
121  %r = fcmp fast oeq float %n, 42.0
122  ret i1 %r
123}
124
125define 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]]
129;
130  %n = fneg fast float %x
131  %r = fcmp fast oeq float %n, 42.0
132  ret i1 %r
133}
134
135; The new fcmp should have the same FMF as the original, vector edition.
136
137define <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]]
141;
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
145}
146
147define 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]]
151;
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
156}
157
158define 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]]
162;
163  %neg1 = fneg float %x
164  %neg2 = fneg float %y
165  %cmp = fcmp nnan olt float %neg1, %neg2
166  ret i1 %cmp
167}
168
169define 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]]
173;
174  %neg1 = fneg float %x
175  %neg2 = fsub float -0.0, %y
176  %cmp = fcmp nnan olt float %neg1, %neg2
177  ret i1 %cmp
178}
179
180define 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]]
184;
185  %neg1 = fsub float -0.0, %x
186  %neg2 = fneg float %y
187  %cmp = fcmp nnan olt float %neg1, %neg2
188  ret i1 %cmp
189}
190
191define <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]]
195;
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
200}
201
202define <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]]
206;
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
211}
212
213define <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]]
217;
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
222}
223
224define <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]]
228;
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
233}
234
235define <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]]
239;
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
244}
245
246define <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]]
250;
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
255}
256
257define <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]]
261;
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
266}
267
268define 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]]
272;
273  %ext = fpext float %x to ppc_fp128
274  %cmp = fcmp ogt ppc_fp128 %ext, 0xM00000000000000000000000000000000
275  ret i1 %cmp
276}
277
278define 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]]
283;
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.
290}
291
292define i1 @fabs_uge(double %a) {
293; CHECK-LABEL: @fabs_uge(
294; CHECK-NEXT:    ret i1 true
295;
296  %call = call double @llvm.fabs.f64(double %a)
297  %cmp = fcmp uge double %call, 0.0
298  ret i1 %cmp
299}
300
301define i1 @fabs_olt(half %a) {
302; CHECK-LABEL: @fabs_olt(
303; CHECK-NEXT:    ret i1 false
304;
305  %call = call half @llvm.fabs.f16(half %a)
306  %cmp = fcmp olt half %call, 0.0
307  ret i1 %cmp
308}
309
310define <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]]
314;
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
318}
319
320define <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]]
324;
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
328}
329
330define 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]]
334;
335  %call = call double @llvm.fabs.f64(double %a)
336  %cmp = fcmp reassoc ogt double %call, 0.0
337  ret i1 %cmp
338}
339
340define 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]]
344;
345  %call = call double @llvm.fabs.f64(double %a)
346  %cmp = fcmp ninf reassoc ugt double %call, 0.0
347  ret i1 %cmp
348}
349
350define 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]]
354;
355  %call = call double @llvm.fabs.f64(double %a)
356  %cmp = fcmp afn oge double %call, 0.0
357  ret i1 %cmp
358}
359
360define 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]]
364;
365  %call = call double @llvm.fabs.f64(double %a)
366  %cmp = fcmp reassoc arcp ult double %call, 0.0
367  ret i1 %cmp
368}
369
370define <2 x i1> @fabs_ult_nnan(<2 x float> %a) {
371; CHECK-LABEL: @fabs_ult_nnan(
372; CHECK-NEXT:    ret <2 x i1> zeroinitializer
373;
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
377}
378
379define 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]]
383;
384  %call = call half @llvm.fabs.f16(half %a)
385  %cmp = fcmp ninf une half %call, 0.0
386  ret i1 %cmp
387}
388
389define 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]]
393;
394  %call = call double @llvm.fabs.f64(double %a)
395  %cmp = fcmp ninf reassoc oeq double %call, 0.0
396  ret i1 %cmp
397}
398
399define 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]]
403;
404  %call = call double @llvm.fabs.f64(double %a)
405  %cmp = fcmp fast one double %call, 0.0
406  ret i1 %cmp
407}
408
409define <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]]
413;
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
417}
418
419define <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]]
423;
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
427}
428
429define <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]]
433;
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
437}
438
439; Don't crash.
440define 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]]
446;
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
451}
452
453; Can fold fcmp with undef on one side by choosing NaN for the undef
454define i32 @test18_undef_unordered(float %a) {
455; CHECK-LABEL: @test18_undef_unordered(
456; CHECK-NEXT:    ret i32 1
457;
458  %cmp = fcmp ueq float %a, undef
459  %conv = zext i1 %cmp to i32
460  ret i32 %conv
461}
462; Can fold fcmp with undef on one side by choosing NaN for the undef
463define i32 @test18_undef_ordered(float %a) {
464; CHECK-LABEL: @test18_undef_ordered(
465; CHECK-NEXT:    ret i32 0
466;
467  %cmp = fcmp oeq float %a, undef
468  %conv = zext i1 %cmp to i32
469  ret i32 %conv
470}
471
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
477define i1 @test19_undef_unordered() {
478; CHECK-LABEL: @test19_undef_unordered(
479; CHECK-NEXT:    ret i1 true
480;
481  %cmp = fcmp ueq float undef, undef
482  ret i1 %cmp
483}
484
485define i1 @test19_undef_ordered() {
486; CHECK-LABEL: @test19_undef_ordered(
487; CHECK-NEXT:    ret i1 false
488;
489  %cmp = fcmp oeq float undef, undef
490  ret i1 %cmp
491}
492
493; Can fold 1.0 / X < 0.0 --> X < 0 with ninf
494define 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]]
498;
499  %div = fdiv ninf float 1.0, %X
500  %cmp = fcmp ninf olt float %div, 0.0
501  ret i1 %cmp
502}
503
504; Can fold -2.0 / X <= 0.0 --> X >= 0 with ninf
505define 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]]
509;
510  %div = fdiv ninf float -2.0, %X
511  %cmp = fcmp ninf ole float %div, 0.0
512  ret i1 %cmp
513}
514
515; Can fold 2.0 / X > 0.0 --> X > 0 with ninf
516define 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]]
520;
521  %div = fdiv ninf float 2.0, %X
522  %cmp = fcmp ninf ogt float %div, 0.0
523  ret i1 %cmp
524}
525
526; Can fold -1.0 / X >= 0.0 --> X <= 0 with ninf
527define 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]]
531;
532  %div = fdiv ninf float -1.0, %X
533  %cmp = fcmp ninf oge float %div, 0.0
534  ret i1 %cmp
535}
536
537; Do not fold 1.0 / X > 0.0 when ninf is missing
538define 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]]
543;
544  %div = fdiv ninf float 2.0, %X
545  %cmp = fcmp ogt float %div, 0.0
546  ret i1 %cmp
547}
548
549; Do not fold 1.0 / X > 0.0 when ninf is missing
550define 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]]
555;
556  %div = fdiv float 2.0, %X
557  %cmp = fcmp ninf ogt float %div, 0.0
558  ret i1 %cmp
559}
560
561; Do not fold 1.0 / X > 0.0 with unordered predicates
562define 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]]
567;
568  %div = fdiv ninf float 2.0, %X
569  %cmp = fcmp ninf ugt float %div, 0.0
570  ret i1 %cmp
571}
572
573; Fold <-1.0, -1.0> / X > <-0.0, -0.0>
574define <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]]
578;
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
582}
583
584define 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]]
589;
590  %s = call double @llvm.copysign.f64(double 1.0, double %x)
591  %r = fcmp olt double %s, 0.0
592  ret i1 %r
593}
594
595; Vectors are ok; the sign of zero in the compare doesn't matter; the copysign constant can be any non-zero number.
596
597define <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]]
602;
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
606}
607
608; TODO: Handle different predicates.
609
610define 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]]
615;
616  %s = call double @llvm.copysign.f64(double -42.0, double %x)
617  %r = fcmp ogt double %s, 0.0
618  ret i1 %r
619}
620
621; Negative test - uses
622
623define 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]]
629;
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
634}
635
636; TODO: Handle non-zero compare constant.
637
638define 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]]
643;
644  %s = call double @llvm.copysign.f64(double -42.0, double %x)
645  %r = fcmp ogt double %s, 1.0
646  ret i1 %r
647}
648
649; TODO: Handle zero copysign constant.
650
651define 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]]
656;
657  %s = call double @llvm.copysign.f64(double 0.0, double %x)
658  %r = fcmp ogt double %s, 0.0
659  ret i1 %r
660}
661
662; TODO: Handle NaN copysign constant.
663
664define 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]]
669;
670  %s = call double @llvm.copysign.f64(double 0xffffffffffffffff, double %x)
671  %r = fcmp ogt double %s, 0.0
672  ret i1 %r
673}
674
675define <2 x i1> @lossy_oeq(<2 x float> %x) {
676; CHECK-LABEL: @lossy_oeq(
677; CHECK-NEXT:    [[E:%.*]] = fpext <2 x float> [[X:%.*]] to <2 x double>
678; CHECK-NEXT:    [[R:%.*]] = fcmp oeq <2 x double> [[E]], <double 1.000000e-01, double 1.000000e-01>
679; CHECK-NEXT:    ret <2 x i1> [[R]]
680;
681  %e = fpext <2 x float> %x to <2 x double>
682  %r = fcmp oeq <2 x double> %e, <double 0.1, double 0.1>
683  ret <2 x i1> %r
684}
685
686define i1 @lossy_one(float %x, double* %p) {
687; CHECK-LABEL: @lossy_one(
688; CHECK-NEXT:    [[E:%.*]] = fpext float [[X:%.*]] to double
689; CHECK-NEXT:    store double [[E]], double* [[P:%.*]], align 8
690; CHECK-NEXT:    [[R:%.*]] = fcmp one double [[E]], 1.000000e-01
691; CHECK-NEXT:    ret i1 [[R]]
692;
693  %e = fpext float %x to double
694  store double %e, double* %p
695  %r = fcmp one double %e, 0.1
696  ret i1 %r
697}
698
699define i1 @lossy_ueq(half %x) {
700; CHECK-LABEL: @lossy_ueq(
701; CHECK-NEXT:    [[E:%.*]] = fpext half [[X:%.*]] to double
702; CHECK-NEXT:    [[R:%.*]] = fcmp ueq double [[E]], 6.553600e+04
703; CHECK-NEXT:    ret i1 [[R]]
704;
705  %e = fpext half %x to double
706  %r = fcmp ueq double %e, 65536.0
707  ret i1 %r
708}
709
710define i1 @lossy_une(half %x) {
711; CHECK-LABEL: @lossy_une(
712; CHECK-NEXT:    [[E:%.*]] = fpext half [[X:%.*]] to float
713; CHECK-NEXT:    [[R:%.*]] = fcmp une float [[E]], 2.049000e+03
714; CHECK-NEXT:    ret i1 [[R]]
715;
716  %e = fpext half %x to float
717  %r = fcmp une float %e, 2049.0
718  ret i1 %r
719}
720
721define <2 x i1> @lossy_ogt(<2 x float> %x) {
722; CHECK-LABEL: @lossy_ogt(
723; CHECK-NEXT:    [[E:%.*]] = fpext <2 x float> [[X:%.*]] to <2 x double>
724; CHECK-NEXT:    [[R:%.*]] = fcmp ogt <2 x double> [[E]], <double 1.000000e-01, double 1.000000e-01>
725; CHECK-NEXT:    ret <2 x i1> [[R]]
726;
727  %e = fpext <2 x float> %x to <2 x double>
728  %r = fcmp ogt <2 x double> %e, <double 0.1, double 0.1>
729  ret <2 x i1> %r
730}
731
732define i1 @lossy_oge(float %x, double* %p) {
733; CHECK-LABEL: @lossy_oge(
734; CHECK-NEXT:    [[E:%.*]] = fpext float [[X:%.*]] to double
735; CHECK-NEXT:    store double [[E]], double* [[P:%.*]], align 8
736; CHECK-NEXT:    [[R:%.*]] = fcmp oge double [[E]], 1.000000e-01
737; CHECK-NEXT:    ret i1 [[R]]
738;
739  %e = fpext float %x to double
740  store double %e, double* %p
741  %r = fcmp oge double %e, 0.1
742  ret i1 %r
743}
744
745define i1 @lossy_olt(half %x) {
746; CHECK-LABEL: @lossy_olt(
747; CHECK-NEXT:    [[E:%.*]] = fpext half [[X:%.*]] to double
748; CHECK-NEXT:    [[R:%.*]] = fcmp olt double [[E]], 6.553600e+04
749; CHECK-NEXT:    ret i1 [[R]]
750;
751  %e = fpext half %x to double
752  %r = fcmp olt double %e, 65536.0
753  ret i1 %r
754}
755
756define i1 @lossy_ole(half %x) {
757; CHECK-LABEL: @lossy_ole(
758; CHECK-NEXT:    [[E:%.*]] = fpext half [[X:%.*]] to float
759; CHECK-NEXT:    [[R:%.*]] = fcmp ole float [[E]], 2.049000e+03
760; CHECK-NEXT:    ret i1 [[R]]
761;
762  %e = fpext half %x to float
763  %r = fcmp ole float %e, 2049.0
764  ret i1 %r
765}
766
767define <2 x i1> @lossy_ugt(<2 x float> %x) {
768; CHECK-LABEL: @lossy_ugt(
769; CHECK-NEXT:    [[E:%.*]] = fpext <2 x float> [[X:%.*]] to <2 x double>
770; CHECK-NEXT:    [[R:%.*]] = fcmp ugt <2 x double> [[E]], <double 1.000000e-01, double 1.000000e-01>
771; CHECK-NEXT:    ret <2 x i1> [[R]]
772;
773  %e = fpext <2 x float> %x to <2 x double>
774  %r = fcmp ugt <2 x double> %e, <double 0.1, double 0.1>
775  ret <2 x i1> %r
776}
777
778define i1 @lossy_uge(float %x, double* %p) {
779; CHECK-LABEL: @lossy_uge(
780; CHECK-NEXT:    [[E:%.*]] = fpext float [[X:%.*]] to double
781; CHECK-NEXT:    store double [[E]], double* [[P:%.*]], align 8
782; CHECK-NEXT:    [[R:%.*]] = fcmp uge double [[E]], 1.000000e-01
783; CHECK-NEXT:    ret i1 [[R]]
784;
785  %e = fpext float %x to double
786  store double %e, double* %p
787  %r = fcmp uge double %e, 0.1
788  ret i1 %r
789}
790
791define i1 @lossy_ult(half %x) {
792; CHECK-LABEL: @lossy_ult(
793; CHECK-NEXT:    [[E:%.*]] = fpext half [[X:%.*]] to double
794; CHECK-NEXT:    [[R:%.*]] = fcmp ult double [[E]], 6.553600e+04
795; CHECK-NEXT:    ret i1 [[R]]
796;
797  %e = fpext half %x to double
798  %r = fcmp ult double %e, 65536.0
799  ret i1 %r
800}
801
802define i1 @lossy_ule(half %x) {
803; CHECK-LABEL: @lossy_ule(
804; CHECK-NEXT:    [[E:%.*]] = fpext half [[X:%.*]] to float
805; CHECK-NEXT:    [[R:%.*]] = fcmp ule float [[E]], 2.049000e+03
806; CHECK-NEXT:    ret i1 [[R]]
807;
808  %e = fpext half %x to float
809  %r = fcmp ule float %e, 2049.0
810  ret i1 %r
811}
812
813define i1 @lossy_ord(half %x) {
814; CHECK-LABEL: @lossy_ord(
815; CHECK-NEXT:    [[R:%.*]] = fcmp ord half [[X:%.*]], 0xH0000
816; CHECK-NEXT:    ret i1 [[R]]
817;
818  %e = fpext half %x to double
819  %r = fcmp ord double %e, 65536.0
820  ret i1 %r
821}
822
823define i1 @lossy_uno(half %x) {
824; CHECK-LABEL: @lossy_uno(
825; CHECK-NEXT:    [[R:%.*]] = fcmp uno half [[X:%.*]], 0xH0000
826; CHECK-NEXT:    ret i1 [[R]]
827;
828  %e = fpext half %x to float
829  %r = fcmp uno float %e, 2049.0
830  ret i1 %r
831}
832
833define i1 @fneg_oeq(float %a) {
834; CHECK-LABEL: @fneg_oeq(
835; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq float [[A:%.*]], 0.000000e+00
836; CHECK-NEXT:    ret i1 [[CMP]]
837;
838  %fneg = fneg float %a
839  %cmp = fcmp oeq float %fneg, %a
840  ret i1 %cmp
841}
842
843define i1 @fneg_ogt(half %a) {
844; CHECK-LABEL: @fneg_ogt(
845; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast olt half [[A:%.*]], 0xH0000
846; CHECK-NEXT:    ret i1 [[CMP]]
847;
848  %fneg = fneg half %a
849  %cmp = fcmp fast ogt half %fneg, %a
850  ret i1 %cmp
851}
852
853define <2 x i1> @fneg_oge(<2 x float> %a) {
854; CHECK-LABEL: @fneg_oge(
855; CHECK-NEXT:    [[CMP:%.*]] = fcmp ole <2 x float> [[A:%.*]], zeroinitializer
856; CHECK-NEXT:    ret <2 x i1> [[CMP]]
857;
858  %fneg = fneg fast <2 x float> %a
859  %cmp = fcmp oge <2 x float> %fneg, %a
860  ret <2 x i1> %cmp
861}
862
863define i1 @fneg_olt(float %a, float* %q) {
864; CHECK-LABEL: @fneg_olt(
865; CHECK-NEXT:    [[FNEG:%.*]] = fneg float [[A:%.*]]
866; CHECK-NEXT:    store float [[FNEG]], float* [[Q:%.*]], align 4
867; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt float [[A]], 0.000000e+00
868; CHECK-NEXT:    ret i1 [[CMP]]
869;
870  %fneg = fneg float %a
871  store float %fneg, float* %q
872  %cmp = fcmp olt float %fneg, %a
873  ret i1 %cmp
874}
875
876define i1 @fneg_ole(float %a) {
877; CHECK-LABEL: @fneg_ole(
878; CHECK-NEXT:    [[CMP:%.*]] = fcmp nsz oge float [[A:%.*]], 0.000000e+00
879; CHECK-NEXT:    ret i1 [[CMP]]
880;
881  %fneg = fneg float %a
882  %cmp = fcmp nsz ole float %fneg, %a
883  ret i1 %cmp
884}
885
886define i1 @fneg_one(float %a) {
887; CHECK-LABEL: @fneg_one(
888; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan one float [[A:%.*]], 0.000000e+00
889; CHECK-NEXT:    ret i1 [[CMP]]
890;
891  %fneg = fneg float %a
892  %cmp = fcmp nnan one float %fneg, %a
893  ret i1 %cmp
894}
895
896define i1 @fneg_ord(float %a) {
897; CHECK-LABEL: @fneg_ord(
898; CHECK-NEXT:    [[CMP:%.*]] = fcmp ninf ord float [[A:%.*]], 0.000000e+00
899; CHECK-NEXT:    ret i1 [[CMP]]
900;
901  %fneg = fneg float %a
902  %cmp = fcmp ninf ord float %fneg, %a
903  ret i1 %cmp
904}
905
906define i1 @fneg_uno(float %a) {
907; CHECK-LABEL: @fneg_uno(
908; CHECK-NEXT:    [[CMP:%.*]] = fcmp uno float [[A:%.*]], 0.000000e+00
909; CHECK-NEXT:    ret i1 [[CMP]]
910;
911  %fneg = fneg float %a
912  %cmp = fcmp uno float %fneg, %a
913  ret i1 %cmp
914}
915
916define i1 @fneg_ueq(half %a) {
917; CHECK-LABEL: @fneg_ueq(
918; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ueq half [[A:%.*]], 0xH0000
919; CHECK-NEXT:    ret i1 [[CMP]]
920;
921  %fneg = fneg half %a
922  %cmp = fcmp fast ueq half %fneg, %a
923  ret i1 %cmp
924}
925
926define <2 x i1> @fneg_ugt(<2 x float> %a) {
927; CHECK-LABEL: @fneg_ugt(
928; CHECK-NEXT:    [[CMP:%.*]] = fcmp ult <2 x float> [[A:%.*]], zeroinitializer
929; CHECK-NEXT:    ret <2 x i1> [[CMP]]
930;
931  %fneg = fneg fast <2 x float> %a
932  %cmp = fcmp ugt <2 x float> %fneg, %a
933  ret <2 x i1> %cmp
934}
935
936define i1 @fneg_uge(float %a, float* %q) {
937; CHECK-LABEL: @fneg_uge(
938; CHECK-NEXT:    [[FNEG:%.*]] = fneg float [[A:%.*]]
939; CHECK-NEXT:    store float [[FNEG]], float* [[Q:%.*]], align 4
940; CHECK-NEXT:    [[CMP:%.*]] = fcmp ule float [[A]], 0.000000e+00
941; CHECK-NEXT:    ret i1 [[CMP]]
942;
943  %fneg = fneg float %a
944  store float %fneg, float* %q
945  %cmp = fcmp uge float %fneg, %a
946  ret i1 %cmp
947}
948
949define i1 @fneg_ult(float %a) {
950; CHECK-LABEL: @fneg_ult(
951; CHECK-NEXT:    [[CMP:%.*]] = fcmp nsz ugt float [[A:%.*]], 0.000000e+00
952; CHECK-NEXT:    ret i1 [[CMP]]
953;
954  %fneg = fneg float %a
955  %cmp = fcmp nsz ult float %fneg, %a
956  ret i1 %cmp
957}
958
959define i1 @fneg_ule(float %a) {
960; CHECK-LABEL: @fneg_ule(
961; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan uge float [[A:%.*]], 0.000000e+00
962; CHECK-NEXT:    ret i1 [[CMP]]
963;
964  %fneg = fneg float %a
965  %cmp = fcmp nnan ule float %fneg, %a
966  ret i1 %cmp
967}
968
969define i1 @fneg_une(float %a) {
970; CHECK-LABEL: @fneg_une(
971; CHECK-NEXT:    [[CMP:%.*]] = fcmp ninf une float [[A:%.*]], 0.000000e+00
972; CHECK-NEXT:    ret i1 [[CMP]]
973;
974  %fneg = fneg float %a
975  %cmp = fcmp ninf une float %fneg, %a
976  ret i1 %cmp
977}
978
979define i1 @fneg_oeq_swap(float %p) {
980; CHECK-LABEL: @fneg_oeq_swap(
981; CHECK-NEXT:    [[A:%.*]] = fadd float [[P:%.*]], [[P]]
982; CHECK-NEXT:    [[CMP:%.*]] = fcmp oeq float [[A]], 0.000000e+00
983; CHECK-NEXT:    ret i1 [[CMP]]
984;
985  %a = fadd float %p, %p ; thwart complexity-based canonicalization
986  %fneg = fneg float %a
987  %cmp = fcmp oeq float %a, %fneg
988  ret i1 %cmp
989}
990
991define i1 @fneg_ogt_swap(half %p) {
992; CHECK-LABEL: @fneg_ogt_swap(
993; CHECK-NEXT:    [[A:%.*]] = fadd half [[P:%.*]], [[P]]
994; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ogt half [[A]], 0xH0000
995; CHECK-NEXT:    ret i1 [[CMP]]
996;
997  %a = fadd half %p, %p ; thwart complexity-based canonicalization
998  %fneg = fneg half %a
999  %cmp = fcmp fast ogt half %a, %fneg
1000  ret i1 %cmp
1001}
1002
1003define <2 x i1> @fneg_oge_swap(<2 x float> %p) {
1004; CHECK-LABEL: @fneg_oge_swap(
1005; CHECK-NEXT:    [[A:%.*]] = fadd <2 x float> [[P:%.*]], [[P]]
1006; CHECK-NEXT:    [[CMP:%.*]] = fcmp oge <2 x float> [[A]], zeroinitializer
1007; CHECK-NEXT:    ret <2 x i1> [[CMP]]
1008;
1009  %a = fadd <2 x float> %p, %p ; thwart complexity-based canonicalization
1010  %fneg = fneg fast <2 x float> %a
1011  %cmp = fcmp oge <2 x float> %a, %fneg
1012  ret <2 x i1> %cmp
1013}
1014
1015define i1 @fneg_olt_swap(float %p, float* %q) {
1016; CHECK-LABEL: @fneg_olt_swap(
1017; CHECK-NEXT:    [[A:%.*]] = fadd float [[P:%.*]], [[P]]
1018; CHECK-NEXT:    [[FNEG:%.*]] = fneg float [[A]]
1019; CHECK-NEXT:    store float [[FNEG]], float* [[Q:%.*]], align 4
1020; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt float [[A]], 0.000000e+00
1021; CHECK-NEXT:    ret i1 [[CMP]]
1022;
1023  %a = fadd float %p, %p ; thwart complexity-based canonicalization
1024  %fneg = fneg float %a
1025  store float %fneg, float* %q
1026  %cmp = fcmp olt float %a, %fneg
1027  ret i1 %cmp
1028}
1029
1030define i1 @fneg_ole_swap(float %p) {
1031; CHECK-LABEL: @fneg_ole_swap(
1032; CHECK-NEXT:    [[A:%.*]] = fadd float [[P:%.*]], [[P]]
1033; CHECK-NEXT:    [[CMP:%.*]] = fcmp nsz ole float [[A]], 0.000000e+00
1034; CHECK-NEXT:    ret i1 [[CMP]]
1035;
1036  %a = fadd float %p, %p ; thwart complexity-based canonicalization
1037  %fneg = fneg float %a
1038  %cmp = fcmp nsz ole float %a, %fneg
1039  ret i1 %cmp
1040}
1041
1042define i1 @fneg_one_swap(float %p) {
1043; CHECK-LABEL: @fneg_one_swap(
1044; CHECK-NEXT:    [[A:%.*]] = fadd float [[P:%.*]], [[P]]
1045; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan one float [[A]], 0.000000e+00
1046; CHECK-NEXT:    ret i1 [[CMP]]
1047;
1048  %a = fadd float %p, %p ; thwart complexity-based canonicalization
1049  %fneg = fneg float %a
1050  %cmp = fcmp nnan one float %a, %fneg
1051  ret i1 %cmp
1052}
1053
1054define i1 @fneg_ord_swap(float %p) {
1055; CHECK-LABEL: @fneg_ord_swap(
1056; CHECK-NEXT:    [[A:%.*]] = fadd float [[P:%.*]], [[P]]
1057; CHECK-NEXT:    [[CMP:%.*]] = fcmp ninf ord float [[A]], 0.000000e+00
1058; CHECK-NEXT:    ret i1 [[CMP]]
1059;
1060  %a = fadd float %p, %p ; thwart complexity-based canonicalization
1061  %fneg = fneg float %a
1062  %cmp = fcmp ninf ord float %a, %fneg
1063  ret i1 %cmp
1064}
1065
1066define i1 @fneg_uno_swap(float %p) {
1067; CHECK-LABEL: @fneg_uno_swap(
1068; CHECK-NEXT:    [[A:%.*]] = fadd float [[P:%.*]], [[P]]
1069; CHECK-NEXT:    [[CMP:%.*]] = fcmp uno float [[A]], 0.000000e+00
1070; CHECK-NEXT:    ret i1 [[CMP]]
1071;
1072  %a = fadd float %p, %p ; thwart complexity-based canonicalization
1073  %fneg = fneg float %a
1074  %cmp = fcmp uno float %a, %fneg
1075  ret i1 %cmp
1076}
1077
1078define i1 @fneg_ueq_swap(half %p) {
1079; CHECK-LABEL: @fneg_ueq_swap(
1080; CHECK-NEXT:    [[A:%.*]] = fadd half [[P:%.*]], [[P]]
1081; CHECK-NEXT:    [[CMP:%.*]] = fcmp fast ueq half [[A]], 0xH0000
1082; CHECK-NEXT:    ret i1 [[CMP]]
1083;
1084  %a = fadd half %p, %p ; thwart complexity-based canonicalization
1085  %fneg = fneg half %a
1086  %cmp = fcmp fast ueq half %a, %fneg
1087  ret i1 %cmp
1088}
1089
1090define <2 x i1> @fneg_ugt_swap(<2 x float> %p) {
1091; CHECK-LABEL: @fneg_ugt_swap(
1092; CHECK-NEXT:    [[A:%.*]] = fadd <2 x float> [[P:%.*]], [[P]]
1093; CHECK-NEXT:    [[CMP:%.*]] = fcmp ugt <2 x float> [[A]], zeroinitializer
1094; CHECK-NEXT:    ret <2 x i1> [[CMP]]
1095;
1096  %a = fadd <2 x float> %p, %p ; thwart complexity-based canonicalization
1097  %fneg = fneg fast <2 x float> %a
1098  %cmp = fcmp ugt <2 x float> %a, %fneg
1099  ret <2 x i1> %cmp
1100}
1101
1102define i1 @fneg_uge_swap(float %p, float* %q) {
1103; CHECK-LABEL: @fneg_uge_swap(
1104; CHECK-NEXT:    [[A:%.*]] = fadd float [[P:%.*]], [[P]]
1105; CHECK-NEXT:    [[FNEG:%.*]] = fneg float [[A]]
1106; CHECK-NEXT:    store float [[FNEG]], float* [[Q:%.*]], align 4
1107; CHECK-NEXT:    [[CMP:%.*]] = fcmp uge float [[A]], 0.000000e+00
1108; CHECK-NEXT:    ret i1 [[CMP]]
1109;
1110  %a = fadd float %p, %p ; thwart complexity-based canonicalization
1111  %fneg = fneg float %a
1112  store float %fneg, float* %q
1113  %cmp = fcmp uge float %a, %fneg
1114  ret i1 %cmp
1115}
1116
1117define i1 @fneg_ult_swap(float %p) {
1118; CHECK-LABEL: @fneg_ult_swap(
1119; CHECK-NEXT:    [[A:%.*]] = fadd float [[P:%.*]], [[P]]
1120; CHECK-NEXT:    [[CMP:%.*]] = fcmp nsz ult float [[A]], 0.000000e+00
1121; CHECK-NEXT:    ret i1 [[CMP]]
1122;
1123  %a = fadd float %p, %p ; thwart complexity-based canonicalization
1124  %fneg = fneg float %a
1125  %cmp = fcmp nsz ult float %a, %fneg
1126  ret i1 %cmp
1127}
1128
1129define i1 @fneg_ule_swap(float %p) {
1130; CHECK-LABEL: @fneg_ule_swap(
1131; CHECK-NEXT:    [[A:%.*]] = fadd float [[P:%.*]], [[P]]
1132; CHECK-NEXT:    [[CMP:%.*]] = fcmp nnan ule float [[A]], 0.000000e+00
1133; CHECK-NEXT:    ret i1 [[CMP]]
1134;
1135  %a = fadd float %p, %p ; thwart complexity-based canonicalization
1136  %fneg = fneg float %a
1137  %cmp = fcmp nnan ule float %a, %fneg
1138  ret i1 %cmp
1139}
1140
1141define i1 @fneg_une_swap(float %p) {
1142; CHECK-LABEL: @fneg_une_swap(
1143; CHECK-NEXT:    [[A:%.*]] = fadd float [[P:%.*]], [[P]]
1144; CHECK-NEXT:    [[CMP:%.*]] = fcmp ninf une float [[A]], 0.000000e+00
1145; CHECK-NEXT:    ret i1 [[CMP]]
1146;
1147  %a = fadd float %p, %p ; thwart complexity-based canonicalization
1148  %fneg = fneg float %a
1149  %cmp = fcmp ninf une float %a, %fneg
1150  ret i1 %cmp
1151}
1152