xref: /llvm-project/llvm/test/Transforms/InstSimplify/floating-point-compare.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
3
4; Infinity
5
6define i1 @inf0(double %arg) {
7; CHECK-LABEL: @inf0(
8; CHECK-NEXT:    ret i1 false
9;
10  %tmp = fcmp ogt double %arg, 0x7FF0000000000000
11  ret i1 %tmp
12}
13
14define i1 @inf0_fabs(double %arg) {
15; CHECK-LABEL: @inf0_fabs(
16; CHECK-NEXT:    ret i1 false
17;
18  %fabs.arg = call double @llvm.fabs.f64(double %arg)
19  %tmp = fcmp ogt double %fabs.arg, 0x7FF0000000000000
20  ret i1 %tmp
21}
22
23define i1 @inf1(double %arg) {
24; CHECK-LABEL: @inf1(
25; CHECK-NEXT:    ret i1 true
26;
27  %tmp = fcmp ule double %arg, 0x7FF0000000000000
28  ret i1 %tmp
29}
30
31define i1 @inf1_fabs(double %arg) {
32; CHECK-LABEL: @inf1_fabs(
33; CHECK-NEXT:    ret i1 true
34;
35  %fabs.arg = call double @llvm.fabs.f64(double %arg)
36  %tmp = fcmp ule double %fabs.arg, 0x7FF0000000000000
37  ret i1 %tmp
38}
39
40; Negative infinity
41
42define i1 @ninf0(double %arg) {
43; CHECK-LABEL: @ninf0(
44; CHECK-NEXT:    ret i1 false
45;
46  %tmp = fcmp olt double %arg, 0xFFF0000000000000
47  ret i1 %tmp
48}
49
50define i1 @ninf0_fabs(double %arg) {
51; CHECK-LABEL: @ninf0_fabs(
52; CHECK-NEXT:    ret i1 false
53;
54  %fabs.arg = call double @llvm.fabs.f64(double %arg)
55  %tmp = fcmp olt double %fabs.arg, 0xFFF0000000000000
56  ret i1 %tmp
57}
58
59define i1 @ninf1(double %arg) {
60; CHECK-LABEL: @ninf1(
61; CHECK-NEXT:    ret i1 true
62;
63  %tmp = fcmp uge double %arg, 0xFFF0000000000000
64  ret i1 %tmp
65}
66
67define i1 @ninf1_fabs(double %arg) {
68; CHECK-LABEL: @ninf1_fabs(
69; CHECK-NEXT:    ret i1 true
70;
71  %fabs.arg = call double @llvm.fabs.f64(double %arg)
72  %tmp = fcmp uge double %fabs.arg, 0xFFF0000000000000
73  ret i1 %tmp
74}
75
76; NaNs
77
78define i1 @nan0(double %arg) {
79; CHECK-LABEL: @nan0(
80; CHECK-NEXT:    ret i1 false
81;
82  %tmp = fcmp ord double %arg, 0x7FF00000FFFFFFFF
83  ret i1 %tmp
84}
85
86define i1 @nan1(double %arg) {
87; CHECK-LABEL: @nan1(
88; CHECK-NEXT:    ret i1 false
89;
90  %tmp = fcmp oeq double %arg, 0x7FF00000FFFFFFFF
91  ret i1 %tmp
92}
93
94define i1 @nan2(double %arg) {
95; CHECK-LABEL: @nan2(
96; CHECK-NEXT:    ret i1 false
97;
98  %tmp = fcmp olt double %arg, 0x7FF00000FFFFFFFF
99  ret i1 %tmp
100}
101
102define i1 @nan3(double %arg) {
103; CHECK-LABEL: @nan3(
104; CHECK-NEXT:    ret i1 true
105;
106  %tmp = fcmp uno double %arg, 0x7FF00000FFFFFFFF
107  ret i1 %tmp
108}
109
110define i1 @nan4(double %arg) {
111; CHECK-LABEL: @nan4(
112; CHECK-NEXT:    ret i1 true
113;
114  %tmp = fcmp une double %arg, 0x7FF00000FFFFFFFF
115  ret i1 %tmp
116}
117
118define i1 @nan5(double %arg) {
119; CHECK-LABEL: @nan5(
120; CHECK-NEXT:    ret i1 true
121;
122  %tmp = fcmp ult double %arg, 0x7FF00000FFFFFFFF
123  ret i1 %tmp
124}
125
126; Negative NaN.
127
128define i1 @nnan0(double %arg) {
129; CHECK-LABEL: @nnan0(
130; CHECK-NEXT:    ret i1 false
131;
132  %tmp = fcmp ord double %arg, 0xFFF00000FFFFFFFF
133  ret i1 %tmp
134}
135
136define i1 @nnan1(double %arg) {
137; CHECK-LABEL: @nnan1(
138; CHECK-NEXT:    ret i1 false
139;
140  %tmp = fcmp oeq double %arg, 0xFFF00000FFFFFFFF
141  ret i1 %tmp
142}
143
144define i1 @nnan2(double %arg) {
145; CHECK-LABEL: @nnan2(
146; CHECK-NEXT:    ret i1 false
147;
148  %tmp = fcmp olt double %arg, 0xFFF00000FFFFFFFF
149  ret i1 %tmp
150}
151
152define i1 @nnan3(double %arg) {
153; CHECK-LABEL: @nnan3(
154; CHECK-NEXT:    ret i1 true
155;
156  %tmp = fcmp uno double %arg, 0xFFF00000FFFFFFFF
157  ret i1 %tmp
158}
159
160define i1 @nnan4(double %arg) {
161; CHECK-LABEL: @nnan4(
162; CHECK-NEXT:    ret i1 true
163;
164  %tmp = fcmp une double %arg, 0xFFF00000FFFFFFFF
165  ret i1 %tmp
166}
167
168define i1 @nnan5(double %arg) {
169; CHECK-LABEL: @nnan5(
170; CHECK-NEXT:    ret i1 true
171;
172  %tmp = fcmp ult double %arg, 0xFFF00000FFFFFFFF
173  ret i1 %tmp
174}
175
176; Negative zero.
177
178define i1 @nzero0() {
179; CHECK-LABEL: @nzero0(
180; CHECK-NEXT:    ret i1 true
181;
182  %tmp = fcmp oeq double 0.0, -0.0
183  ret i1 %tmp
184}
185
186define i1 @nzero1() {
187; CHECK-LABEL: @nzero1(
188; CHECK-NEXT:    ret i1 false
189;
190  %tmp = fcmp ogt double 0.0, -0.0
191  ret i1 %tmp
192}
193
194; No enlightenment here.
195
196define i1 @one_with_self(double %arg) {
197; CHECK-LABEL: @one_with_self(
198; CHECK-NEXT:    ret i1 false
199;
200  %tmp = fcmp one double %arg, %arg
201  ret i1 %tmp
202}
203
204; These tests choose arbitrarily between float and double,
205; and between uge and olt, to give reasonble coverage
206; without combinatorial explosion.
207
208define i1 @orderedLessZeroTree(float,float,float,float) {
209; CHECK-LABEL: @orderedLessZeroTree(
210; CHECK-NEXT:    ret i1 true
211;
212  %square = fmul float %0, %0
213  %abs = call float @llvm.fabs.f32(float %1)
214  %sqrt = call float @llvm.sqrt.f32(float %2)
215  %fma = call float @llvm.fma.f32(float %3, float %3, float %sqrt)
216  %div = fdiv float %square, %abs
217  %rem = frem float %sqrt, %fma
218  %add = fadd float %div, %rem
219  %uge = fcmp uge float %add, 0.000000e+00
220  ret i1 %uge
221}
222
223define i1 @orderedLessZero_fdiv(float %x) {
224; CHECK-LABEL: @orderedLessZero_fdiv(
225; CHECK-NEXT:    ret i1 true
226;
227  %d = fdiv float %x, %x
228  %uge = fcmp uge float %d, 0.0
229  ret i1 %uge
230}
231
232; If x == -0.0, maxnum can return -0.0, but that still compares equal to 0.0.
233
234define i1 @orderedLessZero_maxnum(float %x) {
235; CHECK-LABEL: @orderedLessZero_maxnum(
236; CHECK-NEXT:    ret i1 true
237;
238  %d = call float @llvm.maxnum.f32(float %x, float 0.0)
239  %uge = fcmp uge float %d, 0.0
240  ret i1 %uge
241}
242
243define i1 @orderedLessZeroExpExt(float) {
244; CHECK-LABEL: @orderedLessZeroExpExt(
245; CHECK-NEXT:    ret i1 true
246;
247  %a = call float @llvm.exp.f32(float %0)
248  %b = fpext float %a to double
249  %uge = fcmp uge double %b, 0.000000e+00
250  ret i1 %uge
251}
252
253define i1 @orderedLessZeroExp2Trunc(double) {
254; CHECK-LABEL: @orderedLessZeroExp2Trunc(
255; CHECK-NEXT:    ret i1 false
256;
257  %a = call double @llvm.exp2.f64(double %0)
258  %b = fptrunc double %a to float
259  %olt = fcmp olt float %b, 0.000000e+00
260  ret i1 %olt
261}
262
263define i1 @orderedLessZeroPowi(double,double) {
264; CHECK-LABEL: @orderedLessZeroPowi(
265; CHECK-NEXT:    ret i1 false
266;
267  ; Even constant exponent
268  %a = call double @llvm.powi.f64.i32(double %0, i32 2)
269  %square = fmul double %1, %1
270  ; Odd constant exponent with provably non-negative base
271  %b = call double @llvm.powi.f64.i32(double %square, i32 3)
272  %c = fadd double %a, %b
273  %olt = fcmp olt double %b, 0.000000e+00
274  ret i1 %olt
275}
276
277define i1 @UIToFP_is_nan_or_positive_or_zero(i32 %x) {
278; CHECK-LABEL: @UIToFP_is_nan_or_positive_or_zero(
279; CHECK-NEXT:    ret i1 true
280;
281  %a = uitofp i32 %x to float
282  %r = fcmp uge float %a, 0.000000e+00
283  ret i1 %r
284}
285
286define <2 x i1> @UIToFP_is_nan_or_positive_or_zero_vec(<2 x i32> %x) {
287; CHECK-LABEL: @UIToFP_is_nan_or_positive_or_zero_vec(
288; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
289;
290  %a = uitofp <2 x i32> %x to <2 x float>
291  %r = fcmp uge <2 x float> %a, zeroinitializer
292  ret <2 x i1> %r
293}
294
295define i1 @UIToFP_is_positive_or_zero(i32 %x) {
296; CHECK-LABEL: @UIToFP_is_positive_or_zero(
297; CHECK-NEXT:    ret i1 true
298;
299  %a = uitofp i32 %x to float
300  %r = fcmp oge float %a, 0.000000e+00
301  ret i1 %r
302}
303
304define <2 x i1> @UIToFP_is_positive_or_zero_vec(<2 x i32> %x) {
305; CHECK-LABEL: @UIToFP_is_positive_or_zero_vec(
306; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
307;
308  %a = uitofp <2 x i32> %x to <2 x float>
309  %r = fcmp oge <2 x float> %a, zeroinitializer
310  ret <2 x i1> %r
311}
312
313define i1 @UIToFP_nnan_is_positive_or_zero(i32 %x) {
314; CHECK-LABEL: @UIToFP_nnan_is_positive_or_zero(
315; CHECK-NEXT:    ret i1 true
316;
317  %a = uitofp i32 %x to float
318  %r = fcmp nnan oge float %a, 0.000000e+00
319  ret i1 %r
320}
321
322define <2 x i1> @UIToFP_nnan_is_positive_or_zero_vec(<2 x i32> %x) {
323; CHECK-LABEL: @UIToFP_nnan_is_positive_or_zero_vec(
324; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
325;
326  %a = uitofp <2 x i32> %x to <2 x float>
327  %r = fcmp nnan oge <2 x float> %a, zeroinitializer
328  ret <2 x i1> %r
329}
330
331define i1 @UIToFP_is_not_negative(i32 %x) {
332; CHECK-LABEL: @UIToFP_is_not_negative(
333; CHECK-NEXT:    ret i1 false
334;
335  %a = uitofp i32 %x to float
336  %r = fcmp olt float %a, 0.000000e+00
337  ret i1 %r
338}
339
340define <2 x i1> @UIToFP_is_not_negative_vec(<2 x i32> %x) {
341; CHECK-LABEL: @UIToFP_is_not_negative_vec(
342; CHECK-NEXT:    ret <2 x i1> zeroinitializer
343;
344  %a = uitofp <2 x i32> %x to <2 x float>
345  %r = fcmp olt <2 x float> %a, zeroinitializer
346  ret <2 x i1> %r
347}
348
349; No FMF are required for this transform.
350
351define i1 @UIToFP_is_not_negative_or_nan(i32 %x) {
352; CHECK-LABEL: @UIToFP_is_not_negative_or_nan(
353; CHECK-NEXT:    ret i1 false
354;
355  %a = uitofp i32 %x to float
356  %r = fcmp ult float %a, 0.000000e+00
357  ret i1 %r
358}
359
360define <2 x i1> @UIToFP_is_not_negative_or_nan_vec(<2 x i32> %x) {
361; CHECK-LABEL: @UIToFP_is_not_negative_or_nan_vec(
362; CHECK-NEXT:    ret <2 x i1> zeroinitializer
363;
364  %a = uitofp <2 x i32> %x to <2 x float>
365  %r = fcmp ult <2 x float> %a, zeroinitializer
366  ret <2 x i1> %r
367}
368
369define i1 @UIToFP_nnan_is_not_negative(i32 %x) {
370; CHECK-LABEL: @UIToFP_nnan_is_not_negative(
371; CHECK-NEXT:    ret i1 false
372;
373  %a = uitofp i32 %x to float
374  %r = fcmp nnan ult float %a, 0.000000e+00
375  ret i1 %r
376}
377
378define <2 x i1> @UIToFP_nnan_is_not_negative_vec(<2 x i32> %x) {
379; CHECK-LABEL: @UIToFP_nnan_is_not_negative_vec(
380; CHECK-NEXT:    ret <2 x i1> zeroinitializer
381;
382  %a = uitofp <2 x i32> %x to <2 x float>
383  %r = fcmp nnan ult <2 x float> %a, zeroinitializer
384  ret <2 x i1> %r
385}
386
387define i1 @fabs_is_nan_or_positive_or_zero(double %x) {
388; CHECK-LABEL: @fabs_is_nan_or_positive_or_zero(
389; CHECK-NEXT:    ret i1 true
390;
391  %fabs = tail call double @llvm.fabs.f64(double %x)
392  %cmp = fcmp uge double %fabs, 0.0
393  ret i1 %cmp
394}
395
396define <2 x i1> @fabs_is_nan_or_positive_or_zero_vec(<2 x double> %x) {
397; CHECK-LABEL: @fabs_is_nan_or_positive_or_zero_vec(
398; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
399;
400  %fabs = tail call <2 x double> @llvm.fabs.v2f64(<2 x double> %x)
401  %cmp = fcmp uge <2 x double> %fabs, zeroinitializer
402  ret <2 x i1> %cmp
403}
404
405define i1 @fabs_nnan_is_positive_or_zero(double %x) {
406; CHECK-LABEL: @fabs_nnan_is_positive_or_zero(
407; CHECK-NEXT:    ret i1 true
408;
409  %fabs = tail call nnan double @llvm.fabs.f64(double %x)
410  %cmp = fcmp oge double %fabs, 0.0
411  ret i1 %cmp
412}
413
414define <2 x i1> @fabs_nnan_is_positive_or_zero_vec(<2 x double> %x) {
415; CHECK-LABEL: @fabs_nnan_is_positive_or_zero_vec(
416; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
417;
418  %fabs = tail call nnan <2 x double> @llvm.fabs.v2f64(<2 x double> %x)
419  %cmp = fcmp oge <2 x double> %fabs, zeroinitializer
420  ret <2 x i1> %cmp
421}
422
423define i1 @fabs_fcmp-nnan_is_positive_or_zero(double %x) {
424; CHECK-LABEL: @fabs_fcmp-nnan_is_positive_or_zero(
425; CHECK-NEXT:    ret i1 true
426;
427  %fabs = tail call double @llvm.fabs.f64(double %x)
428  %cmp = fcmp nnan oge double %fabs, 0.0
429  ret i1 %cmp
430}
431
432define i1 @fabs_fcmp_oge0-assume-nnan_is_positive_or_zero(double %x) {
433; CHECK-LABEL: @fabs_fcmp_oge0-assume-nnan_is_positive_or_zero(
434; CHECK-NEXT:    [[FABS:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]])
435; CHECK-NEXT:    [[ORD:%.*]] = fcmp ord double [[FABS]], 0.000000e+00
436; CHECK-NEXT:    call void @llvm.assume(i1 [[ORD]])
437; CHECK-NEXT:    ret i1 true
438;
439  %fabs = tail call double @llvm.fabs.f64(double %x)
440  %ord = fcmp ord double %fabs, 0.0
441  call void @llvm.assume(i1 %ord)
442  %cmp = fcmp oge double %fabs, 0.0
443  ret i1 %cmp
444}
445
446define i1 @fabs_fcmp_olt0_-assume-nnan_is_positive_or_zero(double %x) {
447; CHECK-LABEL: @fabs_fcmp_olt0_-assume-nnan_is_positive_or_zero(
448; CHECK-NEXT:    [[FABS:%.*]] = tail call double @llvm.fabs.f64(double [[X:%.*]])
449; CHECK-NEXT:    [[ORD:%.*]] = fcmp ord double [[FABS]], 0.000000e+00
450; CHECK-NEXT:    call void @llvm.assume(i1 [[ORD]])
451; CHECK-NEXT:    ret i1 false
452;
453  %fabs = tail call double @llvm.fabs.f64(double %x)
454  %ord = fcmp ord double %fabs, 0.0
455  call void @llvm.assume(i1 %ord)
456  %cmp = fcmp olt double %fabs, 0.0
457  ret i1 %cmp
458}
459
460define <2 x i1> @fabs_fcmp-nnan_is_positive_or_zero_vec(<2 x double> %x) {
461; CHECK-LABEL: @fabs_fcmp-nnan_is_positive_or_zero_vec(
462; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
463;
464  %fabs = tail call <2 x double> @llvm.fabs.v2f64(<2 x double> %x)
465  %cmp = fcmp nnan oge <2 x double> %fabs, zeroinitializer
466  ret <2 x i1> %cmp
467}
468
469define i1 @fabs_is_not_negative(double %x) {
470; CHECK-LABEL: @fabs_is_not_negative(
471; CHECK-NEXT:    ret i1 false
472;
473  %fabs = tail call double @llvm.fabs.f64(double %x)
474  %cmp = fcmp olt double %fabs, 0.0
475  ret i1 %cmp
476}
477
478define <2 x i1> @fabs_is_not_negative_vec(<2 x double> %x) {
479; CHECK-LABEL: @fabs_is_not_negative_vec(
480; CHECK-NEXT:    ret <2 x i1> zeroinitializer
481;
482  %fabs = tail call <2 x double> @llvm.fabs.v2f64(<2 x double> %x)
483  %cmp = fcmp olt <2 x double> %fabs, zeroinitializer
484  ret <2 x i1> %cmp
485}
486
487define i1 @fabs_nnan_is_not_negative(double %x) {
488; CHECK-LABEL: @fabs_nnan_is_not_negative(
489; CHECK-NEXT:    ret i1 false
490;
491  %fabs = tail call nnan double @llvm.fabs.f64(double %x)
492  %cmp = fcmp ult double %fabs, 0.0
493  ret i1 %cmp
494}
495
496define <2 x i1> @fabs_nnan_is_not_negative_vec(<2 x double> %x) {
497; CHECK-LABEL: @fabs_nnan_is_not_negative_vec(
498; CHECK-NEXT:    ret <2 x i1> zeroinitializer
499;
500  %fabs = tail call nnan <2 x double> @llvm.fabs.v2f64(<2 x double> %x)
501  %cmp = fcmp ult <2 x double> %fabs, zeroinitializer
502  ret <2 x i1> %cmp
503}
504
505define i1 @fabs_fcmp-nnan_is_not_negative(double %x) {
506; CHECK-LABEL: @fabs_fcmp-nnan_is_not_negative(
507; CHECK-NEXT:    ret i1 false
508;
509  %fabs = tail call double @llvm.fabs.f64(double %x)
510  %cmp = fcmp nnan ult double %fabs, 0.0
511  ret i1 %cmp
512}
513
514define <2 x i1> @fabs_fcmp-nnan_is_not_negative_vec(<2 x double> %x) {
515; CHECK-LABEL: @fabs_fcmp-nnan_is_not_negative_vec(
516; CHECK-NEXT:    ret <2 x i1> zeroinitializer
517;
518  %fabs = tail call <2 x double> @llvm.fabs.v2f64(<2 x double> %x)
519  %cmp = fcmp nnan ult <2 x double> %fabs, zeroinitializer
520  ret <2 x i1> %cmp
521}
522
523define <2 x i1> @fabs_is_not_negative_negzero(<2 x float> %V) {
524; CHECK-LABEL: @fabs_is_not_negative_negzero(
525; CHECK-NEXT:    ret <2 x i1> zeroinitializer
526;
527  %abs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %V)
528  %cmp = fcmp olt <2 x float> %abs, <float -0.0, float -0.0>
529  ret <2 x i1> %cmp
530}
531
532define <2 x i1> @fabs_is_not_negative_poszero(<2 x float> %V) {
533; CHECK-LABEL: @fabs_is_not_negative_poszero(
534; CHECK-NEXT:    ret <2 x i1> zeroinitializer
535;
536  %abs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %V)
537  %cmp = fcmp olt <2 x float> %abs, <float 0.0, float 0.0>
538  ret <2 x i1> %cmp
539}
540
541define <2 x i1> @fabs_is_not_negative_anyzero(<2 x float> %V) {
542; CHECK-LABEL: @fabs_is_not_negative_anyzero(
543; CHECK-NEXT:    ret <2 x i1> zeroinitializer
544;
545  %abs = call <2 x float> @llvm.fabs.v2f32(<2 x float> %V)
546  %cmp = fcmp olt <2 x float> %abs, <float 0.0, float -0.0>
547  ret <2 x i1> %cmp
548}
549
550define <3 x i1> @fabs_is_not_negative_negzero_poison(<3 x float> %V) {
551; CHECK-LABEL: @fabs_is_not_negative_negzero_poison(
552; CHECK-NEXT:    ret <3 x i1> zeroinitializer
553;
554  %abs = call <3 x float> @llvm.fabs.v3f32(<3 x float> %V)
555  %cmp = fcmp olt <3 x float> %abs, <float -0.0, float -0.0, float poison>
556  ret <3 x i1> %cmp
557}
558
559define <3 x i1> @fabs_is_not_negative_poszero_poison(<3 x float> %V) {
560; CHECK-LABEL: @fabs_is_not_negative_poszero_poison(
561; CHECK-NEXT:    ret <3 x i1> zeroinitializer
562;
563  %abs = call <3 x float> @llvm.fabs.v3f32(<3 x float> %V)
564  %cmp = fcmp olt <3 x float> %abs, <float 0.0, float 0.0, float poison>
565  ret <3 x i1> %cmp
566}
567
568define <3 x i1> @fabs_is_not_negative_anyzero_poison(<3 x float> %V) {
569; CHECK-LABEL: @fabs_is_not_negative_anyzero_poison(
570; CHECK-NEXT:    ret <3 x i1> zeroinitializer
571;
572  %abs = call <3 x float> @llvm.fabs.v3f32(<3 x float> %V)
573  %cmp = fcmp olt <3 x float> %abs, <float 0.0, float -0.0, float poison>
574  ret <3 x i1> %cmp
575}
576
577define i1 @orderedLessZeroSelect(float, float) {
578; CHECK-LABEL: @orderedLessZeroSelect(
579; CHECK-NEXT:    ret i1 true
580;
581  %a = call float @llvm.exp.f32(float %0)
582  %b = call float @llvm.fabs.f32(float %1)
583  %c = fcmp olt float %0, %1
584  %d = select i1 %c, float %a, float %b
585  %e = fadd float %d, 1.0
586  %uge = fcmp uge float %e, 0.000000e+00
587  ret i1 %uge
588}
589
590define i1 @orderedLessZeroMinNum(float, float) {
591; CHECK-LABEL: @orderedLessZeroMinNum(
592; CHECK-NEXT:    ret i1 true
593;
594  %a = call float @llvm.exp.f32(float %0)
595  %b = call float @llvm.fabs.f32(float %1)
596  %c = call float @llvm.minnum.f32(float %a, float %b)
597  %uge = fcmp uge float %c, 0.000000e+00
598  ret i1 %uge
599}
600
601; PR37776: https://bugs.llvm.org/show_bug.cgi?id=37776
602; exp() may return nan, leaving %1 as the unknown result, so we can't simplify.
603
604define i1 @orderedLessZeroMaxNum(float, float) {
605; CHECK-LABEL: @orderedLessZeroMaxNum(
606; CHECK-NEXT:    [[A:%.*]] = call float @llvm.exp.f32(float [[TMP0:%.*]])
607; CHECK-NEXT:    [[B:%.*]] = call float @llvm.maxnum.f32(float [[A]], float [[TMP1:%.*]])
608; CHECK-NEXT:    [[UGE:%.*]] = fcmp uge float [[B]], 0.000000e+00
609; CHECK-NEXT:    ret i1 [[UGE]]
610;
611  %a = call float @llvm.exp.f32(float %0)
612  %b = call float @llvm.maxnum.f32(float %a, float %1)
613  %uge = fcmp uge float %b, 0.000000e+00
614  ret i1 %uge
615}
616
617; But using maximum, we can simplify, since the NaN would be propagated
618
619define i1 @orderedLessZeroMaximum(float, float) {
620; CHECK-LABEL: @orderedLessZeroMaximum(
621; CHECK-NEXT:    ret i1 true
622;
623  %a = call float @llvm.exp.f32(float %0)
624  %b = call float @llvm.maximum.f32(float %a, float %1)
625  %uge = fcmp uge float %b, 0.000000e+00
626  ret i1 %uge
627}
628
629define i1 @minnum_non_nan(float %x) {
630; CHECK-LABEL: @minnum_non_nan(
631; CHECK-NEXT:    ret i1 true
632;
633  %min = call float @llvm.minnum.f32(float 0.5, float %x)
634  %cmp = fcmp ord float %min, 1.0
635  ret i1 %cmp
636}
637
638define i1 @maxnum_non_nan(float %x) {
639; CHECK-LABEL: @maxnum_non_nan(
640; CHECK-NEXT:    ret i1 false
641;
642  %min = call float @llvm.maxnum.f32(float %x, float 42.0)
643  %cmp = fcmp uno float %min, 12.0
644  ret i1 %cmp
645}
646
647define i1 @assume_nonnan_ord(float %x) {
648; CHECK-LABEL: @assume_nonnan_ord(
649; CHECK-NEXT:    [[ORD:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
650; CHECK-NEXT:    call void @llvm.assume(i1 [[ORD]])
651; CHECK-NEXT:    ret i1 true
652;
653  %ord = fcmp ord float %x, 0.0
654  call void @llvm.assume(i1 %ord)
655  %cmp = fcmp ord float %x, 1.0
656  ret i1 %cmp
657}
658
659define i1 @assume_nonnan_x2_ord(float %x, float %y) {
660; CHECK-LABEL: @assume_nonnan_x2_ord(
661; CHECK-NEXT:    [[ORD_X:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
662; CHECK-NEXT:    call void @llvm.assume(i1 [[ORD_X]])
663; CHECK-NEXT:    [[ORD_Y:%.*]] = fcmp ord float [[Y:%.*]], 0.000000e+00
664; CHECK-NEXT:    call void @llvm.assume(i1 [[ORD_Y]])
665; CHECK-NEXT:    ret i1 true
666;
667  %ord.x = fcmp ord float %x, 0.0
668  call void @llvm.assume(i1 %ord.x)
669  %ord.y = fcmp ord float %y, 0.0
670  call void @llvm.assume(i1 %ord.y)
671  %cmp = fcmp ord float %x, %y
672  ret i1 %cmp
673}
674
675define i1 @assume_nan_x2_uno(float %x, float %y) {
676; CHECK-LABEL: @assume_nan_x2_uno(
677; CHECK-NEXT:    [[UNO_X:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
678; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO_X]])
679; CHECK-NEXT:    [[UNO_Y:%.*]] = fcmp uno float [[Y:%.*]], 0.000000e+00
680; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO_Y]])
681; CHECK-NEXT:    ret i1 true
682;
683  %uno.x = fcmp uno float %x, 0.0
684  call void @llvm.assume(i1 %uno.x)
685  %uno.y = fcmp uno float %y, 0.0
686  call void @llvm.assume(i1 %uno.y)
687  %cmp = fcmp uno float %x, %y
688  ret i1 %cmp
689}
690
691define i1 @assume_nan_x2_ord(float %x, float %y) {
692; CHECK-LABEL: @assume_nan_x2_ord(
693; CHECK-NEXT:    [[UNO_X:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
694; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO_X]])
695; CHECK-NEXT:    [[UNO_Y:%.*]] = fcmp uno float [[Y:%.*]], 0.000000e+00
696; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO_Y]])
697; CHECK-NEXT:    ret i1 false
698;
699  %uno.x = fcmp uno float %x, 0.0
700  call void @llvm.assume(i1 %uno.x)
701  %uno.y = fcmp uno float %y, 0.0
702  call void @llvm.assume(i1 %uno.y)
703  %cmp = fcmp ord float %x, %y
704  ret i1 %cmp
705}
706
707define i1 @assume_nonan_x2_uno(float %x, float %y) {
708; CHECK-LABEL: @assume_nonan_x2_uno(
709; CHECK-NEXT:    [[ORD_X:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
710; CHECK-NEXT:    call void @llvm.assume(i1 [[ORD_X]])
711; CHECK-NEXT:    [[ORD_Y:%.*]] = fcmp ord float [[Y:%.*]], 0.000000e+00
712; CHECK-NEXT:    call void @llvm.assume(i1 [[ORD_Y]])
713; CHECK-NEXT:    ret i1 false
714;
715  %ord.x = fcmp ord float %x, 0.0
716  call void @llvm.assume(i1 %ord.x)
717  %ord.y = fcmp ord float %y, 0.0
718  call void @llvm.assume(i1 %ord.y)
719  %cmp = fcmp uno float %x, %y
720  ret i1 %cmp
721}
722
723define i1 @assume_nan_ord(float %x) {
724; CHECK-LABEL: @assume_nan_ord(
725; CHECK-NEXT:    [[UNO:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
726; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO]])
727; CHECK-NEXT:    ret i1 false
728;
729  %uno = fcmp uno float %x, 0.0
730  call void @llvm.assume(i1 %uno)
731  %cmp = fcmp ord float %x, 1.0
732  ret i1 %cmp
733}
734
735define i1 @assume_nonnan_uno(float %x) {
736; CHECK-LABEL: @assume_nonnan_uno(
737; CHECK-NEXT:    [[ORD:%.*]] = fcmp ord float [[X:%.*]], 0.000000e+00
738; CHECK-NEXT:    call void @llvm.assume(i1 [[ORD]])
739; CHECK-NEXT:    ret i1 false
740;
741  %ord = fcmp ord float %x, 0.0
742  call void @llvm.assume(i1 %ord)
743  %cmp = fcmp uno float %x, 1.0
744  ret i1 %cmp
745}
746
747define i1 @assume_nan_uno(float %x) {
748; CHECK-LABEL: @assume_nan_uno(
749; CHECK-NEXT:    [[UNO:%.*]] = fcmp uno float [[X:%.*]], 0.000000e+00
750; CHECK-NEXT:    call void @llvm.assume(i1 [[UNO]])
751; CHECK-NEXT:    ret i1 true
752;
753  %uno = fcmp uno float %x, 0.0
754  call void @llvm.assume(i1 %uno)
755  %cmp = fcmp uno float %x, 1.0
756  ret i1 %cmp
757}
758
759; min(x, 0.5) == 1.0 --> false
760
761define i1 @minnum_oeq_small_min_constant(float %x) {
762; CHECK-LABEL: @minnum_oeq_small_min_constant(
763; CHECK-NEXT:    ret i1 false
764;
765  %min = call float @llvm.minnum.f32(float %x, float 0.5)
766  %cmp = fcmp oeq float %min, 1.0
767  ret i1 %cmp
768}
769
770; min(x, 0.5) > 1.0 --> false
771
772define i1 @minnum_ogt_small_min_constant(float %x) {
773; CHECK-LABEL: @minnum_ogt_small_min_constant(
774; CHECK-NEXT:    ret i1 false
775;
776  %min = call float @llvm.minnum.f32(float %x, float 0.5)
777  %cmp = fcmp ogt float %min, 1.0
778  ret i1 %cmp
779}
780
781; min(x, 0.5) >= 1.0 --> false
782
783define i1 @minnum_oge_small_min_constant(float %x) {
784; CHECK-LABEL: @minnum_oge_small_min_constant(
785; CHECK-NEXT:    ret i1 false
786;
787  %min = call float @llvm.minnum.f32(float %x, float 0.5)
788  %cmp = fcmp oge float %min, 1.0
789  ret i1 %cmp
790}
791
792; min(x, 0.5) == 1.0 --> false
793
794define i1 @minnum_ueq_small_min_constant(float %x) {
795; CHECK-LABEL: @minnum_ueq_small_min_constant(
796; CHECK-NEXT:    ret i1 false
797;
798  %min = call float @llvm.minnum.f32(float %x, float 0.5)
799  %cmp = fcmp ueq float %min, 1.0
800  ret i1 %cmp
801}
802
803; min(x, 0.5) > 1.0 --> false
804
805define i1 @minnum_ugt_small_min_constant(float %x) {
806; CHECK-LABEL: @minnum_ugt_small_min_constant(
807; CHECK-NEXT:    ret i1 false
808;
809  %min = call float @llvm.minnum.f32(float %x, float 0.5)
810  %cmp = fcmp ugt float %min, 1.0
811  ret i1 %cmp
812}
813
814; min(x, 0.5) >= 1.0 --> false
815
816define <2 x i1> @minnum_uge_small_min_constant(<2 x float> %x) {
817; CHECK-LABEL: @minnum_uge_small_min_constant(
818; CHECK-NEXT:    ret <2 x i1> zeroinitializer
819;
820  %min = call <2 x float> @llvm.minnum.v2f32(<2 x float> %x, <2 x float> <float 0.5, float 0.5>)
821  %cmp = fcmp uge <2 x float> %min, <float 1.0, float 1.0>
822  ret <2 x i1> %cmp
823}
824
825; min(x, 0.5) < 1.0 --> true
826
827define <2 x i1> @minnum_olt_small_min_constant(<2 x float> %x) {
828; CHECK-LABEL: @minnum_olt_small_min_constant(
829; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
830;
831  %min = call <2 x float> @llvm.minnum.v2f32(<2 x float> %x, <2 x float> <float 0.5, float 0.5>)
832  %cmp = fcmp olt <2 x float> %min, <float 1.0, float 1.0>
833  ret <2 x i1> %cmp
834}
835
836; min(x, 0.5) <= 1.0 --> true
837
838define i1 @minnum_ole_small_min_constant(float %x) {
839; CHECK-LABEL: @minnum_ole_small_min_constant(
840; CHECK-NEXT:    ret i1 true
841;
842  %min = call float @llvm.minnum.f32(float %x, float 0.5)
843  %cmp = fcmp ole float %min, 1.0
844  ret i1 %cmp
845}
846
847; min(x, 0.5) != 1.0 --> true
848
849define i1 @minnum_one_small_min_constant(float %x) {
850; CHECK-LABEL: @minnum_one_small_min_constant(
851; CHECK-NEXT:    ret i1 true
852;
853  %min = call float @llvm.minnum.f32(float %x, float 0.5)
854  %cmp = fcmp one float %min, 1.0
855  ret i1 %cmp
856}
857
858; min(x, 0.5) < 1.0 --> true
859
860define i1 @minnum_ult_small_min_constant(float %x) {
861; CHECK-LABEL: @minnum_ult_small_min_constant(
862; CHECK-NEXT:    ret i1 true
863;
864  %min = call float @llvm.minnum.f32(float %x, float 0.5)
865  %cmp = fcmp ult float %min, 1.0
866  ret i1 %cmp
867}
868
869; min(x, 0.5) <= 1.0 --> true
870
871define i1 @minnum_ule_small_min_constant(float %x) {
872; CHECK-LABEL: @minnum_ule_small_min_constant(
873; CHECK-NEXT:    ret i1 true
874;
875  %min = call float @llvm.minnum.f32(float %x, float 0.5)
876  %cmp = fcmp ule float %min, 1.0
877  ret i1 %cmp
878}
879
880; min(x, 0.5) != 1.0 --> true
881
882define i1 @minnum_une_small_min_constant(float %x) {
883; CHECK-LABEL: @minnum_une_small_min_constant(
884; CHECK-NEXT:    ret i1 true
885;
886  %min = call float @llvm.minnum.f32(float %x, float 0.5)
887  %cmp = fcmp une float %min, 1.0
888  ret i1 %cmp
889}
890
891; Negative test:
892; min(x, 1.0) != 1.0 --> ?
893
894define i1 @minnum_une_equal_min_constant(float %x) {
895; CHECK-LABEL: @minnum_une_equal_min_constant(
896; CHECK-NEXT:    [[MIN:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float 1.000000e+00)
897; CHECK-NEXT:    [[CMP:%.*]] = fcmp une float [[MIN]], 1.000000e+00
898; CHECK-NEXT:    ret i1 [[CMP]]
899;
900  %min = call float @llvm.minnum.f32(float %x, float 1.0)
901  %cmp = fcmp une float %min, 1.0
902  ret i1 %cmp
903}
904
905; Negative test:
906; min(x, 2.0) != 1.0 --> ?
907
908define i1 @minnum_une_large_min_constant(float %x) {
909; CHECK-LABEL: @minnum_une_large_min_constant(
910; CHECK-NEXT:    [[MIN:%.*]] = call float @llvm.minnum.f32(float [[X:%.*]], float 2.000000e+00)
911; CHECK-NEXT:    [[CMP:%.*]] = fcmp une float [[MIN]], 1.000000e+00
912; CHECK-NEXT:    ret i1 [[CMP]]
913;
914  %min = call float @llvm.minnum.f32(float %x, float 2.0)
915  %cmp = fcmp une float %min, 1.0
916  ret i1 %cmp
917}
918
919; Partial negative test (the minnum simplifies):
920; min(x, NaN) != 1.0 --> x != 1.0
921
922define i1 @minnum_une_nan_min_constant(float %x) {
923; CHECK-LABEL: @minnum_une_nan_min_constant(
924; CHECK-NEXT:    [[CMP:%.*]] = fcmp une float [[X:%.*]], 1.000000e+00
925; CHECK-NEXT:    ret i1 [[CMP]]
926;
927  %min = call float @llvm.minnum.f32(float %x, float 0x7FF8000000000000)
928  %cmp = fcmp une float %min, 1.0
929  ret i1 %cmp
930}
931
932; max(x, 1.5) == 1.0 --> false
933
934define i1 @maxnum_oeq_large_max_constant(float %x) {
935; CHECK-LABEL: @maxnum_oeq_large_max_constant(
936; CHECK-NEXT:    ret i1 false
937;
938  %max = call float @llvm.maxnum.f32(float %x, float 1.5)
939  %cmp = fcmp oeq float %max, 1.0
940  ret i1 %cmp
941}
942
943; max(x, 1.5) < 1.0 --> false
944
945define i1 @maxnum_olt_large_max_constant(float %x) {
946; CHECK-LABEL: @maxnum_olt_large_max_constant(
947; CHECK-NEXT:    ret i1 false
948;
949  %max = call float @llvm.maxnum.f32(float %x, float 1.5)
950  %cmp = fcmp olt float %max, 1.0
951  ret i1 %cmp
952}
953
954; max(x, 1.5) <= 1.0 --> false
955
956define i1 @maxnum_ole_large_max_constant(float %x) {
957; CHECK-LABEL: @maxnum_ole_large_max_constant(
958; CHECK-NEXT:    ret i1 false
959;
960  %max = call float @llvm.maxnum.f32(float %x, float 1.5)
961  %cmp = fcmp ole float %max, 1.0
962  ret i1 %cmp
963}
964
965; max(x, 1.5) == 1.0 --> false
966
967define i1 @maxnum_ueq_large_max_constant(float %x) {
968; CHECK-LABEL: @maxnum_ueq_large_max_constant(
969; CHECK-NEXT:    ret i1 false
970;
971  %max = call float @llvm.maxnum.f32(float %x, float 1.5)
972  %cmp = fcmp ueq float %max, 1.0
973  ret i1 %cmp
974}
975
976; max(x, 1.5) < 1.0 --> false
977
978define i1 @maxnum_ult_large_max_constant(float %x) {
979; CHECK-LABEL: @maxnum_ult_large_max_constant(
980; CHECK-NEXT:    ret i1 false
981;
982  %max = call float @llvm.maxnum.f32(float %x, float 1.5)
983  %cmp = fcmp ult float %max, 1.0
984  ret i1 %cmp
985}
986
987; max(x, 1.5) <= 1.0 --> false
988
989define <2 x i1> @maxnum_ule_large_max_constant(<2 x float> %x) {
990; CHECK-LABEL: @maxnum_ule_large_max_constant(
991; CHECK-NEXT:    ret <2 x i1> zeroinitializer
992;
993  %max = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %x, <2 x float> <float 1.5, float 1.5>)
994  %cmp = fcmp ule <2 x float> %max, <float 1.0, float 1.0>
995  ret <2 x i1> %cmp
996}
997
998; max(x, 1.5) > 1.0 --> true
999
1000define <2 x i1> @maxnum_ogt_large_max_constant(<2 x float> %x) {
1001; CHECK-LABEL: @maxnum_ogt_large_max_constant(
1002; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
1003;
1004  %max = call <2 x float> @llvm.maxnum.v2f32(<2 x float> %x, <2 x float> <float 1.5, float 1.5>)
1005  %cmp = fcmp ogt <2 x float> %max, <float 1.0, float 1.0>
1006  ret <2 x i1> %cmp
1007}
1008
1009; max(x, 1.5) >= 1.0 --> true
1010
1011define i1 @maxnum_oge_large_max_constant(float %x) {
1012; CHECK-LABEL: @maxnum_oge_large_max_constant(
1013; CHECK-NEXT:    ret i1 true
1014;
1015  %max = call float @llvm.maxnum.f32(float %x, float 1.5)
1016  %cmp = fcmp oge float %max, 1.0
1017  ret i1 %cmp
1018}
1019
1020; max(x, 1.5) != 1.0 --> true
1021
1022define i1 @maxnum_one_large_max_constant(float %x) {
1023; CHECK-LABEL: @maxnum_one_large_max_constant(
1024; CHECK-NEXT:    ret i1 true
1025;
1026  %max = call float @llvm.maxnum.f32(float %x, float 1.5)
1027  %cmp = fcmp one float %max, 1.0
1028  ret i1 %cmp
1029}
1030
1031; max(x, 1.5) > 1.0 --> true
1032
1033define i1 @maxnum_ugt_large_max_constant(float %x) {
1034; CHECK-LABEL: @maxnum_ugt_large_max_constant(
1035; CHECK-NEXT:    ret i1 true
1036;
1037  %max = call float @llvm.maxnum.f32(float %x, float 1.5)
1038  %cmp = fcmp ugt float %max, 1.0
1039  ret i1 %cmp
1040}
1041
1042; max(x, 1.5) >= 1.0 --> true
1043
1044define i1 @maxnum_uge_large_max_constant(float %x) {
1045; CHECK-LABEL: @maxnum_uge_large_max_constant(
1046; CHECK-NEXT:    ret i1 true
1047;
1048  %max = call float @llvm.maxnum.f32(float %x, float 1.5)
1049  %cmp = fcmp uge float %max, 1.0
1050  ret i1 %cmp
1051}
1052
1053; max(x, 1.5) != 1.0 --> true
1054
1055define i1 @maxnum_une_large_max_constant(float %x) {
1056; CHECK-LABEL: @maxnum_une_large_max_constant(
1057; CHECK-NEXT:    ret i1 true
1058;
1059  %max = call float @llvm.maxnum.f32(float %x, float 1.5)
1060  %cmp = fcmp une float %max, 1.0
1061  ret i1 %cmp
1062}
1063
1064; Negative test:
1065; max(x, 1.0) != 1.0 --> ?
1066
1067define i1 @maxnum_une_equal_max_constant(float %x) {
1068; CHECK-LABEL: @maxnum_une_equal_max_constant(
1069; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 1.000000e+00)
1070; CHECK-NEXT:    [[CMP:%.*]] = fcmp une float [[MAX]], 1.000000e+00
1071; CHECK-NEXT:    ret i1 [[CMP]]
1072;
1073  %max = call float @llvm.maxnum.f32(float %x, float 1.0)
1074  %cmp = fcmp une float %max, 1.0
1075  ret i1 %cmp
1076}
1077
1078; Negative test:
1079; max(x, 0.5) != 1.0 --> ?
1080
1081define i1 @maxnum_une_small_max_constant(float %x) {
1082; CHECK-LABEL: @maxnum_une_small_max_constant(
1083; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[X:%.*]], float 5.000000e-01)
1084; CHECK-NEXT:    [[CMP:%.*]] = fcmp une float [[MAX]], 1.000000e+00
1085; CHECK-NEXT:    ret i1 [[CMP]]
1086;
1087  %max = call float @llvm.maxnum.f32(float %x, float 0.5)
1088  %cmp = fcmp une float %max, 1.0
1089  ret i1 %cmp
1090}
1091
1092; Partial negative test (the maxnum simplifies):
1093; max(x, NaN) != 1.0 --> x != 1.0
1094
1095define i1 @maxnum_une_nan_max_constant(float %x) {
1096; CHECK-LABEL: @maxnum_une_nan_max_constant(
1097; CHECK-NEXT:    [[CMP:%.*]] = fcmp une float [[X:%.*]], 1.000000e+00
1098; CHECK-NEXT:    ret i1 [[CMP]]
1099;
1100  %max = call float @llvm.maxnum.f32(float %x, float 0x7FF8000000000000)
1101  %cmp = fcmp une float %max, 1.0
1102  ret i1 %cmp
1103}
1104
1105define i1 @known_positive_olt_with_negative_constant(double %a) {
1106; CHECK-LABEL: @known_positive_olt_with_negative_constant(
1107; CHECK-NEXT:    ret i1 false
1108;
1109  %call = call double @llvm.fabs.f64(double %a)
1110  %cmp = fcmp olt double %call, -1.0
1111  ret i1 %cmp
1112}
1113
1114define i1 @known_positive_nsz_olt_with_negative_constant(double %mag, double %a) {
1115; CHECK-LABEL: @known_positive_nsz_olt_with_negative_constant(
1116; CHECK-NEXT:    [[SQRT:%.*]] = call nsz double @llvm.sqrt.f64(double [[A:%.*]])
1117; CHECK-NEXT:    [[COPYSIGN:%.*]] = call double @llvm.copysign.f64(double [[MAG:%.*]], double [[SQRT]])
1118; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt double [[COPYSIGN]], -1.000000e+00
1119; CHECK-NEXT:    ret i1 [[CMP]]
1120;
1121  %sqrt = call nsz double @llvm.sqrt.f64(double %a)
1122  %copysign = call double @llvm.copysign.f64(double %mag, double %sqrt)
1123  %cmp = fcmp olt double %copysign, -1.0
1124  ret i1 %cmp
1125}
1126
1127define i1 @known_positive_maybe_neg0_olt_with_negative_constant(double %mag, double %a) {
1128; CHECK-LABEL: @known_positive_maybe_neg0_olt_with_negative_constant(
1129; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[A:%.*]])
1130; CHECK-NEXT:    [[COPYSIGN:%.*]] = call double @llvm.copysign.f64(double [[MAG:%.*]], double [[SQRT]])
1131; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt double [[COPYSIGN]], -1.000000e+00
1132; CHECK-NEXT:    ret i1 [[CMP]]
1133;
1134  %sqrt = call double @llvm.sqrt.f64(double %a)
1135  %copysign = call double @llvm.copysign.f64(double %mag, double %sqrt)
1136  %cmp = fcmp olt double %copysign, -1.0
1137  ret i1 %cmp
1138}
1139
1140define i1 @known_positive_nsz_uge_with_negative_constant(double %mag, double %a) {
1141; CHECK-LABEL: @known_positive_nsz_uge_with_negative_constant(
1142; CHECK-NEXT:    [[SQRT:%.*]] = call nsz double @llvm.sqrt.f64(double [[A:%.*]])
1143; CHECK-NEXT:    [[COPYSIGN:%.*]] = call double @llvm.copysign.f64(double [[MAG:%.*]], double [[SQRT]])
1144; CHECK-NEXT:    [[CMP:%.*]] = fcmp uge double [[COPYSIGN]], -1.000000e+00
1145; CHECK-NEXT:    ret i1 [[CMP]]
1146;
1147  %sqrt = call nsz double @llvm.sqrt.f64(double %a)
1148  %copysign = call double @llvm.copysign.f64(double %mag, double %sqrt)
1149  %cmp = fcmp uge double %copysign, -1.0
1150  ret i1 %cmp
1151}
1152
1153define i1 @known_positive_maybe_neg0_uge_with_negative_constant(double %mag, double %a) {
1154; CHECK-LABEL: @known_positive_maybe_neg0_uge_with_negative_constant(
1155; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[A:%.*]])
1156; CHECK-NEXT:    [[COPYSIGN:%.*]] = call double @llvm.copysign.f64(double [[MAG:%.*]], double [[SQRT]])
1157; CHECK-NEXT:    [[CMP:%.*]] = fcmp uge double [[COPYSIGN]], -1.000000e+00
1158; CHECK-NEXT:    ret i1 [[CMP]]
1159;
1160  %sqrt = call double @llvm.sqrt.f64(double %a)
1161  %copysign = call double @llvm.copysign.f64(double %mag, double %sqrt)
1162  %cmp = fcmp uge double %copysign, -1.0
1163  ret i1 %cmp
1164}
1165
1166define i1 @known_positive_nsz_oge_with_zero_constant(double %mag, double %a) {
1167; CHECK-LABEL: @known_positive_nsz_oge_with_zero_constant(
1168; CHECK-NEXT:    [[SQRT:%.*]] = call nsz double @llvm.sqrt.f64(double [[A:%.*]])
1169; CHECK-NEXT:    [[COPYSIGN:%.*]] = call double @llvm.copysign.f64(double [[MAG:%.*]], double [[SQRT]])
1170; CHECK-NEXT:    [[CMP:%.*]] = fcmp oge double [[COPYSIGN]], 0.000000e+00
1171; CHECK-NEXT:    ret i1 [[CMP]]
1172;
1173  %sqrt = call nsz double @llvm.sqrt.f64(double %a)
1174  %copysign = call double @llvm.copysign.f64(double %mag, double %sqrt)
1175  %cmp = fcmp oge double %copysign, 0.0
1176  ret i1 %cmp
1177}
1178
1179define i1 @known_positive_maybe_neg0_oge_with_zero_constant(double %mag, double %a) {
1180; CHECK-LABEL: @known_positive_maybe_neg0_oge_with_zero_constant(
1181; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[A:%.*]])
1182; CHECK-NEXT:    [[COPYSIGN:%.*]] = call double @llvm.copysign.f64(double [[MAG:%.*]], double [[SQRT]])
1183; CHECK-NEXT:    [[CMP:%.*]] = fcmp oge double [[COPYSIGN]], 0.000000e+00
1184; CHECK-NEXT:    ret i1 [[CMP]]
1185;
1186  %sqrt = call double @llvm.sqrt.f64(double %a)
1187  %copysign = call double @llvm.copysign.f64(double %mag, double %sqrt)
1188  %cmp = fcmp oge double %copysign, 0.0
1189  ret i1 %cmp
1190}
1191
1192define i1 @known_positive_nsz_olt_with_zero_constant(double %mag, double %a) {
1193; CHECK-LABEL: @known_positive_nsz_olt_with_zero_constant(
1194; CHECK-NEXT:    [[SQRT:%.*]] = call nsz double @llvm.sqrt.f64(double [[A:%.*]])
1195; CHECK-NEXT:    [[COPYSIGN:%.*]] = call double @llvm.copysign.f64(double [[MAG:%.*]], double [[SQRT]])
1196; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt double [[COPYSIGN]], 0.000000e+00
1197; CHECK-NEXT:    ret i1 [[CMP]]
1198;
1199  %sqrt = call nsz double @llvm.sqrt.f64(double %a)
1200  %copysign = call double @llvm.copysign.f64(double %mag, double %sqrt)
1201  %cmp = fcmp olt double %copysign, 0.0
1202  ret i1 %cmp
1203}
1204
1205define i1 @known_positive_maybe_neg0_olt_with_zero_constant(double %mag, double %a) {
1206; CHECK-LABEL: @known_positive_maybe_neg0_olt_with_zero_constant(
1207; CHECK-NEXT:    [[SQRT:%.*]] = call double @llvm.sqrt.f64(double [[A:%.*]])
1208; CHECK-NEXT:    [[COPYSIGN:%.*]] = call double @llvm.copysign.f64(double [[MAG:%.*]], double [[SQRT]])
1209; CHECK-NEXT:    [[CMP:%.*]] = fcmp olt double [[COPYSIGN]], 0.000000e+00
1210; CHECK-NEXT:    ret i1 [[CMP]]
1211;
1212  %sqrt = call double @llvm.sqrt.f64(double %a)
1213  %copysign = call double @llvm.copysign.f64(double %mag, double %sqrt)
1214  %cmp = fcmp olt double %copysign, 0.0
1215  ret i1 %cmp
1216}
1217
1218define i1 @assumed_positive_olt_with_negative_constant(double %a) {
1219; CHECK-LABEL: @assumed_positive_olt_with_negative_constant(
1220; CHECK-NEXT:    [[ASSUME_CMP:%.*]] = fcmp oge double [[A:%.*]], 0.000000e+00
1221; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME_CMP]])
1222; CHECK-NEXT:    ret i1 false
1223;
1224  %assume.cmp = fcmp oge double %a, 0.0
1225  call void @llvm.assume(i1 %assume.cmp)
1226  %cmp = fcmp olt double %a, -1.0
1227  ret i1 %cmp
1228}
1229
1230define i1 @assumed_positive_ole_with_negative_constant(double %a) {
1231; CHECK-LABEL: @assumed_positive_ole_with_negative_constant(
1232; CHECK-NEXT:    [[ASSUME_CMP:%.*]] = fcmp oge double [[A:%.*]], 0.000000e+00
1233; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME_CMP]])
1234; CHECK-NEXT:    ret i1 false
1235;
1236  %assume.cmp = fcmp oge double %a, 0.0
1237  call void @llvm.assume(i1 %assume.cmp)
1238  %cmp = fcmp ole double %a, -1.0
1239  ret i1 %cmp
1240}
1241
1242define i1 @assumed_positive_oeq_with_negative_constant(double %a) {
1243; CHECK-LABEL: @assumed_positive_oeq_with_negative_constant(
1244; CHECK-NEXT:    [[ASSUME_CMP:%.*]] = fcmp oge double [[A:%.*]], 0.000000e+00
1245; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME_CMP]])
1246; CHECK-NEXT:    ret i1 false
1247;
1248  %assume.cmp = fcmp oge double %a, 0.0
1249  call void @llvm.assume(i1 %assume.cmp)
1250  %cmp = fcmp oeq double %a, -1.0
1251  ret i1 %cmp
1252}
1253
1254define <2 x i1> @known_positive_ole_with_negative_constant_splat_vec(<2 x i32> %a) {
1255; CHECK-LABEL: @known_positive_ole_with_negative_constant_splat_vec(
1256; CHECK-NEXT:    ret <2 x i1> zeroinitializer
1257;
1258  %call = uitofp <2 x i32> %a to <2 x double>
1259  %cmp = fcmp ole <2 x double> %call, <double -2.0, double -2.0>
1260  ret <2 x i1> %cmp
1261}
1262
1263define i1 @known_positive_ugt_with_negative_constant(i32 %a) {
1264; CHECK-LABEL: @known_positive_ugt_with_negative_constant(
1265; CHECK-NEXT:    ret i1 true
1266;
1267  %call = uitofp i32 %a to float
1268  %cmp = fcmp ugt float %call, -3.0
1269  ret i1 %cmp
1270}
1271
1272define i1 @assumed_positive_ugt_with_negative_constant(float %a) {
1273; CHECK-LABEL: @assumed_positive_ugt_with_negative_constant(
1274; CHECK-NEXT:    [[ASSUME_CMP:%.*]] = fcmp ogt float [[A:%.*]], 0.000000e+00
1275; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME_CMP]])
1276; CHECK-NEXT:    ret i1 true
1277;
1278  %assume.cmp = fcmp ogt float %a, 0.0
1279  call void @llvm.assume(i1 %assume.cmp)
1280  %cmp = fcmp ugt float %a, -3.0
1281  ret i1 %cmp
1282}
1283
1284define i1 @assumed_positive_uge_with_negative_constant(float %a) {
1285; CHECK-LABEL: @assumed_positive_uge_with_negative_constant(
1286; CHECK-NEXT:    [[ASSUME_CMP:%.*]] = fcmp ogt float [[A:%.*]], 0.000000e+00
1287; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME_CMP]])
1288; CHECK-NEXT:    ret i1 true
1289;
1290  %assume.cmp = fcmp ogt float %a, 0.0
1291  call void @llvm.assume(i1 %assume.cmp)
1292  %cmp = fcmp uge float %a, -3.0
1293  ret i1 %cmp
1294}
1295
1296define i1 @assumed_positive_une_with_negative_constant(float %a) {
1297; CHECK-LABEL: @assumed_positive_une_with_negative_constant(
1298; CHECK-NEXT:    [[ASSUME_CMP:%.*]] = fcmp ogt float [[A:%.*]], 0.000000e+00
1299; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME_CMP]])
1300; CHECK-NEXT:    ret i1 true
1301;
1302  %assume.cmp = fcmp ogt float %a, 0.0
1303  call void @llvm.assume(i1 %assume.cmp)
1304  %cmp = fcmp une float %a, -3.0
1305  ret i1 %cmp
1306}
1307
1308define <2 x i1> @known_positive_uge_with_negative_constant_splat_vec(<2 x float> %a) {
1309; CHECK-LABEL: @known_positive_uge_with_negative_constant_splat_vec(
1310; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
1311;
1312  %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
1313  %cmp = fcmp uge <2 x float> %call, <float -4.0, float -4.0>
1314  ret <2 x i1> %cmp
1315}
1316
1317define i1 @known_positive_oeq_with_negative_constant(half %a) {
1318; CHECK-LABEL: @known_positive_oeq_with_negative_constant(
1319; CHECK-NEXT:    ret i1 false
1320;
1321  %call = call half @llvm.fabs.f16(half %a)
1322  %cmp = fcmp oeq half %call, -5.0
1323  ret i1 %cmp
1324}
1325
1326define <2 x i1> @known_positive_une_with_negative_constant_splat_vec(<2 x i32> %a) {
1327; CHECK-LABEL: @known_positive_une_with_negative_constant_splat_vec(
1328; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
1329;
1330  %call = uitofp <2 x i32> %a to <2 x half>
1331  %cmp = fcmp une <2 x half> %call, <half -6.0, half -6.0>
1332  ret <2 x i1> %cmp
1333}
1334
1335define i1 @pr58046(i64 %arg) {
1336; CHECK-LABEL: @pr58046(
1337; CHECK-NEXT:    ret i1 true
1338;
1339  %fp = uitofp i64 %arg to double
1340  %mul = fmul double -0.000000e+00, %fp
1341  %div = fdiv double 1.000000e+00, %mul
1342  %cmp = fcmp oeq double %div, 0xFFF0000000000000
1343  ret i1 %cmp
1344}
1345
1346define i1 @nonans1(double %in1, double %in2) {
1347; CHECK-LABEL: @nonans1(
1348; CHECK-NEXT:    ret i1 false
1349;
1350  %cmp = fcmp nnan uno double %in1, %in2
1351  ret i1 %cmp
1352}
1353
1354define i1 @nonans2(double %in1, double %in2) {
1355; CHECK-LABEL: @nonans2(
1356; CHECK-NEXT:    ret i1 true
1357;
1358  %cmp = fcmp nnan ord double %in1, %in2
1359  ret i1 %cmp
1360}
1361
1362define <2 x i1> @orderedCompareWithNaNVector(<2 x double> %A) {
1363; CHECK-LABEL: @orderedCompareWithNaNVector(
1364; CHECK-NEXT:    ret <2 x i1> zeroinitializer
1365;
1366  %cmp = fcmp olt <2 x double> %A, <double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF>
1367  ret <2 x i1> %cmp
1368}
1369
1370define <2 x i1> @orderedCompareWithNaNVector_poison_elt(<2 x double> %A) {
1371; CHECK-LABEL: @orderedCompareWithNaNVector_poison_elt(
1372; CHECK-NEXT:    ret <2 x i1> zeroinitializer
1373;
1374  %cmp = fcmp olt <2 x double> %A, <double 0xFFFFFFFFFFFFFFFF, double poison>
1375  ret <2 x i1> %cmp
1376}
1377
1378define <2 x i1> @unorderedCompareWithNaNVector_poison_elt(<2 x double> %A) {
1379; CHECK-LABEL: @unorderedCompareWithNaNVector_poison_elt(
1380; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
1381;
1382  %cmp = fcmp ult <2 x double> %A, <double poison, double 0xFFFFFFFFFFFFFFFF>
1383  ret <2 x i1> %cmp
1384}
1385
1386define i1 @is_infinite(float %x) {
1387; CHECK-LABEL: @is_infinite(
1388; CHECK-NEXT:    ret i1 false
1389;
1390  %xabs = call ninf float @llvm.fabs.f32(float %x)
1391  %r = fcmp oeq float %xabs, 0x7FF0000000000000
1392  ret i1 %r
1393}
1394
1395define i1 @is_infinite_assumed_finite(float %x) {
1396; CHECK-LABEL: @is_infinite_assumed_finite(
1397; CHECK-NEXT:    [[XABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
1398; CHECK-NEXT:    [[NOT_INF:%.*]] = fcmp one float [[XABS]], 0x7FF0000000000000
1399; CHECK-NEXT:    call void @llvm.assume(i1 [[NOT_INF]])
1400; CHECK-NEXT:    ret i1 false
1401;
1402  %xabs = call float @llvm.fabs.f32(float %x)
1403  %not.inf = fcmp one float %xabs, 0x7FF0000000000000
1404  call void @llvm.assume(i1 %not.inf)
1405  %r = fcmp oeq float %xabs, 0x7FF0000000000000
1406  ret i1 %r
1407}
1408
1409define i1 @une_inf_assumed_not_inf(float %x) {
1410; CHECK-LABEL: @une_inf_assumed_not_inf(
1411; CHECK-NEXT:    [[XABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
1412; CHECK-NEXT:    [[NOT_INF:%.*]] = fcmp one float [[XABS]], 0x7FF0000000000000
1413; CHECK-NEXT:    call void @llvm.assume(i1 [[NOT_INF]])
1414; CHECK-NEXT:    ret i1 true
1415;
1416  %xabs = call float @llvm.fabs.f32(float %x)
1417  %not.inf = fcmp one float %xabs, 0x7FF0000000000000
1418  call void @llvm.assume(i1 %not.inf)
1419  %r = fcmp une float %xabs, 0x7FF0000000000000
1420  ret i1 %r
1421}
1422
1423define <2 x i1> @is_infinite_neg(<2 x float> %x) {
1424; CHECK-LABEL: @is_infinite_neg(
1425; CHECK-NEXT:    ret <2 x i1> zeroinitializer
1426;
1427  %x42 = fadd ninf <2 x float> %x, <float 42.0, float 42.0>
1428  %r = fcmp oeq <2 x float> %x42, <float 0xFFF0000000000000, float 0xFFF0000000000000>
1429  ret <2 x i1> %r
1430}
1431
1432; Negative test - but this could be reduced to 'uno' outside of instsimplify.
1433
1434define i1 @is_infinite_or_nan(float %x) {
1435; CHECK-LABEL: @is_infinite_or_nan(
1436; CHECK-NEXT:    [[X42:%.*]] = fadd ninf float [[X:%.*]], 4.200000e+01
1437; CHECK-NEXT:    [[R:%.*]] = fcmp ueq float [[X42]], 0xFFF0000000000000
1438; CHECK-NEXT:    ret i1 [[R]]
1439;
1440  %x42 = fadd ninf float %x, 42.0
1441  %r = fcmp ueq float %x42, 0xFFF0000000000000
1442  ret i1 %r
1443}
1444
1445define i1 @is_infinite_or_nan2(float %x) {
1446; CHECK-LABEL: @is_infinite_or_nan2(
1447; CHECK-NEXT:    ret i1 false
1448;
1449  %xabs = call nnan ninf float @llvm.fabs.f32(float %x)
1450  %r = fcmp ueq float %xabs, 0x7FF0000000000000
1451  ret i1 %r
1452}
1453
1454define i1 @is_infinite_or_nan2_assume(float %x) {
1455; CHECK-LABEL: @is_infinite_or_nan2_assume(
1456; CHECK-NEXT:    [[XABS:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
1457; CHECK-NEXT:    [[IS_INF_OR_NAN:%.*]] = fcmp one float [[XABS]], 0x7FF0000000000000
1458; CHECK-NEXT:    call void @llvm.assume(i1 [[IS_INF_OR_NAN]])
1459; CHECK-NEXT:    ret i1 false
1460;
1461  %xabs = call float @llvm.fabs.f32(float %x)
1462  %is.inf.or.nan = fcmp one float %xabs, 0x7FF0000000000000
1463  call void @llvm.assume(i1 %is.inf.or.nan)
1464  %r = fcmp ueq float %xabs, 0x7FF0000000000000
1465  ret i1 %r
1466}
1467
1468define <2 x i1> @is_infinite_neg_or_nan(<2 x float> %x) {
1469; CHECK-LABEL: @is_infinite_neg_or_nan(
1470; CHECK-NEXT:    ret <2 x i1> zeroinitializer
1471;
1472  %x42 = fadd nnan ninf <2 x float> %x, <float 42.0, float 42.0>
1473  %r = fcmp ueq <2 x float> %x42, <float 0xFFF0000000000000, float 0xFFF0000000000000>
1474  ret <2 x i1> %r
1475}
1476
1477define i1 @is_finite_or_nan(i1 %c, double %x) {
1478; CHECK-LABEL: @is_finite_or_nan(
1479; CHECK-NEXT:    ret i1 true
1480;
1481  %xx = fmul ninf double %x, %x
1482  %s = select i1 %c, double 42.0, double %xx
1483  %r = fcmp une double %s, 0x7FF0000000000000
1484  ret i1 %r
1485}
1486
1487define <2 x i1> @is_finite_or_nan_commute(<2 x i8> %x) {
1488; CHECK-LABEL: @is_finite_or_nan_commute(
1489; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
1490;
1491  %cast = uitofp <2 x i8> %x to <2 x float>
1492  %r = fcmp une <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>, %cast
1493  ret <2 x i1> %r
1494}
1495
1496; Negative test - but this could be reduced to 'ord' outside of instsimplify.
1497
1498define i1 @is_finite_and_ordered(double %x) {
1499; CHECK-LABEL: @is_finite_and_ordered(
1500; CHECK-NEXT:    [[XX:%.*]] = fmul ninf double [[X:%.*]], [[X]]
1501; CHECK-NEXT:    [[R:%.*]] = fcmp one double [[XX]], 0x7FF0000000000000
1502; CHECK-NEXT:    ret i1 [[R]]
1503;
1504  %xx = fmul ninf double %x, %x
1505  %r = fcmp one double %xx, 0x7FF0000000000000
1506  ret i1 %r
1507}
1508
1509define i1 @is_finite(i1 %c, double %x) {
1510; CHECK-LABEL: @is_finite(
1511; CHECK-NEXT:    ret i1 true
1512;
1513  %xx = fmul nnan ninf double %x, %x
1514  %s = select i1 %c, double 42.0, double %xx
1515  %r = fcmp one double %s, 0x7FF0000000000000
1516  ret i1 %r
1517}
1518
1519define i1 @is_finite_assume(i1 %c, double %x) {
1520; CHECK-LABEL: @is_finite_assume(
1521; CHECK-NEXT:    [[XABS:%.*]] = call double @llvm.fabs.f64(double [[X:%.*]])
1522; CHECK-NEXT:    [[IS_INF_OR_NAN:%.*]] = fcmp one double [[XABS]], 0x7FF0000000000000
1523; CHECK-NEXT:    call void @llvm.assume(i1 [[IS_INF_OR_NAN]])
1524; CHECK-NEXT:    ret i1 true
1525;
1526  %xabs = call double @llvm.fabs.f64(double %x)
1527  %is.inf.or.nan = fcmp one double %xabs, 0x7FF0000000000000
1528  call void @llvm.assume(i1 %is.inf.or.nan)
1529  %s = select i1 %c, double 42.0, double %x
1530  %r = fcmp one double %s, 0x7FF0000000000000
1531  ret i1 %r
1532}
1533
1534define <2 x i1> @is_finite_commute(<2 x i8> %x) {
1535; CHECK-LABEL: @is_finite_commute(
1536; CHECK-NEXT:    ret <2 x i1> splat (i1 true)
1537;
1538  %cast = uitofp <2 x i8> %x to <2 x float>
1539  %r = fcmp one <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>, %cast
1540  ret <2 x i1> %r
1541}
1542
1543define i1 @fcmp_oge_0_assumed_oge_zero(float %x) {
1544; CHECK-LABEL: @fcmp_oge_0_assumed_oge_zero(
1545; CHECK-NEXT:    [[ASSUME_CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
1546; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME_CMP]])
1547; CHECK-NEXT:    ret i1 true
1548;
1549  %assume.cmp = fcmp oge float %x, 0.0
1550  call void @llvm.assume(i1 %assume.cmp)
1551  %r = fcmp oge float %x, 0.000000e+00
1552  ret i1 %r
1553}
1554
1555define i1 @fcmp_ult_0_assumed_oge_zero(float %x) {
1556; CHECK-LABEL: @fcmp_ult_0_assumed_oge_zero(
1557; CHECK-NEXT:    [[ASSUME_CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
1558; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME_CMP]])
1559; CHECK-NEXT:    ret i1 false
1560;
1561  %assume.cmp = fcmp oge float %x, 0.0
1562  call void @llvm.assume(i1 %assume.cmp)
1563  %r = fcmp ult float %x, 0.000000e+00
1564  ret i1 %r
1565}
1566
1567define i1 @fcmp_uge_0_assumed_oge_zero(float %x) {
1568; CHECK-LABEL: @fcmp_uge_0_assumed_oge_zero(
1569; CHECK-NEXT:    [[ASSUME_CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
1570; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME_CMP]])
1571; CHECK-NEXT:    ret i1 true
1572;
1573  %assume.cmp = fcmp oge float %x, 0.0
1574  call void @llvm.assume(i1 %assume.cmp)
1575  %r = fcmp uge float %x, 0.000000e+00
1576  ret i1 %r
1577}
1578
1579define i1 @fcmp_olt_0_assumed_oge_zero(float %x) {
1580; CHECK-LABEL: @fcmp_olt_0_assumed_oge_zero(
1581; CHECK-NEXT:    [[ASSUME_CMP:%.*]] = fcmp oge float [[X:%.*]], 0.000000e+00
1582; CHECK-NEXT:    call void @llvm.assume(i1 [[ASSUME_CMP]])
1583; CHECK-NEXT:    ret i1 false
1584;
1585  %assume.cmp = fcmp oge float %x, 0.0
1586  call void @llvm.assume(i1 %assume.cmp)
1587  %r = fcmp olt float %x, 0.000000e+00
1588  ret i1 %r
1589}
1590
1591define i1 @ogt_zero_fabs_select_negone_or_pinf(i1 %cond) {
1592; CHECK-LABEL: @ogt_zero_fabs_select_negone_or_pinf(
1593; CHECK-NEXT:  entry:
1594; CHECK-NEXT:    ret i1 true
1595;
1596entry:
1597  %select = select i1 %cond, float -1.0, float 0x7FF0000000000000
1598  %fabs = call float @llvm.fabs.f32(float %select)
1599  %one = fcmp ogt float %fabs, 0.0
1600  ret i1 %one
1601}
1602
1603define i1 @ogt_zero_fabs_select_one_or_ninf(i1 %cond) {
1604; CHECK-LABEL: @ogt_zero_fabs_select_one_or_ninf(
1605; CHECK-NEXT:  entry:
1606; CHECK-NEXT:    ret i1 true
1607;
1608entry:
1609  %select = select i1 %cond, float 1.0, float 0xFFF0000000000000
1610  %fabs = call float @llvm.fabs.f32(float %select)
1611  %one = fcmp ogt float %fabs, 0.0
1612  ret i1 %one
1613}
1614
1615; Make sure we recognize fcmp < 0 is recognized as impossible here when simplifying the fcmp
1616define float @fast_square_must_be_positive_ieee(float %arg, float %arg1) {
1617; CHECK-LABEL: @fast_square_must_be_positive_ieee(
1618; CHECK-NEXT:  bb:
1619; CHECK-NEXT:    [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
1620; CHECK-NEXT:    [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
1621; CHECK-NEXT:    [[I3:%.*]] = fadd float [[I2]], [[I]]
1622; CHECK-NEXT:    ret float [[I3]]
1623;
1624bb:
1625  %i = fmul float %arg, %arg
1626  %i2 = fmul float %arg1, %arg1
1627  %i3 = fadd float %i2, %i
1628  %i4 = fcmp olt float %i3, 0.000000e+00
1629  %i5 = select i1 %i4, float 0.000000e+00, float %i3
1630  ret float %i5
1631}
1632
1633; Make sure we recognize fcmp < 0 is recognized as impossible here when simplifying the fcmp
1634define float @fast_square_must_be_positive_ieee_nnan(float %arg, float %arg1) {
1635; CHECK-LABEL: @fast_square_must_be_positive_ieee_nnan(
1636; CHECK-NEXT:  bb:
1637; CHECK-NEXT:    [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
1638; CHECK-NEXT:    [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
1639; CHECK-NEXT:    [[I3:%.*]] = fadd float [[I2]], [[I]]
1640; CHECK-NEXT:    ret float [[I3]]
1641;
1642bb:
1643  %i = fmul float %arg, %arg
1644  %i2 = fmul float %arg1, %arg1
1645  %i3 = fadd float %i2, %i
1646  %i4 = fcmp nnan olt float %i3, 0.000000e+00
1647  %i5 = select i1 %i4, float 0.000000e+00, float %i3
1648  ret float %i5
1649}
1650
1651; Make sure we recognize fcmp < 0 is recognized as impossible here when simplifying the fcmp
1652define float @fast_square_must_be_positive_daz(float %arg, float %arg1) #0 {
1653; CHECK-LABEL: @fast_square_must_be_positive_daz(
1654; CHECK-NEXT:  bb:
1655; CHECK-NEXT:    [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
1656; CHECK-NEXT:    [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
1657; CHECK-NEXT:    [[I3:%.*]] = fadd float [[I2]], [[I]]
1658; CHECK-NEXT:    ret float [[I3]]
1659;
1660bb:
1661  %i = fmul float %arg, %arg
1662  %i2 = fmul float %arg1, %arg1
1663  %i3 = fadd float %i2, %i
1664  %i4 = fcmp olt float %i3, 0.000000e+00
1665  %i5 = select i1 %i4, float 0.000000e+00, float %i3
1666  ret float %i5
1667}
1668
1669; Make sure we recognize fcmp < 0 is recognized as impossible here when simplifying the fcmp
1670define float @fast_square_must_be_positive_daz_nnan(float %arg, float %arg1) #0 {
1671; CHECK-LABEL: @fast_square_must_be_positive_daz_nnan(
1672; CHECK-NEXT:  bb:
1673; CHECK-NEXT:    [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
1674; CHECK-NEXT:    [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
1675; CHECK-NEXT:    [[I3:%.*]] = fadd float [[I2]], [[I]]
1676; CHECK-NEXT:    ret float [[I3]]
1677;
1678bb:
1679  %i = fmul float %arg, %arg
1680  %i2 = fmul float %arg1, %arg1
1681  %i3 = fadd float %i2, %i
1682  %i4 = fcmp nnan olt float %i3, 0.000000e+00
1683  %i5 = select i1 %i4, float 0.000000e+00, float %i3
1684  ret float %i5
1685}
1686
1687; Make the compare to negative constant is folded out
1688define float @must_be_olt_negative_constant_daz(float %arg, float %arg1) #0 {
1689; CHECK-LABEL: @must_be_olt_negative_constant_daz(
1690; CHECK-NEXT:  bb:
1691; CHECK-NEXT:    [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
1692; CHECK-NEXT:    [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
1693; CHECK-NEXT:    [[I3:%.*]] = fadd float [[I2]], [[I]]
1694; CHECK-NEXT:    ret float [[I3]]
1695;
1696bb:
1697  %i = fmul float %arg, %arg
1698  %i2 = fmul float %arg1, %arg1
1699  %i3 = fadd float %i2, %i
1700  %i4 = fcmp olt float %i3, -1.0
1701  %i5 = select i1 %i4, float 0.000000e+00, float %i3
1702  ret float %i5
1703}
1704
1705; Make the compare to negative constant is folded out
1706define float @must_be_olt_negative_constant_daz_nnan(float %arg, float %arg1) #0 {
1707; CHECK-LABEL: @must_be_olt_negative_constant_daz_nnan(
1708; CHECK-NEXT:  bb:
1709; CHECK-NEXT:    [[I:%.*]] = fmul float [[ARG:%.*]], [[ARG]]
1710; CHECK-NEXT:    [[I2:%.*]] = fmul float [[ARG1:%.*]], [[ARG1]]
1711; CHECK-NEXT:    [[I3:%.*]] = fadd float [[I2]], [[I]]
1712; CHECK-NEXT:    ret float [[I3]]
1713;
1714bb:
1715  %i = fmul float %arg, %arg
1716  %i2 = fmul float %arg1, %arg1
1717  %i3 = fadd float %i2, %i
1718  %i4 = fcmp nnan olt float %i3, -1.0
1719  %i5 = select i1 %i4, float 0.000000e+00, float %i3
1720  ret float %i5
1721}
1722
1723define i1 @is_olt_smallest_normal_dynamic(float %x) "denormal-fp-math"="dynamic,dynamic" {
1724; CHECK-LABEL: @is_olt_smallest_normal_dynamic(
1725; CHECK-NEXT:    [[IS_DENORM_OR_ZERO:%.*]] = fcmp olt float [[X:%.*]], 0x3810000000000000
1726; CHECK-NEXT:    ret i1 [[IS_DENORM_OR_ZERO]]
1727;
1728  %is.denorm.or.zero = fcmp olt float %x, 0x3810000000000000
1729  ret i1 %is.denorm.or.zero
1730}
1731
1732define i1 @is_olt_smallest_normal_ieee(float %x) "denormal-fp-math"="dynamic,ieee" {
1733; CHECK-LABEL: @is_olt_smallest_normal_ieee(
1734; CHECK-NEXT:    [[IS_DENORM_OR_ZERO:%.*]] = fcmp olt float [[X:%.*]], 0x3810000000000000
1735; CHECK-NEXT:    ret i1 [[IS_DENORM_OR_ZERO]]
1736;
1737  %is.denorm.or.zero = fcmp olt float %x, 0x3810000000000000
1738  ret i1 %is.denorm.or.zero
1739}
1740
1741define i1 @is_olt_smallest_normal_preserve_sign(float %x) "denormal-fp-math"="dynamic,preserve-sign" {
1742; CHECK-LABEL: @is_olt_smallest_normal_preserve_sign(
1743; CHECK-NEXT:    [[IS_DENORM_OR_ZERO:%.*]] = fcmp olt float [[X:%.*]], 0x3810000000000000
1744; CHECK-NEXT:    ret i1 [[IS_DENORM_OR_ZERO]]
1745;
1746  %is.denorm.or.zero = fcmp olt float %x, 0x3810000000000000
1747  ret i1 %is.denorm.or.zero
1748}
1749
1750define i1 @is_olt_smallest_normal_positive_zero(float %x) "denormal-fp-math"="dynamic,positive-zero" {
1751; CHECK-LABEL: @is_olt_smallest_normal_positive_zero(
1752; CHECK-NEXT:    [[IS_DENORM_OR_ZERO:%.*]] = fcmp olt float [[X:%.*]], 0x3810000000000000
1753; CHECK-NEXT:    ret i1 [[IS_DENORM_OR_ZERO]]
1754;
1755  %is.denorm.or.zero = fcmp olt float %x, 0x3810000000000000
1756  ret i1 %is.denorm.or.zero
1757}
1758
1759define i1 @is_fabs_olt_smallest_normal_dynamic(float %x) "denormal-fp-math"="dynamic,dynamic" {
1760; CHECK-LABEL: @is_fabs_olt_smallest_normal_dynamic(
1761; CHECK-NEXT:    [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
1762; CHECK-NEXT:    [[IS_DENORM_OR_ZERO:%.*]] = fcmp olt float [[FABS_X]], 0x3810000000000000
1763; CHECK-NEXT:    ret i1 [[IS_DENORM_OR_ZERO]]
1764;
1765  %fabs.x = call float @llvm.fabs.f32(float %x)
1766  %is.denorm.or.zero = fcmp olt float %fabs.x, 0x3810000000000000
1767  ret i1 %is.denorm.or.zero
1768}
1769
1770define i1 @is_fabs_olt_smallest_normal_ieee(float %x) "denormal-fp-math"="dynamic,ieee" {
1771; CHECK-LABEL: @is_fabs_olt_smallest_normal_ieee(
1772; CHECK-NEXT:    [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
1773; CHECK-NEXT:    [[IS_DENORM_OR_ZERO:%.*]] = fcmp olt float [[FABS_X]], 0x3810000000000000
1774; CHECK-NEXT:    ret i1 [[IS_DENORM_OR_ZERO]]
1775;
1776  %fabs.x = call float @llvm.fabs.f32(float %x)
1777  %is.denorm.or.zero = fcmp olt float %fabs.x, 0x3810000000000000
1778  ret i1 %is.denorm.or.zero
1779}
1780
1781define i1 @is_fabs_olt_smallest_normal_preserve_sign(float %x) "denormal-fp-math"="dynamic,preserve-sign" {
1782; CHECK-LABEL: @is_fabs_olt_smallest_normal_preserve_sign(
1783; CHECK-NEXT:    [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
1784; CHECK-NEXT:    [[IS_DENORM_OR_ZERO:%.*]] = fcmp olt float [[FABS_X]], 0x3810000000000000
1785; CHECK-NEXT:    ret i1 [[IS_DENORM_OR_ZERO]]
1786;
1787  %fabs.x = call float @llvm.fabs.f32(float %x)
1788  %is.denorm.or.zero = fcmp olt float %fabs.x, 0x3810000000000000
1789  ret i1 %is.denorm.or.zero
1790}
1791
1792define i1 @is_fabs_olt_smallest_normal_positive_zero(float %x) "denormal-fp-math"="dynamic,positive-zero" {
1793; CHECK-LABEL: @is_fabs_olt_smallest_normal_positive_zero(
1794; CHECK-NEXT:    [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X:%.*]])
1795; CHECK-NEXT:    [[IS_DENORM_OR_ZERO:%.*]] = fcmp olt float [[FABS_X]], 0x3810000000000000
1796; CHECK-NEXT:    ret i1 [[IS_DENORM_OR_ZERO]]
1797;
1798  %fabs.x = call float @llvm.fabs.f32(float %x)
1799  %is.denorm.or.zero = fcmp olt float %fabs.x, 0x3810000000000000
1800  ret i1 %is.denorm.or.zero
1801}
1802
1803
1804declare <2 x double> @llvm.fabs.v2f64(<2 x double>)
1805declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
1806declare <2 x float> @llvm.maxnum.v2f32(<2 x float>, <2 x float>)
1807declare <2 x float> @llvm.minnum.v2f32(<2 x float>, <2 x float>)
1808declare <3 x float> @llvm.fabs.v3f32(<3 x float>)
1809declare double @llvm.exp2.f64(double)
1810declare double @llvm.fabs.f64(double)
1811declare double @llvm.powi.f64.i32(double, i32)
1812declare float @llvm.exp.f32(float)
1813declare float @llvm.fabs.f32(float)
1814declare float @llvm.fma.f32(float, float, float)
1815declare float @llvm.maximum.f32(float, float)
1816declare float @llvm.maxnum.f32(float, float)
1817declare float @llvm.minnum.f32(float, float)
1818declare float @llvm.sqrt.f32(float)
1819declare double @llvm.sqrt.f64(double)
1820declare double @llvm.copysign.f64(double, double)
1821declare half @llvm.fabs.f16(half)
1822declare void @llvm.assume(i1 noundef)
1823
1824attributes #0 = { "denormal-fp-math"="preserve-sign,preserve-sign" }
1825