1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -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 @inf1(double %arg) {
15; CHECK-LABEL: @inf1(
16; CHECK-NEXT:    ret i1 true
17;
18  %tmp = fcmp ule double %arg, 0x7FF0000000000000
19  ret i1 %tmp
20}
21
22; Negative infinity
23
24define i1 @ninf0(double %arg) {
25; CHECK-LABEL: @ninf0(
26; CHECK-NEXT:    ret i1 false
27;
28  %tmp = fcmp olt double %arg, 0xFFF0000000000000
29  ret i1 %tmp
30}
31
32define i1 @ninf1(double %arg) {
33; CHECK-LABEL: @ninf1(
34; CHECK-NEXT:    ret i1 true
35;
36  %tmp = fcmp uge double %arg, 0xFFF0000000000000
37  ret i1 %tmp
38}
39
40; NaNs
41
42define i1 @nan0(double %arg) {
43; CHECK-LABEL: @nan0(
44; CHECK-NEXT:    ret i1 false
45;
46  %tmp = fcmp ord double %arg, 0x7FF00000FFFFFFFF
47  ret i1 %tmp
48}
49
50define i1 @nan1(double %arg) {
51; CHECK-LABEL: @nan1(
52; CHECK-NEXT:    ret i1 false
53;
54  %tmp = fcmp oeq double %arg, 0x7FF00000FFFFFFFF
55  ret i1 %tmp
56}
57
58define i1 @nan2(double %arg) {
59; CHECK-LABEL: @nan2(
60; CHECK-NEXT:    ret i1 false
61;
62  %tmp = fcmp olt double %arg, 0x7FF00000FFFFFFFF
63  ret i1 %tmp
64}
65
66define i1 @nan3(double %arg) {
67; CHECK-LABEL: @nan3(
68; CHECK-NEXT:    ret i1 true
69;
70  %tmp = fcmp uno double %arg, 0x7FF00000FFFFFFFF
71  ret i1 %tmp
72}
73
74define i1 @nan4(double %arg) {
75; CHECK-LABEL: @nan4(
76; CHECK-NEXT:    ret i1 true
77;
78  %tmp = fcmp une double %arg, 0x7FF00000FFFFFFFF
79  ret i1 %tmp
80}
81
82define i1 @nan5(double %arg) {
83; CHECK-LABEL: @nan5(
84; CHECK-NEXT:    ret i1 true
85;
86  %tmp = fcmp ult double %arg, 0x7FF00000FFFFFFFF
87  ret i1 %tmp
88}
89
90; Negative NaN.
91
92define i1 @nnan0(double %arg) {
93; CHECK-LABEL: @nnan0(
94; CHECK-NEXT:    ret i1 false
95;
96  %tmp = fcmp ord double %arg, 0xFFF00000FFFFFFFF
97  ret i1 %tmp
98}
99
100define i1 @nnan1(double %arg) {
101; CHECK-LABEL: @nnan1(
102; CHECK-NEXT:    ret i1 false
103;
104  %tmp = fcmp oeq double %arg, 0xFFF00000FFFFFFFF
105  ret i1 %tmp
106}
107
108define i1 @nnan2(double %arg) {
109; CHECK-LABEL: @nnan2(
110; CHECK-NEXT:    ret i1 false
111;
112  %tmp = fcmp olt double %arg, 0xFFF00000FFFFFFFF
113  ret i1 %tmp
114}
115
116define i1 @nnan3(double %arg) {
117; CHECK-LABEL: @nnan3(
118; CHECK-NEXT:    ret i1 true
119;
120  %tmp = fcmp uno double %arg, 0xFFF00000FFFFFFFF
121  ret i1 %tmp
122}
123
124define i1 @nnan4(double %arg) {
125; CHECK-LABEL: @nnan4(
126; CHECK-NEXT:    ret i1 true
127;
128  %tmp = fcmp une double %arg, 0xFFF00000FFFFFFFF
129  ret i1 %tmp
130}
131
132define i1 @nnan5(double %arg) {
133; CHECK-LABEL: @nnan5(
134; CHECK-NEXT:    ret i1 true
135;
136  %tmp = fcmp ult double %arg, 0xFFF00000FFFFFFFF
137  ret i1 %tmp
138}
139
140; Negative zero.
141
142define i1 @nzero0() {
143; CHECK-LABEL: @nzero0(
144; CHECK-NEXT:    ret i1 true
145;
146  %tmp = fcmp oeq double 0.0, -0.0
147  ret i1 %tmp
148}
149
150define i1 @nzero1() {
151; CHECK-LABEL: @nzero1(
152; CHECK-NEXT:    ret i1 false
153;
154  %tmp = fcmp ogt double 0.0, -0.0
155  ret i1 %tmp
156}
157
158; No enlightenment here.
159
160define i1 @one_with_self(double %arg) {
161; CHECK-LABEL: @one_with_self(
162; CHECK-NEXT:    ret i1 false
163;
164  %tmp = fcmp one double %arg, %arg
165  ret i1 %tmp
166}
167
168; These tests choose arbitrarily between float and double,
169; and between uge and olt, to give reasonble coverage
170; without combinatorial explosion.
171
172declare half @llvm.fabs.f16(half)
173declare float @llvm.fabs.f32(float)
174declare double @llvm.fabs.f64(double)
175declare <2 x float> @llvm.fabs.v2f32(<2 x float>)
176declare <2 x double> @llvm.fabs.v2f64(<2 x double>)
177declare float @llvm.sqrt.f32(float)
178declare double @llvm.powi.f64(double,i32)
179declare float @llvm.exp.f32(float)
180declare float @llvm.minnum.f32(float, float)
181declare float @llvm.maxnum.f32(float, float)
182declare double @llvm.exp2.f64(double)
183declare float @llvm.fma.f32(float,float,float)
184
185declare void @expect_equal(i1,i1)
186
187define i1 @orderedLessZeroTree(float,float,float,float) {
188; CHECK-LABEL: @orderedLessZeroTree(
189; CHECK-NEXT:    ret i1 true
190;
191  %square = fmul float %0, %0
192  %abs = call float @llvm.fabs.f32(float %1)
193  %sqrt = call float @llvm.sqrt.f32(float %2)
194  %fma = call float @llvm.fma.f32(float %3, float %3, float %sqrt)
195  %div = fdiv float %square, %abs
196  %rem = frem float %sqrt, %fma
197  %add = fadd float %div, %rem
198  %uge = fcmp uge float %add, 0.000000e+00
199  ret i1 %uge
200}
201
202define i1 @orderedLessZeroExpExt(float) {
203; CHECK-LABEL: @orderedLessZeroExpExt(
204; CHECK-NEXT:    ret i1 true
205;
206  %a = call float @llvm.exp.f32(float %0)
207  %b = fpext float %a to double
208  %uge = fcmp uge double %b, 0.000000e+00
209  ret i1 %uge
210}
211
212define i1 @orderedLessZeroExp2Trunc(double) {
213; CHECK-LABEL: @orderedLessZeroExp2Trunc(
214; CHECK-NEXT:    ret i1 false
215;
216  %a = call double @llvm.exp2.f64(double %0)
217  %b = fptrunc double %a to float
218  %olt = fcmp olt float %b, 0.000000e+00
219  ret i1 %olt
220}
221
222define i1 @orderedLessZeroPowi(double,double) {
223; CHECK-LABEL: @orderedLessZeroPowi(
224; CHECK-NEXT:    ret i1 false
225;
226  ; Even constant exponent
227  %a = call double @llvm.powi.f64(double %0, i32 2)
228  %square = fmul double %1, %1
229  ; Odd constant exponent with provably non-negative base
230  %b = call double @llvm.powi.f64(double %square, i32 3)
231  %c = fadd double %a, %b
232  %olt = fcmp olt double %b, 0.000000e+00
233  ret i1 %olt
234}
235
236define i1 @orderedLessZeroUIToFP(i32) {
237; CHECK-LABEL: @orderedLessZeroUIToFP(
238; CHECK-NEXT:    ret i1 true
239;
240  %a = uitofp i32 %0 to float
241  %uge = fcmp uge float %a, 0.000000e+00
242  ret i1 %uge
243}
244
245define i1 @orderedLessZeroSelect(float, float) {
246; CHECK-LABEL: @orderedLessZeroSelect(
247; CHECK-NEXT:    ret i1 true
248;
249  %a = call float @llvm.exp.f32(float %0)
250  %b = call float @llvm.fabs.f32(float %1)
251  %c = fcmp olt float %0, %1
252  %d = select i1 %c, float %a, float %b
253  %e = fadd float %d, 1.0
254  %uge = fcmp uge float %e, 0.000000e+00
255  ret i1 %uge
256}
257
258define i1 @orderedLessZeroMinNum(float, float) {
259; CHECK-LABEL: @orderedLessZeroMinNum(
260; CHECK-NEXT:    ret i1 true
261;
262  %a = call float @llvm.exp.f32(float %0)
263  %b = call float @llvm.fabs.f32(float %1)
264  %c = call float @llvm.minnum.f32(float %a, float %b)
265  %uge = fcmp uge float %c, 0.000000e+00
266  ret i1 %uge
267}
268
269; PR37776: https://bugs.llvm.org/show_bug.cgi?id=37776
270; exp() may return nan, leaving %1 as the unknown result, so we can't simplify.
271
272define i1 @orderedLessZeroMaxNum(float, float) {
273; CHECK-LABEL: @orderedLessZeroMaxNum(
274; CHECK-NEXT:    [[A:%.*]] = call float @llvm.exp.f32(float [[TMP0:%.*]])
275; CHECK-NEXT:    [[B:%.*]] = call float @llvm.maxnum.f32(float [[A]], float [[TMP1:%.*]])
276; CHECK-NEXT:    [[UGE:%.*]] = fcmp uge float [[B]], 0.000000e+00
277; CHECK-NEXT:    ret i1 [[UGE]]
278;
279  %a = call float @llvm.exp.f32(float %0)
280  %b = call float @llvm.maxnum.f32(float %a, float %1)
281  %uge = fcmp uge float %b, 0.000000e+00
282  ret i1 %uge
283}
284
285define i1 @known_positive_olt_with_negative_constant(double %a) {
286; CHECK-LABEL: @known_positive_olt_with_negative_constant(
287; CHECK-NEXT:    ret i1 false
288;
289  %call = call double @llvm.fabs.f64(double %a)
290  %cmp = fcmp olt double %call, -1.0
291  ret i1 %cmp
292}
293
294define <2 x i1> @known_positive_ole_with_negative_constant_splat_vec(<2 x i32> %a) {
295; CHECK-LABEL: @known_positive_ole_with_negative_constant_splat_vec(
296; CHECK-NEXT:    ret <2 x i1> zeroinitializer
297;
298  %call = uitofp <2 x i32> %a to <2 x double>
299  %cmp = fcmp ole <2 x double> %call, <double -2.0, double -2.0>
300  ret <2 x i1> %cmp
301}
302
303define i1 @known_positive_ugt_with_negative_constant(i32 %a) {
304; CHECK-LABEL: @known_positive_ugt_with_negative_constant(
305; CHECK-NEXT:    ret i1 true
306;
307  %call = uitofp i32 %a to float
308  %cmp = fcmp ugt float %call, -3.0
309  ret i1 %cmp
310}
311
312define <2 x i1> @known_positive_uge_with_negative_constant_splat_vec(<2 x float> %a) {
313; CHECK-LABEL: @known_positive_uge_with_negative_constant_splat_vec(
314; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
315;
316  %call = call <2 x float> @llvm.fabs.v2f32(<2 x float> %a)
317  %cmp = fcmp uge <2 x float> %call, <float -4.0, float -4.0>
318  ret <2 x i1> %cmp
319}
320
321define i1 @known_positive_oeq_with_negative_constant(half %a) {
322; CHECK-LABEL: @known_positive_oeq_with_negative_constant(
323; CHECK-NEXT:    ret i1 false
324;
325  %call = call half @llvm.fabs.f16(half %a)
326  %cmp = fcmp oeq half %call, -5.0
327  ret i1 %cmp
328}
329
330define <2 x i1> @known_positive_une_with_negative_constant_splat_vec(<2 x i32> %a) {
331; CHECK-LABEL: @known_positive_une_with_negative_constant_splat_vec(
332; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
333;
334  %call = uitofp <2 x i32> %a to <2 x half>
335  %cmp = fcmp une <2 x half> %call, <half -6.0, half -6.0>
336  ret <2 x i1> %cmp
337}
338
339define i1 @nonans1(double %in1, double %in2) {
340; CHECK-LABEL: @nonans1(
341; CHECK-NEXT:    ret i1 false
342;
343  %cmp = fcmp nnan uno double %in1, %in2
344  ret i1 %cmp
345}
346
347define i1 @nonans2(double %in1, double %in2) {
348; CHECK-LABEL: @nonans2(
349; CHECK-NEXT:    ret i1 true
350;
351  %cmp = fcmp nnan ord double %in1, %in2
352  ret i1 %cmp
353}
354
355define <2 x i1> @orderedCompareWithNaNVector(<2 x double> %A) {
356; CHECK-LABEL: @orderedCompareWithNaNVector(
357; CHECK-NEXT:    ret <2 x i1> zeroinitializer
358;
359  %cmp = fcmp olt <2 x double> %A, <double 0xFFFFFFFFFFFFFFFF, double 0xFFFFFFFFFFFFFFFF>
360  ret <2 x i1> %cmp
361}
362
363define <2 x i1> @orderedCompareWithNaNVector_undef_elt(<2 x double> %A) {
364; CHECK-LABEL: @orderedCompareWithNaNVector_undef_elt(
365; CHECK-NEXT:    ret <2 x i1> zeroinitializer
366;
367  %cmp = fcmp olt <2 x double> %A, <double 0xFFFFFFFFFFFFFFFF, double undef>
368  ret <2 x i1> %cmp
369}
370
371define <2 x i1> @unorderedCompareWithNaNVector_undef_elt(<2 x double> %A) {
372; CHECK-LABEL: @unorderedCompareWithNaNVector_undef_elt(
373; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 true>
374;
375  %cmp = fcmp ult <2 x double> %A, <double undef, double 0xFFFFFFFFFFFFFFFF>
376  ret <2 x i1> %cmp
377}
378
379