xref: /llvm-project/llvm/test/Transforms/InstCombine/fcmp-range-check-idiom.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 4
2; RUN: opt -S -passes=instcombine %s | FileCheck %s
3
4declare void @use(i1)
5
6define i1 @test_and_olt(float %x) {
7; CHECK-LABEL: define i1 @test_and_olt(
8; CHECK-SAME: float [[X:%.*]]) {
9; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
10; CHECK-NEXT:    [[COND:%.*]] = fcmp olt float [[TMP1]], 0x3C00000000000000
11; CHECK-NEXT:    ret i1 [[COND]]
12;
13  %cmp1 = fcmp olt float %x, 0x3C00000000000000
14  %cmp2 = fcmp ogt float %x, 0xBC00000000000000
15  %cond = and i1 %cmp1, %cmp2
16  ret i1 %cond
17}
18
19define i1 @test_and_ole(float %x) {
20; CHECK-LABEL: define i1 @test_and_ole(
21; CHECK-SAME: float [[X:%.*]]) {
22; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
23; CHECK-NEXT:    [[COND:%.*]] = fcmp ole float [[TMP1]], 0x3C00000000000000
24; CHECK-NEXT:    ret i1 [[COND]]
25;
26  %cmp1 = fcmp ole float %x, 0x3C00000000000000
27  %cmp2 = fcmp oge float %x, 0xBC00000000000000
28  %cond = and i1 %cmp1, %cmp2
29  ret i1 %cond
30}
31
32define i1 @test_or_ogt(float %x) {
33; CHECK-LABEL: define i1 @test_or_ogt(
34; CHECK-SAME: float [[X:%.*]]) {
35; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
36; CHECK-NEXT:    [[COND:%.*]] = fcmp ogt float [[TMP1]], 0x3C00000000000000
37; CHECK-NEXT:    ret i1 [[COND]]
38;
39  %cmp1 = fcmp ogt float %x, 0x3C00000000000000
40  %cmp2 = fcmp olt float %x, 0xBC00000000000000
41  %cond = or i1 %cmp1, %cmp2
42  ret i1 %cond
43}
44
45define i1 @test_or_oge(float %x) {
46; CHECK-LABEL: define i1 @test_or_oge(
47; CHECK-SAME: float [[X:%.*]]) {
48; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
49; CHECK-NEXT:    [[COND:%.*]] = fcmp oge float [[TMP1]], 0x3C00000000000000
50; CHECK-NEXT:    ret i1 [[COND]]
51;
52  %cmp1 = fcmp oge float %x, 0x3C00000000000000
53  %cmp2 = fcmp ole float %x, 0xBC00000000000000
54  %cond = or i1 %cmp1, %cmp2
55  ret i1 %cond
56}
57
58define i1 @test_and_ult(float %x) {
59; CHECK-LABEL: define i1 @test_and_ult(
60; CHECK-SAME: float [[X:%.*]]) {
61; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
62; CHECK-NEXT:    [[COND:%.*]] = fcmp ult float [[TMP1]], 0x3C00000000000000
63; CHECK-NEXT:    ret i1 [[COND]]
64;
65  %cmp1 = fcmp ult float %x, 0x3C00000000000000
66  %cmp2 = fcmp ugt float %x, 0xBC00000000000000
67  %cond = and i1 %cmp1, %cmp2
68  ret i1 %cond
69}
70
71define i1 @test_and_ule(float %x) {
72; CHECK-LABEL: define i1 @test_and_ule(
73; CHECK-SAME: float [[X:%.*]]) {
74; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
75; CHECK-NEXT:    [[COND:%.*]] = fcmp ule float [[TMP1]], 0x3C00000000000000
76; CHECK-NEXT:    ret i1 [[COND]]
77;
78  %cmp1 = fcmp ule float %x, 0x3C00000000000000
79  %cmp2 = fcmp uge float %x, 0xBC00000000000000
80  %cond = and i1 %cmp1, %cmp2
81  ret i1 %cond
82}
83
84define i1 @test_or_ugt(float %x) {
85; CHECK-LABEL: define i1 @test_or_ugt(
86; CHECK-SAME: float [[X:%.*]]) {
87; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
88; CHECK-NEXT:    [[COND:%.*]] = fcmp ugt float [[TMP1]], 0x3C00000000000000
89; CHECK-NEXT:    ret i1 [[COND]]
90;
91  %cmp1 = fcmp ugt float %x, 0x3C00000000000000
92  %cmp2 = fcmp ult float %x, 0xBC00000000000000
93  %cond = or i1 %cmp1, %cmp2
94  ret i1 %cond
95}
96
97define i1 @test_or_uge(float %x) {
98; CHECK-LABEL: define i1 @test_or_uge(
99; CHECK-SAME: float [[X:%.*]]) {
100; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
101; CHECK-NEXT:    [[COND:%.*]] = fcmp uge float [[TMP1]], 0x3C00000000000000
102; CHECK-NEXT:    ret i1 [[COND]]
103;
104  %cmp1 = fcmp uge float %x, 0x3C00000000000000
105  %cmp2 = fcmp ule float %x, 0xBC00000000000000
106  %cond = or i1 %cmp1, %cmp2
107  ret i1 %cond
108}
109
110define i1 @test_and_olt_commuted(float %x) {
111; CHECK-LABEL: define i1 @test_and_olt_commuted(
112; CHECK-SAME: float [[X:%.*]]) {
113; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
114; CHECK-NEXT:    [[COND:%.*]] = fcmp olt float [[TMP1]], 0x3C00000000000000
115; CHECK-NEXT:    ret i1 [[COND]]
116;
117  %cmp1 = fcmp olt float %x, 0x3C00000000000000
118  %cmp2 = fcmp ogt float %x, 0xBC00000000000000
119  %cond = and i1 %cmp2, %cmp1
120  ret i1 %cond
121}
122
123define i1 @test_and_olt_subnormal(float %x) {
124; CHECK-LABEL: define i1 @test_and_olt_subnormal(
125; CHECK-SAME: float [[X:%.*]]) {
126; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
127; CHECK-NEXT:    [[COND:%.*]] = fcmp olt float [[TMP1]], 0x36A0000000000000
128; CHECK-NEXT:    ret i1 [[COND]]
129;
130  %cmp1 = fcmp olt float %x, 0x36A0000000000000
131  %cmp2 = fcmp ogt float %x, 0xB6A0000000000000
132  %cond = and i1 %cmp1, %cmp2
133  ret i1 %cond
134}
135
136define i1 @test_and_olt_infinity(float %x) {
137; CHECK-LABEL: define i1 @test_and_olt_infinity(
138; CHECK-SAME: float [[X:%.*]]) {
139; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
140; CHECK-NEXT:    [[COND:%.*]] = fcmp one float [[TMP1]], 0x7FF0000000000000
141; CHECK-NEXT:    ret i1 [[COND]]
142;
143  %cmp1 = fcmp olt float %x, 0x7FF0000000000000
144  %cmp2 = fcmp ogt float %x, 0xFFF0000000000000
145  %cond = and i1 %cmp1, %cmp2
146  ret i1 %cond
147}
148
149define i1 @test_and_olt_zero(float %x) {
150; CHECK-LABEL: define i1 @test_and_olt_zero(
151; CHECK-SAME: float [[X:%.*]]) {
152; CHECK-NEXT:    ret i1 false
153;
154  %cmp1 = fcmp olt float %x, 0x0000000000000000
155  %cmp2 = fcmp ogt float %x, 0x8000000000000000
156  %cond = and i1 %cmp1, %cmp2
157  ret i1 %cond
158}
159
160define i1 @test_and_ole_zero(float %x) {
161; CHECK-LABEL: define i1 @test_and_ole_zero(
162; CHECK-SAME: float [[X:%.*]]) {
163; CHECK-NEXT:    [[COND:%.*]] = fcmp oeq float [[X]], 0.000000e+00
164; CHECK-NEXT:    ret i1 [[COND]]
165;
166  %cmp1 = fcmp ole float %x, 0x0000000000000000
167  %cmp2 = fcmp oge float %x, 0x8000000000000000
168  %cond = and i1 %cmp1, %cmp2
169  ret i1 %cond
170}
171
172define i1 @test_and_olt_logical(float %x) {
173; CHECK-LABEL: define i1 @test_and_olt_logical(
174; CHECK-SAME: float [[X:%.*]]) {
175; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
176; CHECK-NEXT:    [[COND:%.*]] = fcmp olt float [[TMP1]], 0x3C00000000000000
177; CHECK-NEXT:    ret i1 [[COND]]
178;
179  %cmp1 = fcmp olt float %x, 0x3C00000000000000
180  %cmp2 = fcmp ogt float %x, 0xBC00000000000000
181  %cond = select i1 %cmp1, i1 %cmp2, i1 false
182  ret i1 %cond
183}
184
185define <2 x i1> @test_and_olt_poison(<2 x float> %x) {
186; CHECK-LABEL: define <2 x i1> @test_and_olt_poison(
187; CHECK-SAME: <2 x float> [[X:%.*]]) {
188; CHECK-NEXT:    [[TMP1:%.*]] = call <2 x float> @llvm.fabs.v2f32(<2 x float> [[X]])
189; CHECK-NEXT:    [[COND:%.*]] = fcmp olt <2 x float> [[TMP1]], splat (float 0x3C00000000000000)
190; CHECK-NEXT:    ret <2 x i1> [[COND]]
191;
192  %cmp1 = fcmp olt <2 x float> %x, <float 0x3C00000000000000, float poison>
193  %cmp2 = fcmp ogt <2 x float> %x, <float 0xBC00000000000000, float poison>
194  %cond = and <2 x i1> %cmp1, %cmp2
195  ret <2 x i1> %cond
196}
197
198define i1 @test_and_olt_nan(float %x) {
199; CHECK-LABEL: define i1 @test_and_olt_nan(
200; CHECK-SAME: float [[X:%.*]]) {
201; CHECK-NEXT:    ret i1 false
202;
203  %cmp1 = fcmp olt float %x, 0x7FF8000000000000
204  %cmp2 = fcmp ogt float %x, 0xFFF8000000000000
205  %cond = and i1 %cmp1, %cmp2
206  ret i1 %cond
207}
208
209define i1 @test_and_ult_nan(float %x) {
210; CHECK-LABEL: define i1 @test_and_ult_nan(
211; CHECK-SAME: float [[X:%.*]]) {
212; CHECK-NEXT:    ret i1 true
213;
214  %cmp1 = fcmp ult float %x, 0x7FF0000020000000
215  %cmp2 = fcmp ugt float %x, 0xFFF0000020000000
216  %cond = and i1 %cmp1, %cmp2
217  ret i1 %cond
218}
219
220define i1 @test_or_ogt_nan(float %x) {
221; CHECK-LABEL: define i1 @test_or_ogt_nan(
222; CHECK-SAME: float [[X:%.*]]) {
223; CHECK-NEXT:    ret i1 false
224;
225  %cmp1 = fcmp ogt float %x, 0x7FF0000020000000
226  %cmp2 = fcmp olt float %x, 0xFFF0000020000000
227  %cond = or i1 %cmp1, %cmp2
228  ret i1 %cond
229}
230
231define i1 @test_or_ugt_nan(float %x) {
232; CHECK-LABEL: define i1 @test_or_ugt_nan(
233; CHECK-SAME: float [[X:%.*]]) {
234; CHECK-NEXT:    ret i1 true
235;
236  %cmp1 = fcmp ugt float %x, 0x7FF0000020000000
237  %cmp2 = fcmp ult float %x, 0xFFF0000020000000
238  %cond = or i1 %cmp1, %cmp2
239  ret i1 %cond
240}
241
242define i1 @test_and_ogt(float %x) {
243; CHECK-LABEL: define i1 @test_and_ogt(
244; CHECK-SAME: float [[X:%.*]]) {
245; CHECK-NEXT:    ret i1 false
246;
247  %cmp1 = fcmp ogt float %x, 0x3C00000000000000
248  %cmp2 = fcmp olt float %x, 0xBC00000000000000
249  %cond = and i1 %cmp1, %cmp2
250  ret i1 %cond
251}
252
253define i1 @test_or_olt(float %x) {
254; CHECK-LABEL: define i1 @test_or_olt(
255; CHECK-SAME: float [[X:%.*]]) {
256; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
257; CHECK-NEXT:    [[COND:%.*]] = fcmp ogt float [[TMP1]], 0xBC00000000000000
258; CHECK-NEXT:    ret i1 [[COND]]
259;
260  %cmp1 = fcmp olt float %x, 0x3C00000000000000
261  %cmp2 = fcmp ogt float %x, 0xBC00000000000000
262  %cond = or i1 %cmp1, %cmp2
263  ret i1 %cond
264}
265
266; Negative tests
267
268define i1 @test_and_olt_multiuse(float %x) {
269; CHECK-LABEL: define i1 @test_and_olt_multiuse(
270; CHECK-SAME: float [[X:%.*]]) {
271; CHECK-NEXT:    [[CMP1:%.*]] = fcmp olt float [[X]], 0x3C00000000000000
272; CHECK-NEXT:    call void @use(i1 [[CMP1]])
273; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ogt float [[X]], 0xBC00000000000000
274; CHECK-NEXT:    [[COND:%.*]] = and i1 [[CMP1]], [[CMP2]]
275; CHECK-NEXT:    ret i1 [[COND]]
276;
277  %cmp1 = fcmp olt float %x, 0x3C00000000000000
278  call void @use(i1 %cmp1)
279  %cmp2 = fcmp ogt float %x, 0xBC00000000000000
280  %cond = and i1 %cmp1, %cmp2
281  ret i1 %cond
282}
283
284define i1 @test_and_olt_mismatched_lhs(float %x, float %y) {
285; CHECK-LABEL: define i1 @test_and_olt_mismatched_lhs(
286; CHECK-SAME: float [[X:%.*]], float [[Y:%.*]]) {
287; CHECK-NEXT:    [[CMP1:%.*]] = fcmp olt float [[X]], 0x3C00000000000000
288; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ogt float [[Y]], 0xBC00000000000000
289; CHECK-NEXT:    [[COND:%.*]] = and i1 [[CMP1]], [[CMP2]]
290; CHECK-NEXT:    ret i1 [[COND]]
291;
292  %cmp1 = fcmp olt float %x, 0x3C00000000000000
293  %cmp2 = fcmp ogt float %y, 0xBC00000000000000
294  %cond = and i1 %cmp1, %cmp2
295  ret i1 %cond
296}
297
298define i1 @test_and_olt_same_sign(float %x) {
299; CHECK-LABEL: define i1 @test_and_olt_same_sign(
300; CHECK-SAME: float [[X:%.*]]) {
301; CHECK-NEXT:    ret i1 false
302;
303  %cmp1 = fcmp olt float %x, 0x3C00000000000000
304  %cmp2 = fcmp ogt float %x, 0x3C00000000000000
305  %cond = and i1 %cmp1, %cmp2
306  ret i1 %cond
307}
308
309define i1 @test_and_olt_mismatched_mag(float %x) {
310; CHECK-LABEL: define i1 @test_and_olt_mismatched_mag(
311; CHECK-SAME: float [[X:%.*]]) {
312; CHECK-NEXT:    [[CMP1:%.*]] = fcmp olt float [[X]], 0x3C80000000000000
313; CHECK-NEXT:    [[CMP2:%.*]] = fcmp ogt float [[X]], 0xBC00000000000000
314; CHECK-NEXT:    [[COND:%.*]] = and i1 [[CMP1]], [[CMP2]]
315; CHECK-NEXT:    ret i1 [[COND]]
316;
317  %cmp1 = fcmp olt float %x, 0x3C80000000000000
318  %cmp2 = fcmp ogt float %x, 0xBC00000000000000
319  %cond = and i1 %cmp1, %cmp2
320  ret i1 %cond
321}
322
323define i1 @test_and_olt_wrong_pred2(float %x) {
324; CHECK-LABEL: define i1 @test_and_olt_wrong_pred2(
325; CHECK-SAME: float [[X:%.*]]) {
326; CHECK-NEXT:    [[CMP1:%.*]] = fcmp olt float [[X]], 0x3C00000000000000
327; CHECK-NEXT:    [[CMP2:%.*]] = fcmp oge float [[X]], 0xBC00000000000000
328; CHECK-NEXT:    [[COND:%.*]] = and i1 [[CMP1]], [[CMP2]]
329; CHECK-NEXT:    ret i1 [[COND]]
330;
331  %cmp1 = fcmp olt float %x, 0x3C00000000000000
332  %cmp2 = fcmp oge float %x, 0xBC00000000000000
333  %cond = and i1 %cmp1, %cmp2
334  ret i1 %cond
335}
336
337define i1 @test_and_olt_fmf_propagation(float %x) {
338; CHECK-LABEL: define i1 @test_and_olt_fmf_propagation(
339; CHECK-SAME: float [[X:%.*]]) {
340; CHECK-NEXT:    [[TMP1:%.*]] = call nnan ninf nsz float @llvm.fabs.f32(float [[X]])
341; CHECK-NEXT:    [[COND:%.*]] = fcmp nnan ninf nsz olt float [[TMP1]], 0x3C00000000000000
342; CHECK-NEXT:    ret i1 [[COND]]
343;
344  %cmp1 = fcmp nsz nnan ninf olt float %x, 0x3C00000000000000
345  %cmp2 = fcmp nsz nnan ninf ogt float %x, 0xBC00000000000000
346  %cond = and i1 %cmp1, %cmp2
347  ret i1 %cond
348}
349
350define i1 @test_and_olt_fmf_propagation_union(float %x) {
351; CHECK-LABEL: define i1 @test_and_olt_fmf_propagation_union(
352; CHECK-SAME: float [[X:%.*]]) {
353; CHECK-NEXT:    [[TMP1:%.*]] = call nnan ninf nsz float @llvm.fabs.f32(float [[X]])
354; CHECK-NEXT:    [[COND:%.*]] = fcmp nnan ninf nsz olt float [[TMP1]], 0x3C00000000000000
355; CHECK-NEXT:    ret i1 [[COND]]
356;
357  %cmp1 = fcmp nnan ninf olt float %x, 0x3C00000000000000
358  %cmp2 = fcmp nsz nnan ogt float %x, 0xBC00000000000000
359  %cond = and i1 %cmp1, %cmp2
360  ret i1 %cond
361}
362
363define i1 @test_and_olt_fmf_propagation_union_logical_rhs_poison(float %x) {
364; CHECK-LABEL: define i1 @test_and_olt_fmf_propagation_union_logical_rhs_poison(
365; CHECK-SAME: float [[X:%.*]]) {
366; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
367; CHECK-NEXT:    [[COND:%.*]] = fcmp olt float [[TMP1]], 0x3C00000000000000
368; CHECK-NEXT:    ret i1 [[COND]]
369;
370  %cmp1 = fcmp ninf olt float %x, 0x3C00000000000000
371  %cmp2 = fcmp ogt float %x, 0xBC00000000000000
372  %cond = select i1 %cmp2, i1 %cmp1, i1 false
373  ret i1 %cond
374}
375
376define i1 @test_and_olt_fmf_propagation_union_logical_lhs_poison(float %x) {
377; CHECK-LABEL: define i1 @test_and_olt_fmf_propagation_union_logical_lhs_poison(
378; CHECK-SAME: float [[X:%.*]]) {
379; CHECK-NEXT:    [[TMP1:%.*]] = call ninf float @llvm.fabs.f32(float [[X]])
380; CHECK-NEXT:    [[COND:%.*]] = fcmp ninf olt float [[TMP1]], 0x3C00000000000000
381; CHECK-NEXT:    ret i1 [[COND]]
382;
383  %cmp1 = fcmp olt float %x, 0x3C00000000000000
384  %cmp2 = fcmp ninf ogt float %x, 0xBC00000000000000
385  %cond = select i1 %cmp2, i1 %cmp1, i1 false
386  ret i1 %cond
387}
388
389define i1 @test_and_olt_fmf_propagation_union_logical_both_poison(float %x) {
390; CHECK-LABEL: define i1 @test_and_olt_fmf_propagation_union_logical_both_poison(
391; CHECK-SAME: float [[X:%.*]]) {
392; CHECK-NEXT:    [[TMP1:%.*]] = call ninf float @llvm.fabs.f32(float [[X]])
393; CHECK-NEXT:    [[COND:%.*]] = fcmp ninf olt float [[TMP1]], 0x3C00000000000000
394; CHECK-NEXT:    ret i1 [[COND]]
395;
396  %cmp1 = fcmp ninf olt float %x, 0x3C00000000000000
397  %cmp2 = fcmp ninf ogt float %x, 0xBC00000000000000
398  %cond = select i1 %cmp2, i1 %cmp1, i1 false
399  ret i1 %cond
400}
401