xref: /llvm-project/llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll (revision 38fffa630ee80163dc65e759392ad29798905679)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2
2; RUN: opt -S -passes=instcombine < %s | FileCheck %s
3
4declare float @llvm.fabs.f32(float)
5declare float @llvm.copysign.f32(float, float)
6declare void @llvm.assume(i1 noundef)
7declare float @llvm.log2.f32(float)
8declare float @llvm.exp2.f32(float)
9declare float @llvm.trunc.f32(float)
10declare float @llvm.arithmetic.fence.f32(float)
11declare float @llvm.minnum.f32(float, float)
12declare float @llvm.maxnum.f32(float, float)
13
14
15define float @ninf_user_select_inf(i1 %cond, float %x, float %y) {
16; CHECK-LABEL: define float @ninf_user_select_inf
17; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[Y:%.*]]) {
18; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000
19; CHECK-NEXT:    [[NINF_USER:%.*]] = fmul ninf float [[Y]], [[SELECT]]
20; CHECK-NEXT:    ret float [[NINF_USER]]
21;
22  %select = select i1 %cond, float %x, float 0x7FF0000000000000
23  %ninf.user = fmul ninf float %y, %select
24  ret float %ninf.user
25}
26
27define nofpclass(inf) float @ret_nofpclass_inf_poison() {
28; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf_poison() {
29; CHECK-NEXT:    ret float poison
30;
31  ret float poison
32}
33
34define nofpclass(inf) float @ret_nofpclass_inf_undef() {
35; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf_undef() {
36; CHECK-NEXT:    ret float undef
37;
38  ret float undef
39}
40
41; Make sure there's no infinite loop
42define nofpclass(all) float @ret_nofpclass_all_var(float %arg) {
43; CHECK-LABEL: define nofpclass(all) float @ret_nofpclass_all_var
44; CHECK-SAME: (float [[ARG:%.*]]) {
45; CHECK-NEXT:    ret float poison
46;
47  ret float %arg
48}
49
50; Make sure there's no infinite loop
51define nofpclass(all) <2 x float> @ret_nofpclass_all_var_vector(<2 x float> %arg) {
52; CHECK-LABEL: define nofpclass(all) <2 x float> @ret_nofpclass_all_var_vector
53; CHECK-SAME: (<2 x float> [[ARG:%.*]]) {
54; CHECK-NEXT:    ret <2 x float> poison
55;
56  ret <2 x float> %arg
57}
58
59define nofpclass(inf) float @ret_nofpclass_inf__0() {
60; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__0() {
61; CHECK-NEXT:    ret float 0.000000e+00
62;
63  ret float 0.0
64}
65
66define nofpclass(inf) float @ret_nofpclass_inf__pinf() {
67; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__pinf() {
68; CHECK-NEXT:    ret float poison
69;
70  ret float 0x7FF0000000000000
71}
72
73define nofpclass(pinf) float @ret_nofpclass_pinf__pinf() {
74; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__pinf() {
75; CHECK-NEXT:    ret float poison
76;
77  ret float 0x7FF0000000000000
78}
79
80define nofpclass(pinf) float @ret_nofpclass_pinf__ninf() {
81; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__ninf() {
82; CHECK-NEXT:    ret float 0xFFF0000000000000
83;
84  ret float 0xFFF0000000000000
85}
86
87define nofpclass(inf) float @ret_nofpclass_inf__ninf() {
88; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__ninf() {
89; CHECK-NEXT:    ret float poison
90;
91  ret float 0xFFF0000000000000
92}
93
94; Basic aggregate tests to ensure this does not crash.
95define nofpclass(nan) { float } @ret_nofpclass_struct_ty() {
96; CHECK-LABEL: define nofpclass(nan) { float } @ret_nofpclass_struct_ty() {
97; CHECK-NEXT:  entry:
98; CHECK-NEXT:    ret { float } zeroinitializer
99;
100entry:
101  ret { float } zeroinitializer
102}
103
104define nofpclass(nan) { float, float } @ret_nofpclass_multiple_elems_struct_ty() {
105; CHECK-LABEL: define nofpclass(nan) { float, float } @ret_nofpclass_multiple_elems_struct_ty() {
106; CHECK-NEXT:  entry:
107; CHECK-NEXT:    ret { float, float } zeroinitializer
108;
109entry:
110  ret { float, float } zeroinitializer
111}
112
113define nofpclass(nan) { <4 x float>, <4 x float> } @ret_nofpclass_vector_elems_struct_ty() {
114; CHECK-LABEL: define nofpclass(nan) { <4 x float>, <4 x float> } @ret_nofpclass_vector_elems_struct_ty() {
115; CHECK-NEXT:  entry:
116; CHECK-NEXT:    ret { <4 x float>, <4 x float> } zeroinitializer
117;
118entry:
119  ret { <4 x float>, <4 x float> } zeroinitializer
120}
121
122define nofpclass(nan) [ 5 x float ] @ret_nofpclass_array_ty() {
123; CHECK-LABEL: define nofpclass(nan) [5 x float] @ret_nofpclass_array_ty() {
124; CHECK-NEXT:  entry:
125; CHECK-NEXT:    ret [5 x float] zeroinitializer
126;
127entry:
128  ret [ 5 x float ] zeroinitializer
129}
130
131define nofpclass(nan) [ 2 x [ 5 x float ]] @ret_nofpclass_nested_array_ty() {
132; CHECK-LABEL: define nofpclass(nan) [2 x [5 x float]] @ret_nofpclass_nested_array_ty() {
133; CHECK-NEXT:  entry:
134; CHECK-NEXT:    ret [2 x [5 x float]] zeroinitializer
135;
136entry:
137  ret [ 2 x [ 5 x float ]] zeroinitializer
138}
139
140define nofpclass(pinf) { float } @ret_nofpclass_struct_ty_pinf__ninf() {
141; CHECK-LABEL: define nofpclass(pinf) { float } @ret_nofpclass_struct_ty_pinf__ninf() {
142; CHECK-NEXT:  entry:
143; CHECK-NEXT:    ret { float } { float 0xFFF0000000000000 }
144;
145entry:
146  ret { float } { float 0xFFF0000000000000 }
147}
148
149define nofpclass(pinf) { float, float } @ret_nofpclass_multiple_elems_struct_ty_pinf__ninf() {
150; CHECK-LABEL: define nofpclass(pinf) { float, float } @ret_nofpclass_multiple_elems_struct_ty_pinf__ninf() {
151; CHECK-NEXT:  entry:
152; CHECK-NEXT:    ret { float, float } { float 0xFFF0000000000000, float 0xFFF0000000000000 }
153;
154entry:
155  ret { float, float } { float 0xFFF0000000000000, float 0xFFF0000000000000 }
156}
157
158define nofpclass(pinf) { <2 x float> } @ret_nofpclass_vector_elems_struct_ty_pinf__ninf() {
159; CHECK-LABEL: define nofpclass(pinf) { <2 x float> } @ret_nofpclass_vector_elems_struct_ty_pinf__ninf() {
160; CHECK-NEXT:  entry:
161; CHECK-NEXT:    ret { <2 x float> } { <2 x float> splat (float 0xFFF0000000000000) }
162;
163entry:
164  ret { <2 x float>} { <2 x float> <float 0xFFF0000000000000, float 0xFFF0000000000000> }
165}
166
167; UTC_ARGS: --disable
168; FileCheck does not like the nested square brackets.
169define nofpclass(pinf) [ 1 x [ 1 x float ]] @ret_nofpclass_nested_array_ty_pinf__ninf() {
170; CHECK-LABEL: @ret_nofpclass_nested_array_ty_pinf__ninf() {
171; CHECK-NEXT:  entry:
172; CHECK-NEXT:    ret {{.*}}float 0xFFF0000000000000
173;
174entry:
175  ret [ 1 x [ 1 x float ]] [[ 1 x float ] [float 0xFFF0000000000000]]
176}
177; UTC_ARGS: --enable
178
179define nofpclass(pzero) { float, float } @ret_nofpclass_multiple_elems_struct_ty_pzero__nzero() {
180; CHECK-LABEL: define nofpclass(pzero) { float, float } @ret_nofpclass_multiple_elems_struct_ty_pzero__nzero() {
181; CHECK-NEXT:  entry:
182; CHECK-NEXT:    ret { float, float } { float -0.000000e+00, float -0.000000e+00 }
183;
184entry:
185  ret { float, float } { float -0.0, float -0.0 }
186}
187
188define nofpclass(ninf) { float, float } @ret_nofpclass_multiple_elems_struct_ty_ninf__npinf() {
189; CHECK-LABEL: define nofpclass(ninf) { float, float } @ret_nofpclass_multiple_elems_struct_ty_ninf__npinf() {
190; CHECK-NEXT:  entry:
191; CHECK-NEXT:    ret { float, float } { float 0x7FF0000000000000, float 0x7FF0000000000000 }
192;
193entry:
194  ret { float, float } { float 0x7FF0000000000000, float 0x7FF0000000000000 }
195}
196
197; FIXME (should be poison): Support computeKnownFPClass() for non-zero aggregates.
198define nofpclass(inf) { float, float } @ret_nofpclass_multiple_elems_struct_ty_inf__npinf() {
199; CHECK-LABEL: define nofpclass(inf) { float, float } @ret_nofpclass_multiple_elems_struct_ty_inf__npinf() {
200; CHECK-NEXT:  entry:
201; CHECK-NEXT:    ret { float, float } { float 0x7FF0000000000000, float 0x7FF0000000000000 }
202;
203entry:
204  ret { float, float } { float 0x7FF0000000000000, float 0x7FF0000000000000 }
205}
206
207; FIXME (should be poison): Support computeKnownFPClass() for non-zero aggregates.
208define nofpclass(nzero) [ 1 x float ] @ret_nofpclass_multiple_elems_struct_ty_nzero_nzero() {
209; CHECK-LABEL: define nofpclass(nzero) [1 x float] @ret_nofpclass_multiple_elems_struct_ty_nzero_nzero() {
210; CHECK-NEXT:  entry:
211; CHECK-NEXT:    ret [1 x float] [float -0.000000e+00]
212;
213entry:
214  ret [ 1 x float ] [ float -0.0 ]
215}
216
217; Negative test, do nothing
218define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_inf_lhs(i1 %cond, float nofpclass(inf) %x, float %y) {
219; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_inf_lhs
220; CHECK-SAME: (i1 [[COND:%.*]], float nofpclass(inf) [[X:%.*]], float [[Y:%.*]]) {
221; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float [[Y]]
222; CHECK-NEXT:    ret float [[SELECT]]
223;
224  %select = select i1 %cond, float %x, float %y
225  ret float %select
226}
227
228; Make sure nofpclass from source argument is used, fold to %y
229define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_arg_only_inf_lhs(i1 %cond, float nofpclass(nan norm zero sub) %x, float %y) {
230; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_arg_only_inf_lhs
231; CHECK-SAME: (i1 [[COND:%.*]], float nofpclass(nan zero sub norm) [[X:%.*]], float [[Y:%.*]]) {
232; CHECK-NEXT:    ret float [[Y]]
233;
234  %select = select i1 %cond, float %x, float %y
235  ret float %select
236}
237
238; Make sure nofpclass from source argument is used, fold to %x
239define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_arg_only_inf_rhs(i1 %cond, float %x, float nofpclass(nan norm zero sub) %y) {
240; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_arg_only_inf_rhs
241; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float nofpclass(nan zero sub norm) [[Y:%.*]]) {
242; CHECK-NEXT:    ret float [[X]]
243;
244  %select = select i1 %cond, float %x, float %y
245  ret float %select
246}
247
248; Fold to ret %y
249define nofpclass(inf) [3 x [2 x float]] @ret_float_array(i1 %cond, [3 x [2 x float]] nofpclass(nan norm zero sub) %x, [3 x [2 x float]] %y) {
250; CHECK-LABEL: define nofpclass(inf) [3 x [2 x float]] @ret_float_array
251; CHECK-SAME: (i1 [[COND:%.*]], [3 x [2 x float]] nofpclass(nan zero sub norm) [[X:%.*]], [3 x [2 x float]] [[Y:%.*]]) {
252; CHECK-NEXT:    ret [3 x [2 x float]] [[Y]]
253;
254  %select = select i1 %cond, [3 x [2 x float]] %x, [3 x [2 x float]] %y
255  ret [3 x [2 x float ]] %select
256}
257
258; Fold to ret %x
259define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_lhs(i1 %cond, float %x) {
260; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_lhs
261; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
262; CHECK-NEXT:    ret float [[X]]
263;
264  %select = select i1 %cond, float 0x7FF0000000000000, float %x
265  ret float %select
266}
267
268; Fold to ret %x
269define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_rhs(i1 %cond, float %x) {
270; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_rhs
271; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
272; CHECK-NEXT:    ret float [[X]]
273;
274  %select = select i1 %cond, float %x, float 0x7FF0000000000000
275  ret float %select
276}
277
278; Fold to poison
279define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_or_ninf(i1 %cond, float %x) {
280; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_pinf_or_ninf
281; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
282; CHECK-NEXT:    ret float poison
283;
284  %select = select i1 %cond, float 0x7FF0000000000000, float 0xFFF0000000000000
285  ret float %select
286}
287
288; Fold to poison
289define nofpclass(inf) float @ret_nofpclass_inf__select_ninf_or_pinf(i1 %cond, float %x) {
290; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_ninf_or_pinf
291; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
292; CHECK-NEXT:    ret float poison
293;
294  %select = select i1 %cond, float 0xFFF0000000000000, float 0x7FF0000000000000
295  ret float %select
296}
297
298; Fold to pos inf
299define nofpclass(ninf) float @ret_nofpclass_ninf__select_ninf_or_pinf(i1 %cond, float %x) {
300; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf__select_ninf_or_pinf
301; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
302; CHECK-NEXT:    ret float 0x7FF0000000000000
303;
304  %select = select i1 %cond, float 0xFFF0000000000000, float 0x7FF0000000000000
305  ret float %select
306}
307
308; Fold to neg inf
309define nofpclass(pinf) float @ret_nofpclass_pinf__select_ninf_or_pinf(i1 %cond, float %x) {
310; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__select_ninf_or_pinf
311; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
312; CHECK-NEXT:    ret float 0xFFF0000000000000
313;
314  %select = select i1 %cond, float 0xFFF0000000000000, float 0x7FF0000000000000
315  ret float %select
316}
317
318; Fold to poison
319define nofpclass(zero) float @ret_nofpclass_zero__select_pzero_or_nzero(i1 %cond, float %x) {
320; CHECK-LABEL: define nofpclass(zero) float @ret_nofpclass_zero__select_pzero_or_nzero
321; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
322; CHECK-NEXT:    ret float poison
323;
324  %select = select i1 %cond, float 0.0, float -0.0
325  ret float %select
326}
327
328; Fold to +0
329define nofpclass(nzero) float @ret_nofpclass_nzero__select_pzero_or_nzero(i1 %cond, float %x) {
330; CHECK-LABEL: define nofpclass(nzero) float @ret_nofpclass_nzero__select_pzero_or_nzero
331; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
332; CHECK-NEXT:    ret float 0.000000e+00
333;
334  %select = select i1 %cond, float 0.0, float -0.0
335  ret float %select
336}
337
338; Fold to -0
339define nofpclass(pzero) float @ret_nofpclass_pzero__select_pzero_or_nzero(i1 %cond, float %x) {
340; CHECK-LABEL: define nofpclass(pzero) float @ret_nofpclass_pzero__select_pzero_or_nzero
341; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
342; CHECK-NEXT:    ret float -0.000000e+00
343;
344  %select = select i1 %cond, float 0.0, float -0.0
345  ret float %select
346}
347
348; Fold to ret %x
349define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_pinf_lhs_vector(<2 x i1> %cond, <2 x float> %x) {
350; CHECK-LABEL: define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_pinf_lhs_vector
351; CHECK-SAME: (<2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]]) {
352; CHECK-NEXT:    ret <2 x float> [[X]]
353;
354  %select = select <2 x i1> %cond, <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>, <2 x float> %x
355  ret <2 x float> %select
356}
357
358; Fold to ret %x
359define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_pinf_lhs_vector_undef(<2 x i1> %cond, <2 x float> %x) {
360; CHECK-LABEL: define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_pinf_lhs_vector_undef
361; CHECK-SAME: (<2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]]) {
362; CHECK-NEXT:    ret <2 x float> [[X]]
363;
364  %select = select <2 x i1> %cond, <2 x float> <float 0x7FF0000000000000, float poison>, <2 x float> %x
365  ret <2 x float> %select
366}
367
368; Fold to ret %x
369define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_mixed_inf_lhs_vector(<2 x i1> %cond, <2 x float> %x) {
370; CHECK-LABEL: define nofpclass(inf) <2 x float> @ret_nofpclass_inf__select_mixed_inf_lhs_vector
371; CHECK-SAME: (<2 x i1> [[COND:%.*]], <2 x float> [[X:%.*]]) {
372; CHECK-NEXT:    ret <2 x float> [[X]]
373;
374  %select = select <2 x i1> %cond, <2 x float> <float 0x7FF0000000000000, float 0xFFF0000000000000>, <2 x float> %x
375  ret <2 x float> %select
376}
377
378; Can't delete the select
379define nofpclass(inf) float @ret_nofpclass_inf__select_multi_use_pinf_lhs(i1 %cond, float %x, ptr %ptr) {
380; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_multi_use_pinf_lhs
381; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], ptr [[PTR:%.*]]) {
382; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float 0x7FF0000000000000, float [[X]]
383; CHECK-NEXT:    store float [[SELECT]], ptr [[PTR]], align 4
384; CHECK-NEXT:    ret float [[SELECT]]
385;
386  %select = select i1 %cond, float 0x7FF0000000000000, float %x
387  store float %select, ptr %ptr
388  ret float %select
389}
390
391; Can't do anything
392define nofpclass(inf) float @ret_nofpclass_inf__select_p0_lhs(i1 %cond, float %x) {
393; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_p0_lhs
394; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
395; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float 0.000000e+00, float [[X]]
396; CHECK-NEXT:    ret float [[SELECT]]
397;
398  %select = select i1 %cond, float 0.0, float %x
399  ret float %select
400}
401
402; Can't do anything
403define nofpclass(inf) float @ret_nofpclass_inf__select_p0_rhs(i1 %cond, float %x) {
404; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_p0_rhs
405; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
406; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0.000000e+00
407; CHECK-NEXT:    ret float [[SELECT]]
408;
409  %select = select i1 %cond, float %x, float 0.0
410  ret float %select
411}
412
413; Can't do anything
414define nofpclass(nan) float @ret_nofpclass_nan__select_pinf_lhs(i1 %cond, float %x) {
415; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__select_pinf_lhs
416; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
417; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float 0x7FF0000000000000, float [[X]]
418; CHECK-NEXT:    ret float [[SELECT]]
419;
420  %select = select i1 %cond, float 0x7FF0000000000000, float %x
421  ret float %select
422}
423
424; Can't do anything
425define nofpclass(nan) float @ret_nofpclass_nan__select_pinf_rhs(i1 %cond, float %x) {
426; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__select_pinf_rhs
427; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
428; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000
429; CHECK-NEXT:    ret float [[SELECT]]
430;
431  %select = select i1 %cond, float %x, float 0x7FF0000000000000
432  ret float %select
433}
434
435define nofpclass(inf nan) float @ret_nofpclass_inf_nan__select_chain_inf_nan_0(i1 %cond, float %x) {
436; CHECK-LABEL: define nofpclass(nan inf) float @ret_nofpclass_inf_nan__select_chain_inf_nan_0
437; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
438; CHECK-NEXT:    ret float [[X]]
439;
440  %select0 = select i1 %cond, float 0x7FF8000000000000, float %x
441  %select1 = select i1 %cond, float 0x7FF0000000000000, float %select0
442  ret float %select1
443}
444
445define nofpclass(inf nan) float @ret_nofpclass_inf_nan__select_chain_inf_nan_1(i1 %cond, float %x) {
446; CHECK-LABEL: define nofpclass(nan inf) float @ret_nofpclass_inf_nan__select_chain_inf_nan_1
447; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
448; CHECK-NEXT:    ret float poison
449;
450  %select0 = select i1 %cond, float %x, float 0x7FF8000000000000
451  %select1 = select i1 %cond, float 0x7FF0000000000000, float %select0
452  ret float %select1
453}
454
455define nofpclass(nan) float @ret_nofpclass_nan__select_chain_inf_nan(i1 %cond, float %x) {
456; CHECK-LABEL: define nofpclass(nan) float @ret_nofpclass_nan__select_chain_inf_nan
457; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
458; CHECK-NEXT:    [[SELECT1:%.*]] = select i1 [[COND]], float 0x7FF0000000000000, float [[X]]
459; CHECK-NEXT:    ret float [[SELECT1]]
460;
461  %select0 = select i1 %cond, float 0x7FF8000000000000, float %x
462  %select1 = select i1 %cond, float 0x7FF0000000000000, float %select0
463  ret float %select1
464}
465
466define nofpclass(inf) float @ret_nofpclass_inf__select_chain_inf_nan_0(i1 %cond, float %x) {
467; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_chain_inf_nan_0
468; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
469; CHECK-NEXT:    ret float [[X]]
470;
471  %select0 = select i1 %cond, float 0x7FF8000000000000, float %x
472  %select1 = select i1 %cond, float 0x7FF0000000000000, float %select0
473  ret float %select1
474}
475
476define nofpclass(inf) float @ret_nofpclass_inf__select_chain_inf_nan_1(i1 %cond, float %x) {
477; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_chain_inf_nan_1
478; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
479; CHECK-NEXT:    ret float 0x7FF8000000000000
480;
481  %select0 = select i1 %cond, float 0x7FF8000000000000, float %x
482  %select1 = select i1 %cond, float %select0, float 0x7FF0000000000000
483  ret float %select1
484}
485
486; Simplify to fabs %x
487define nofpclass(inf) float @ret_nofpclass_inf__fabs_select_ninf_rhs(i1 %cond, float %x) {
488; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__fabs_select_ninf_rhs
489; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
490; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
491; CHECK-NEXT:    ret float [[TMP1]]
492;
493  %select = select i1 %cond, float %x, float 0xFFF0000000000000
494  %fabs = call float @llvm.fabs.f32(float %select)
495  ret float %fabs
496}
497
498; Simplify to fabs %x
499define nofpclass(inf) float @ret_nofpclass_inf__fabs_select_pinf_rhs(i1 %cond, float %x) {
500; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__fabs_select_pinf_rhs
501; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
502; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
503; CHECK-NEXT:    ret float [[TMP1]]
504;
505  %select = select i1 %cond, float %x, float 0x7FF0000000000000
506  %fabs = call float @llvm.fabs.f32(float %select)
507  ret float %fabs
508}
509
510define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives__fabs_select_pinf_rhs(i1 %cond, float %x) {
511; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives__fabs_select_pinf_rhs
512; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
513; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
514; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000
515; CHECK-NEXT:    ret float [[FABS]]
516;
517  %select = select i1 %cond, float %x, float 0x7FF0000000000000
518  %fabs = call float @llvm.fabs.f32(float %select)
519  ret float %fabs
520}
521
522; Fold to fabs(%x), preserving a possible nan's payload bits
523define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_no_positives__fabs_select_pinf_rhs(i1 %cond, float %x) {
524; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_no_positives__fabs_select_pinf_rhs
525; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
526; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
527; CHECK-NEXT:    ret float [[TMP1]]
528;
529  %select = select i1 %cond, float %x, float 0x7FF0000000000000
530  %fabs = call float @llvm.fabs.f32(float %select)
531  ret float %fabs
532}
533
534define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives_nan__fabs_select_pinf_rhs(i1 %cond, float %x) {
535; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives_nan__fabs_select_pinf_rhs
536; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
537; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
538; CHECK-NEXT:    [[FABS:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000
539; CHECK-NEXT:    ret float [[FABS]]
540;
541  %select = select i1 %cond, float %x, float 0x7FF0000000000000
542  %fabs = call float @llvm.fabs.f32(float %select)
543  ret float %fabs
544}
545
546; Can fold to poison
547define nofpclass(nan pinf pnorm psub pzero) float @ret_nofpclass_no_positives_nan__fabs_select_pinf_rhs(i1 %cond, float %x) {
548; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_nofpclass_no_positives_nan__fabs_select_pinf_rhs
549; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
550; CHECK-NEXT:    ret float poison
551;
552  %select = select i1 %cond, float %x, float 0x7FF0000000000000
553  %fabs = call float @llvm.fabs.f32(float %select)
554  ret float %fabs
555}
556
557; Simplify to fneg %x
558define nofpclass(inf) float @ret_nofpclass_inf__fneg_select_ninf_rhs(i1 %cond, float %x) {
559; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__fneg_select_ninf_rhs
560; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
561; CHECK-NEXT:    [[X_NEG:%.*]] = fneg float [[X]]
562; CHECK-NEXT:    ret float [[X_NEG]]
563;
564  %select = select i1 %cond, float %x, float 0xFFF0000000000000
565  %fneg = fneg float %select
566  ret float %fneg
567}
568
569; Simplify to fneg %x
570define nofpclass(inf nnorm nsub nzero) float @ret_nofpclass_nonegatives_noinf___fneg_select_pinf_rhs(i1 %cond, float %x) {
571; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_nofpclass_nonegatives_noinf___fneg_select_pinf_rhs
572; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
573; CHECK-NEXT:    [[X_NEG:%.*]] = fneg float [[X]]
574; CHECK-NEXT:    ret float [[X_NEG]]
575;
576  %select = select i1 %cond, float %x, float 0x7FF0000000000000
577  %fneg = fneg float %select
578  ret float %fneg
579}
580
581; Simplify to fneg %x
582define nofpclass(inf nnorm nsub nzero) float @ret_nofpclass_nonegatives_noinf___fneg_select_ninf_lhs(i1 %cond, float %x) {
583; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_nofpclass_nonegatives_noinf___fneg_select_ninf_lhs
584; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
585; CHECK-NEXT:    [[X_NEG:%.*]] = fneg float [[X]]
586; CHECK-NEXT:    ret float [[X_NEG]]
587;
588  %select = select i1 %cond, float 0xFFF0000000000000, float %x
589  %fneg = fneg float %select
590  ret float %fneg
591}
592
593define nofpclass(pzero psub pnorm pinf) float @ret_nofpclass_nopositives___fneg_select_pinf_rhs(i1 %cond, float %x) {
594; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_nopositives___fneg_select_pinf_rhs
595; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
596; CHECK-NEXT:    [[X_NEG:%.*]] = fneg float [[X]]
597; CHECK-NEXT:    [[FNEG:%.*]] = select i1 [[COND]], float [[X_NEG]], float 0xFFF0000000000000
598; CHECK-NEXT:    ret float [[FNEG]]
599;
600  %select = select i1 %cond, float %x, float 0x7FF0000000000000
601  %fneg = fneg float %select
602  ret float %fneg
603}
604
605; Fold to fneg fabs
606define nofpclass(inf) float @ret_nofpclass_inf__fneg_fabs_select_pinf_rhs(i1 %cond, float %x) {
607; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__fneg_fabs_select_pinf_rhs
608; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
609; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
610; CHECK-NEXT:    [[DOTNEG:%.*]] = fneg float [[TMP1]]
611; CHECK-NEXT:    ret float [[DOTNEG]]
612;
613  %select = select i1 %cond, float %x, float 0x7FF0000000000000
614  %fabs = call float @llvm.fabs.f32(float %select)
615  %fneg = fneg float %fabs
616  ret float %fneg
617}
618
619; Fold to fneg fabs, may need to preserve a nan payload
620define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives__fneg_fabs_select_pinf_rhs(i1 %cond, float %x) {
621; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives__fneg_fabs_select_pinf_rhs
622; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
623; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
624; CHECK-NEXT:    [[DOTNEG:%.*]] = fneg float [[TMP1]]
625; CHECK-NEXT:    ret float [[DOTNEG]]
626;
627  %select = select i1 %cond, float %x, float 0x7FF0000000000000
628  %fabs = call float @llvm.fabs.f32(float %select)
629  %fneg = fneg float %fabs
630  ret float %fneg
631}
632
633
634; Fold to poison
635define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives_nonan__fneg_fabs_select_pinf_rhs(i1 %cond, float %x) {
636; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives_nonan__fneg_fabs_select_pinf_rhs
637; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
638; CHECK-NEXT:    ret float poison
639;
640  %select = select i1 %cond, float %x, float 0x7FF0000000000000
641  %fabs = call float @llvm.fabs.f32(float %select)
642  %fneg = fneg float %fabs
643  ret float %fneg
644}
645
646; should fold to ret copysign(%x)
647define nofpclass(inf) float @ret_nofpclass_inf__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
648; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__copysign_unknown_select_pinf_rhs
649; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
650; CHECK-NEXT:    [[COPYSIGN:%.*]] = call float @llvm.copysign.f32(float [[X]], float [[UNKNOWN_SIGN]])
651; CHECK-NEXT:    ret float [[COPYSIGN]]
652;
653  %select = select i1 %cond, float %x, float 0x7FF0000000000000
654  %copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign)
655  ret float %copysign
656}
657
658define nofpclass(inf) float @ret_nofpclass_inf__copysign_positive_select_pinf_rhs(i1 %cond, float %x) {
659; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__copysign_positive_select_pinf_rhs
660; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
661; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
662; CHECK-NEXT:    ret float [[TMP1]]
663;
664  %select = select i1 %cond, float %x, float 0x7FF0000000000000
665  %copysign = call float @llvm.copysign.f32(float %select, float 1.0)
666  ret float %copysign
667}
668
669define nofpclass(inf) float @ret_nofpclass_inf__copysign_negative_select_pinf_rhs(i1 %cond, float %x) {
670; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__copysign_negative_select_pinf_rhs
671; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
672; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
673; CHECK-NEXT:    [[DOTNEG:%.*]] = fneg float [[TMP1]]
674; CHECK-NEXT:    ret float [[DOTNEG]]
675;
676  %select = select i1 %cond, float %x, float 0x7FF0000000000000
677  %copysign = call float @llvm.copysign.f32(float %select, float -1.0)
678  ret float %copysign
679}
680
681; can fold to fneg(fabs(x))
682define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_nopositives_copysign(float %x, float %unknown.sign) {
683; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_nopositives_copysign
684; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
685; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
686; CHECK-NEXT:    [[COPYSIGN:%.*]] = fneg float [[TMP1]]
687; CHECK-NEXT:    ret float [[COPYSIGN]]
688;
689  %copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign)
690  ret float %copysign
691}
692
693; can fold to fneg(fabs(x))
694define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_nopositives_copysign_nnan_flag(float %x, float %unknown.sign) {
695; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_nopositives_copysign_nnan_flag
696; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
697; CHECK-NEXT:    [[TMP1:%.*]] = call nnan float @llvm.fabs.f32(float [[X]])
698; CHECK-NEXT:    [[COPYSIGN:%.*]] = fneg nnan float [[TMP1]]
699; CHECK-NEXT:    ret float [[COPYSIGN]]
700;
701  %copysign = call nnan float @llvm.copysign.f32(float %x, float %unknown.sign)
702  ret float %copysign
703}
704
705; can fold to fneg(fabs(x))
706define nofpclass(nan pinf pnorm psub pzero) float @ret_nofpclass_nopositives_nonan_copysign(float %x, float %unknown.sign) {
707; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_nofpclass_nopositives_nonan_copysign
708; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
709; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
710; CHECK-NEXT:    [[COPYSIGN:%.*]] = fneg float [[TMP1]]
711; CHECK-NEXT:    ret float [[COPYSIGN]]
712;
713  %copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign)
714  ret float %copysign
715}
716
717; can fold to fabs(x)
718define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives_copysign(float %x, float %unknown.sign) {
719; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives_copysign
720; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
721; CHECK-NEXT:    [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[X]])
722; CHECK-NEXT:    ret float [[COPYSIGN]]
723;
724  %copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign)
725  ret float %copysign
726}
727
728; can fold to fabs(x)
729define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives_copysign_nnan_flag(float %x, float %unknown.sign) {
730; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives_copysign_nnan_flag
731; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
732; CHECK-NEXT:    [[COPYSIGN:%.*]] = call nnan float @llvm.fabs.f32(float [[X]])
733; CHECK-NEXT:    ret float [[COPYSIGN]]
734;
735  %copysign = call nnan float @llvm.copysign.f32(float %x, float %unknown.sign)
736  ret float %copysign
737}
738
739; can fold to fabs(x)
740define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_nonegatives_nonan_copysign(float %x, float %unknown.sign) {
741; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_nonegatives_nonan_copysign
742; CHECK-SAME: (float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
743; CHECK-NEXT:    [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[X]])
744; CHECK-NEXT:    ret float [[COPYSIGN]]
745;
746  %copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign)
747  ret float %copysign
748}
749
750define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_nopositives__copysign_fabs_select_pinf_rhs(i1 %cond, float %x, float %sign) {
751; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_nopositives__copysign_fabs_select_pinf_rhs
752; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[SIGN:%.*]]) {
753; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
754; CHECK-NEXT:    ret float [[TMP1]]
755;
756  %select = select i1 %cond, float %x, float 0x7FF0000000000000
757  %fabs.sign = call float @llvm.fabs.f32(float %sign)
758  %copysign = call float @llvm.copysign.f32(float %select, float %fabs.sign)
759  ret float %copysign
760}
761
762; Can fold to copysign %x
763define nofpclass(inf nnorm nsub nzero) float @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
764; CHECK-LABEL: define nofpclass(inf nzero nsub nnorm) float @ret_nofpclass_no_negatives_noinf__copysign_unknown_select_pinf_rhs
765; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
766; CHECK-NEXT:    [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[X]])
767; CHECK-NEXT:    ret float [[COPYSIGN]]
768;
769  %select = select i1 %cond, float %x, float 0x7FF0000000000000
770  %copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign)
771  ret float %copysign
772}
773
774; Can fold to copysign %x
775define nofpclass(inf pnorm psub pzero) float @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
776; CHECK-LABEL: define nofpclass(inf pzero psub pnorm) float @ret_nofpclass_no_positives_noinf__copysign_unknown_select_pinf_rhs
777; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
778; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
779; CHECK-NEXT:    [[COPYSIGN:%.*]] = fneg float [[TMP1]]
780; CHECK-NEXT:    ret float [[COPYSIGN]]
781;
782  %select = select i1 %cond, float %x, float 0x7FF0000000000000
783  %copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign)
784  ret float %copysign
785}
786
787; Can't fold because it could have nan payload bits
788define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
789; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs
790; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
791; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
792; CHECK-NEXT:    [[COPYSIGN:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000
793; CHECK-NEXT:    ret float [[COPYSIGN]]
794;
795  %select = select i1 %cond, float %x, float 0x7FF0000000000000
796  %copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign)
797  ret float %copysign
798}
799
800; Can't fold because it could be nan
801define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
802; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs
803; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
804; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
805; CHECK-NEXT:    [[DOTNEG:%.*]] = fneg float [[TMP1]]
806; CHECK-NEXT:    [[COPYSIGN:%.*]] = select i1 [[COND]], float [[DOTNEG]], float 0xFFF0000000000000
807; CHECK-NEXT:    ret float [[COPYSIGN]]
808;
809  %select = select i1 %cond, float %x, float 0x7FF0000000000000
810  %copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign)
811  ret float %copysign
812}
813
814; Could fold to copysign with constant
815define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
816; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs
817; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
818; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
819; CHECK-NEXT:    [[COPYSIGN:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000
820; CHECK-NEXT:    ret float [[COPYSIGN]]
821;
822  %select = select i1 %cond, float %x, float 0x7FF0000000000000
823  %copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign)
824  ret float %copysign
825}
826
827; Could fold to copysign %x with constant
828define nofpclass(nan pinf pnorm psub pzero) float @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
829; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs
830; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
831; CHECK-NEXT:    [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
832; CHECK-NEXT:    [[DOTNEG:%.*]] = fneg float [[TMP1]]
833; CHECK-NEXT:    [[COPYSIGN:%.*]] = select i1 [[COND]], float [[DOTNEG]], float 0xFFF0000000000000
834; CHECK-NEXT:    ret float [[COPYSIGN]]
835;
836  %select = select i1 %cond, float %x, float 0x7FF0000000000000
837  %copysign = call float @llvm.copysign.f32(float %select, float %unknown.sign)
838  ret float %copysign
839}
840
841; Do nothing
842define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_negatives__select_clamp_neg_to_zero(float %x) {
843; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_negatives__select_clamp_neg_to_zero
844; CHECK-SAME: (float [[X:%.*]]) {
845; CHECK-NEXT:    [[IS_LT_ZERO:%.*]] = fcmp olt float [[X]], 0.000000e+00
846; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[IS_LT_ZERO]], float 0.000000e+00, float [[X]]
847; CHECK-NEXT:    ret float [[SELECT]]
848;
849  %is.lt.zero = fcmp olt float %x, 0.0
850  %select = select i1 %is.lt.zero, float 0.0, float %x
851  ret float %select
852}
853
854; Can fold to ret %x, assumed to be nan
855define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_negatives__select_clamp_pos_to_zero(float %x) {
856; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_negatives__select_clamp_pos_to_zero
857; CHECK-SAME: (float [[X:%.*]]) {
858; CHECK-NEXT:    [[IS_GT_ZERO:%.*]] = fcmp ogt float [[X]], 0.000000e+00
859; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[IS_GT_ZERO]], float 0.000000e+00, float [[X]]
860; CHECK-NEXT:    ret float [[SELECT]]
861;
862  %is.gt.zero = fcmp ogt float %x, 0.0
863  %select = select i1 %is.gt.zero, float 0.0, float %x
864  ret float %select
865}
866
867; Can fold to ret +0
868define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_nan_negatives__select_clamp_pos_to_zero(float %x) {
869; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_nan_negatives__select_clamp_pos_to_zero
870; CHECK-SAME: (float [[X:%.*]]) {
871; CHECK-NEXT:    [[IS_GT_ZERO:%.*]] = fcmp ogt float [[X]], 0.000000e+00
872; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[IS_GT_ZERO]], float 0.000000e+00, float [[X]]
873; CHECK-NEXT:    ret float [[SELECT]]
874;
875  %is.gt.zero = fcmp ogt float %x, 0.0
876  %select = select i1 %is.gt.zero, float 0.0, float %x
877  ret float %select
878}
879
880; Can fold to ret poison
881define nofpclass(nan ninf nnorm nsub zero) float @ret_nofpclass_nan_negatives_zero__select_clamp_pos_to_zero(float %x) {
882; CHECK-LABEL: define nofpclass(nan ninf zero nsub nnorm) float @ret_nofpclass_nan_negatives_zero__select_clamp_pos_to_zero
883; CHECK-SAME: (float [[X:%.*]]) {
884; CHECK-NEXT:    ret float [[X]]
885;
886  %is.gt.zero = fcmp ogt float %x, 0.0
887  %select = select i1 %is.gt.zero, float 0.0, float %x
888  ret float %select
889}
890
891; Can fold to ret %x, assumed to be nan
892define nofpclass(ninf nnorm nsub zero) float @ret_nofpclass_negatives_zero__select_clamp_pos_to_zero(float %x) {
893; CHECK-LABEL: define nofpclass(ninf zero nsub nnorm) float @ret_nofpclass_negatives_zero__select_clamp_pos_to_zero
894; CHECK-SAME: (float [[X:%.*]]) {
895; CHECK-NEXT:    ret float [[X]]
896;
897  %is.gt.zero = fcmp ogt float %x, 0.0
898  %select = select i1 %is.gt.zero, float 0.0, float %x
899  ret float %select
900}
901
902; Assume should allow folding ret %y
903define nofpclass(inf) float @ret_nofpclass_noinfs__assumed_isinf__select_pinf_lhs(i1 %cond, float %x, float %y) {
904; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_noinfs__assumed_isinf__select_pinf_lhs
905; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[Y:%.*]]) {
906; CHECK-NEXT:    [[FABS_X:%.*]] = call float @llvm.fabs.f32(float [[X]])
907; CHECK-NEXT:    [[X_IS_INF:%.*]] = fcmp oeq float [[FABS_X]], 0x7FF0000000000000
908; CHECK-NEXT:    call void @llvm.assume(i1 [[X_IS_INF]])
909; CHECK-NEXT:    ret float [[Y]]
910;
911  %fabs.x = call float @llvm.fabs.f32(float %x)
912  %x.is.inf = fcmp oeq float %fabs.x, 0x7FF0000000000000
913  call void @llvm.assume(i1 %x.is.inf)
914  %select = select i1 %cond, float %x, float %y
915  ret float %select
916}
917
918; Ideally should be able to fold out everything after the exp2 call.
919define nofpclass(nan inf nzero nsub nnorm) float @powr_issue64870(float nofpclass(nan inf) %x, float nofpclass(nan inf) %y) {
920; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) float @powr_issue64870
921; CHECK-SAME: (float nofpclass(nan inf) [[X:%.*]], float nofpclass(nan inf) [[Y:%.*]]) {
922; CHECK-NEXT:  entry:
923; CHECK-NEXT:    [[I:%.*]] = tail call float @llvm.fabs.f32(float [[X]])
924; CHECK-NEXT:    [[I1:%.*]] = tail call float @llvm.log2.f32(float [[I]])
925; CHECK-NEXT:    [[I2:%.*]] = fmul float [[I1]], [[Y]]
926; CHECK-NEXT:    [[I3:%.*]] = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.exp2.f32(float [[I2]])
927; CHECK-NEXT:    [[I6:%.*]] = fcmp oeq float [[X]], 0.000000e+00
928; CHECK-NEXT:    [[I7:%.*]] = select i1 [[I6]], float 0.000000e+00, float [[I3]]
929; CHECK-NEXT:    [[I8:%.*]] = fcmp oeq float [[Y]], 0.000000e+00
930; CHECK-NEXT:    [[I11:%.*]] = fcmp oeq float [[X]], 1.000000e+00
931; CHECK-NEXT:    [[TMP0:%.*]] = select i1 [[I11]], i1 true, i1 [[I8]]
932; CHECK-NEXT:    [[I12:%.*]] = select i1 [[TMP0]], float 1.000000e+00, float [[I7]]
933; CHECK-NEXT:    ret float [[I12]]
934;
935entry:
936  %i = tail call float @llvm.fabs.f32(float %x)
937  %i1 = tail call float @llvm.log2.f32(float %i)
938  %i2 = fmul float %i1, %y
939  %i3 = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.exp2.f32(float %i2)
940  %i4 = fcmp olt float %y, 0.000000e+00
941  %i5 = select i1 %i4, float 0x7FF0000000000000, float 0.000000e+00
942  %i6 = fcmp oeq float %x, 0.000000e+00
943  %i7 = select i1 %i6, float %i5, float %i3
944  %i8 = fcmp oeq float %y, 0.000000e+00
945  %i9 = select i1 %i6, float 0x7FF8000000000000, float 1.000000e+00
946  %i10 = select i1 %i8, float %i9, float %i7
947  %i11 = fcmp oeq float %x, 1.000000e+00
948  %i12 = select i1 %i11, float 1.000000e+00, float %i10
949  %i13 = fcmp olt float %x, 0.000000e+00
950  %i14 = select i1 %i13, float 0x7FF8000000000000, float %i12
951  ret float %i14
952}
953
954; Different implementation of powr
955define nofpclass(nan inf nzero nsub nnorm) float @test_powr_issue64870_2(float nofpclass(nan inf) %arg, float nofpclass(nan inf) %arg1) #0 {
956; CHECK-LABEL: define nofpclass(nan inf nzero nsub nnorm) float @test_powr_issue64870_2
957; CHECK-SAME: (float nofpclass(nan inf) [[ARG:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) {
958; CHECK-NEXT:  bb:
959; CHECK-NEXT:    [[I:%.*]] = fcmp olt float [[ARG]], 0.000000e+00
960; CHECK-NEXT:    [[I2:%.*]] = select i1 [[I]], float 0x7FF8000000000000, float [[ARG]]
961; CHECK-NEXT:    [[I3:%.*]] = tail call float @llvm.log2.f32(float noundef [[I2]])
962; CHECK-NEXT:    [[I4:%.*]] = select i1 [[I]], float 0x7FF8000000000000, float [[ARG1]]
963; CHECK-NEXT:    [[I5:%.*]] = fmul float [[I4]], [[I3]]
964; CHECK-NEXT:    [[I6:%.*]] = tail call noundef nofpclass(ninf nzero nsub nnorm) float @llvm.exp2.f32(float noundef [[I5]])
965; CHECK-NEXT:    [[I10:%.*]] = fcmp oeq float [[I2]], 0.000000e+00
966; CHECK-NEXT:    [[I12:%.*]] = select i1 [[I10]], float 0.000000e+00, float [[I6]]
967; CHECK-NEXT:    ret float [[I12]]
968;
969bb:
970  %i = fcmp olt float %arg, 0.000000e+00
971  %i2 = select i1 %i, float 0x7FF8000000000000, float %arg
972  %i3 = tail call float @llvm.log2.f32(float noundef %i2) #2
973  %i4 = select i1 %i, float 0x7FF8000000000000, float %arg1
974  %i5 = fmul float %i4, %i3
975  %i6 = tail call noundef nofpclass(ninf nzero nsub nnorm) float @llvm.exp2.f32(float noundef %i5)
976  %i7 = fcmp olt float %i4, 0.000000e+00
977  %i8 = select i1 %i7, float 0x7FF0000000000000, float 0.000000e+00
978  %i9 = fcmp ueq float %i4, 0.000000e+00
979  %i10 = fcmp oeq float %i2, 0.000000e+00
980  %i11 = select i1 %i9, float 0x7FF8000000000000, float %i8
981  %i12 = select i1 %i10, float %i11, float %i6
982  ret float %i12
983}
984
985; implementation of pow with some prunable cases
986define nofpclass(nan inf) float @pow_f32(float nofpclass(nan inf) %arg, float nofpclass(nan inf) %arg1) #0 {
987; CHECK-LABEL: define nofpclass(nan inf) float @pow_f32
988; CHECK-SAME: (float nofpclass(nan inf) [[ARG:%.*]], float nofpclass(nan inf) [[ARG1:%.*]]) {
989; CHECK-NEXT:  bb:
990; CHECK-NEXT:    [[I:%.*]] = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float noundef [[ARG]])
991; CHECK-NEXT:    [[I2:%.*]] = tail call float @llvm.log2.f32(float noundef [[I]])
992; CHECK-NEXT:    [[I3:%.*]] = fmul float [[I2]], [[ARG1]]
993; CHECK-NEXT:    [[I4:%.*]] = tail call noundef float @llvm.exp2.f32(float noundef [[I3]])
994; CHECK-NEXT:    [[I5:%.*]] = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float noundef [[ARG1]])
995; CHECK-NEXT:    [[I6:%.*]] = tail call float @llvm.trunc.f32(float noundef [[I5]])
996; CHECK-NEXT:    [[I7:%.*]] = fcmp oeq float [[I6]], [[I5]]
997; CHECK-NEXT:    [[I8:%.*]] = fmul float [[I5]], 5.000000e-01
998; CHECK-NEXT:    [[I9:%.*]] = tail call float @llvm.trunc.f32(float noundef [[I8]])
999; CHECK-NEXT:    [[I10:%.*]] = fcmp une float [[I9]], [[I8]]
1000; CHECK-NEXT:    [[I11:%.*]] = and i1 [[I7]], [[I10]]
1001; CHECK-NEXT:    [[I12:%.*]] = select i1 [[I11]], float [[ARG]], float 1.000000e+00
1002; CHECK-NEXT:    [[I13:%.*]] = tail call noundef float @llvm.copysign.f32(float noundef [[I4]], float noundef [[I12]])
1003; CHECK-NEXT:    [[I17:%.*]] = fcmp oeq float [[ARG]], 0.000000e+00
1004; CHECK-NEXT:    [[TMP0:%.*]] = tail call nofpclass(nan sub norm) float @llvm.copysign.f32(float 0.000000e+00, float [[ARG]])
1005; CHECK-NEXT:    [[I22:%.*]] = select i1 [[I11]], float [[TMP0]], float 0.000000e+00
1006; CHECK-NEXT:    [[I23:%.*]] = select i1 [[I17]], float [[I22]], float [[I13]]
1007; CHECK-NEXT:    [[I24:%.*]] = fcmp oeq float [[ARG]], 1.000000e+00
1008; CHECK-NEXT:    [[I25:%.*]] = fcmp oeq float [[ARG1]], 0.000000e+00
1009; CHECK-NEXT:    [[I26:%.*]] = or i1 [[I24]], [[I25]]
1010; CHECK-NEXT:    [[I27:%.*]] = select i1 [[I26]], float 1.000000e+00, float [[I23]]
1011; CHECK-NEXT:    ret float [[I27]]
1012;
1013bb:
1014  %i = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float noundef %arg)
1015  %i2 = tail call float @llvm.log2.f32(float noundef %i)
1016  %i3 = fmul float %i2, %arg1
1017  %i4 = tail call noundef float @llvm.exp2.f32(float noundef %i3)
1018  %i5 = tail call nofpclass(ninf nzero nsub nnorm) float @llvm.fabs.f32(float noundef %arg1)
1019  %i6 = tail call float @llvm.trunc.f32(float noundef %i5)
1020  %i7 = fcmp oeq float %i6, %i5
1021  %i8 = fmul float %i5, 5.000000e-01
1022  %i9 = tail call float @llvm.trunc.f32(float noundef %i8)
1023  %i10 = fcmp une float %i9, %i8
1024  %i11 = and i1 %i7, %i10
1025  %i12 = select i1 %i11, float %arg, float 1.000000e+00
1026  %i13 = tail call noundef float @llvm.copysign.f32(float noundef %i4, float noundef %i12)
1027  %i14 = fcmp olt float %arg, 0.000000e+00
1028  %i15 = select i1 %i7, float %i13, float 0x7FF8000000000000
1029  %i16 = select i1 %i14, float %i15, float %i13
1030  %i17 = fcmp oeq float %arg, 0.000000e+00
1031  %i18 = fcmp olt float %arg1, 0.000000e+00
1032  %i19 = xor i1 %i17, %i18
1033  %i20 = select i1 %i19, float 0.000000e+00, float 0x7FF0000000000000
1034  %i21 = select i1 %i11, float %arg, float 0.000000e+00
1035  %i22 = tail call noundef nofpclass(nan sub norm) float @llvm.copysign.f32(float noundef %i20, float noundef %i21)
1036  %i23 = select i1 %i17, float %i22, float %i16
1037  %i24 = fcmp oeq float %arg, 1.000000e+00
1038  %i25 = fcmp oeq float %arg1, 0.000000e+00
1039  %i26 = or i1 %i24, %i25
1040  %i27 = select i1 %i26, float 1.000000e+00, float %i23
1041  ret float %i27
1042}
1043
1044declare float @extern()
1045
1046; Make sure nofpclass from arbitrary callsite is used, fold to %y
1047define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_call_only_inf(i1 %cond, float %y) {
1048; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_nofpclass_call_only_inf
1049; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
1050; CHECK-NEXT:    [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) float @extern()
1051; CHECK-NEXT:    ret float [[Y]]
1052;
1053  %must.be.inf = call nofpclass(nan norm zero sub) float @extern()
1054  %select = select i1 %cond, float %must.be.inf, float %y
1055  ret float %select
1056}
1057
1058define nofpclass(pinf) float @ret_nofpclass_pinf__nofpclass_call_only_inf(i1 %cond, float %y) {
1059; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__nofpclass_call_only_inf
1060; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
1061; CHECK-NEXT:    [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) float @extern()
1062; CHECK-NEXT:    ret float 0xFFF0000000000000
1063;
1064  %must.be.inf = call nofpclass(nan norm zero sub) float @extern()
1065  ret float %must.be.inf
1066}
1067
1068define nofpclass(ninf) float @ret_nofpclass_ninf__nofpclass_call_only_inf(i1 %cond, float %y) {
1069; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf__nofpclass_call_only_inf
1070; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
1071; CHECK-NEXT:    [[MUST_BE_INF:%.*]] = call nofpclass(nan zero sub norm) float @extern()
1072; CHECK-NEXT:    ret float 0x7FF0000000000000
1073;
1074  %must.be.inf = call nofpclass(nan norm zero sub) float @extern()
1075  ret float %must.be.inf
1076}
1077
1078define nofpclass(nzero) float @ret_nofpclass_nzero__nofpclass_call_only_zero(i1 %cond, float %y) {
1079; CHECK-LABEL: define nofpclass(nzero) float @ret_nofpclass_nzero__nofpclass_call_only_zero
1080; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
1081; CHECK-NEXT:    [[MUST_BE_ZERO:%.*]] = call nofpclass(nan inf sub norm) float @extern()
1082; CHECK-NEXT:    ret float 0.000000e+00
1083;
1084  %must.be.zero = call nofpclass(nan sub norm inf) float @extern()
1085  ret float %must.be.zero
1086}
1087
1088define nofpclass(pzero) float @ret_nofpclass_pzero__nofpclass_call_only_zero(i1 %cond, float %y) {
1089; CHECK-LABEL: define nofpclass(pzero) float @ret_nofpclass_pzero__nofpclass_call_only_zero
1090; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
1091; CHECK-NEXT:    [[MUST_BE_ZERO:%.*]] = call nofpclass(nan inf sub norm) float @extern()
1092; CHECK-NEXT:    ret float -0.000000e+00
1093;
1094  %must.be.zero = call nofpclass(nan sub norm inf) float @extern()
1095  ret float %must.be.zero
1096}
1097
1098; Should not fold this, should not assume payload/sign bits are canonical
1099define nofpclass(qnan) float @ret_nofpclass_qnan__nofpclass_call_only_nan(i1 %cond, float %y) {
1100; CHECK-LABEL: define nofpclass(qnan) float @ret_nofpclass_qnan__nofpclass_call_only_nan
1101; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
1102; CHECK-NEXT:    [[MUST_BE_NAN:%.*]] = call nofpclass(inf zero sub norm) float @extern()
1103; CHECK-NEXT:    ret float [[MUST_BE_NAN]]
1104;
1105  %must.be.nan = call nofpclass(inf norm zero sub) float @extern()
1106  ret float %must.be.nan
1107}
1108
1109; Should not fold this, should not assume payload/sign bits are canonical
1110define nofpclass(snan) float @ret_nofpclass_snan__nofpclass_call_only_nan(i1 %cond, float %y) {
1111; CHECK-LABEL: define nofpclass(snan) float @ret_nofpclass_snan__nofpclass_call_only_nan
1112; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
1113; CHECK-NEXT:    [[MUST_BE_NAN:%.*]] = call nofpclass(inf zero sub norm) float @extern()
1114; CHECK-NEXT:    ret float [[MUST_BE_NAN]]
1115;
1116  %must.be.nan = call nofpclass(inf norm zero sub) float @extern()
1117  ret float %must.be.nan
1118}
1119
1120; Assume call should allow folding this to %y
1121; TODO: Not working, multiple user problem.
1122define nofpclass(inf) float @ret_nofpclass_inf__select_assumed_call_result_only_inf(i1 %cond, float %y) {
1123; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__select_assumed_call_result_only_inf
1124; CHECK-SAME: (i1 [[COND:%.*]], float [[Y:%.*]]) {
1125; CHECK-NEXT:    [[MUST_BE_INF:%.*]] = call float @extern()
1126; CHECK-NEXT:    [[FABS:%.*]] = call float @llvm.fabs.f32(float [[MUST_BE_INF]])
1127; CHECK-NEXT:    [[IS_INF:%.*]] = fcmp oeq float [[FABS]], 0x7FF0000000000000
1128; CHECK-NEXT:    call void @llvm.assume(i1 [[IS_INF]])
1129; CHECK-NEXT:    [[SELECT:%.*]] = select i1 [[COND]], float [[MUST_BE_INF]], float [[Y]]
1130; CHECK-NEXT:    ret float [[SELECT]]
1131;
1132  %must.be.inf = call float @extern()
1133  %fabs = call float @llvm.fabs.f32(float %must.be.inf)
1134  %is.inf = fcmp oeq float %fabs, 0x7FF0000000000000
1135  call void @llvm.assume(i1 %is.inf)
1136  %select = select i1 %cond, float %must.be.inf, float %y
1137  ret float %select
1138}
1139
1140define nofpclass(inf) float @ret_nofpclass_inf__simple_phi_inf_or_unknown(i1 %cond, float %x) {
1141; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__simple_phi_inf_or_unknown
1142; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
1143; CHECK-NEXT:  entry:
1144; CHECK-NEXT:    br i1 [[COND]], label [[BB0:%.*]], label [[RET:%.*]]
1145; CHECK:       bb0:
1146; CHECK-NEXT:    br label [[RET]]
1147; CHECK:       ret:
1148; CHECK-NEXT:    [[PHI:%.*]] = phi float [ 0x7FF0000000000000, [[ENTRY:%.*]] ], [ [[X]], [[BB0]] ]
1149; CHECK-NEXT:    ret float [[PHI]]
1150;
1151entry:
1152  br i1 %cond, label %bb0, label %ret
1153
1154bb0:
1155  br label %ret
1156
1157ret:
1158  %phi = phi float [ 0x7FF0000000000000, %entry ], [ %x, %bb0 ]
1159  ret float %phi
1160}
1161
1162declare i1 @loop.cond()
1163
1164declare float @loop.func()
1165
1166
1167; Should be able to fold inf initial value to poison
1168define nofpclass(inf) float @ret_nofpclass_inf__phi_0(i1 %cond0, float %unknown) {
1169; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__phi_0
1170; CHECK-SAME: (i1 [[COND0:%.*]], float [[UNKNOWN:%.*]]) {
1171; CHECK-NEXT:  entry:
1172; CHECK-NEXT:    br i1 [[COND0]], label [[LOOP:%.*]], label [[RET:%.*]]
1173; CHECK:       loop:
1174; CHECK-NEXT:    [[PHI_LOOP:%.*]] = phi float [ 0x7FF0000000000000, [[ENTRY:%.*]] ], [ [[LOOP_FUNC:%.*]], [[LOOP]] ]
1175; CHECK-NEXT:    [[LOOP_FUNC]] = call nofpclass(nan) float @loop.func()
1176; CHECK-NEXT:    [[LOOP_COND:%.*]] = call i1 @loop.cond()
1177; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[RET]], label [[LOOP]]
1178; CHECK:       ret:
1179; CHECK-NEXT:    [[PHI_RET:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[PHI_LOOP]], [[LOOP]] ]
1180; CHECK-NEXT:    ret float [[PHI_RET]]
1181;
1182entry:
1183  br i1 %cond0, label %loop, label %ret
1184
1185loop:
1186  %phi.loop = phi float [ 0x7FF0000000000000, %entry ], [ %loop.func, %loop ]
1187  %loop.func = call nofpclass(nan) float @loop.func()
1188  %loop.cond = call i1 @loop.cond()
1189  br i1 %loop.cond, label %ret, label %loop
1190
1191ret:
1192  %phi.ret = phi float [ 0.0, %entry ], [ %phi.loop, %loop ]
1193  ret float %phi.ret
1194}
1195
1196; fold to ret 0
1197define nofpclass(inf) float @ret_nofpclass_inf__recursive_phi_0(i1 %cond0, float %unknown) {
1198; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__recursive_phi_0
1199; CHECK-SAME: (i1 [[COND0:%.*]], float [[UNKNOWN:%.*]]) {
1200; CHECK-NEXT:  entry:
1201; CHECK-NEXT:    br i1 [[COND0]], label [[LOOP:%.*]], label [[RET:%.*]]
1202; CHECK:       loop:
1203; CHECK-NEXT:    [[LOOP_COND:%.*]] = call i1 @loop.cond()
1204; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[RET]], label [[LOOP]]
1205; CHECK:       ret:
1206; CHECK-NEXT:    ret float 0.000000e+00
1207;
1208entry:
1209  br i1 %cond0, label %loop, label %ret
1210
1211loop:
1212  %phi.loop = phi float [ 0x7FF0000000000000, %entry ], [ %phi.loop, %loop ]
1213  %loop.cond = call i1 @loop.cond()
1214  br i1 %loop.cond, label %ret, label %loop
1215
1216ret:
1217  %phi.ret = phi float [ 0.0, %entry ], [ %phi.loop, %loop ]
1218  ret float %phi.ret
1219}
1220
1221; fold to ret poison
1222define nofpclass(inf) float @ret_nofpclass_inf__recursive_phi_1(i1 %cond0, float %unknown) {
1223; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__recursive_phi_1
1224; CHECK-SAME: (i1 [[COND0:%.*]], float [[UNKNOWN:%.*]]) {
1225; CHECK-NEXT:  entry:
1226; CHECK-NEXT:    br i1 [[COND0]], label [[LOOP:%.*]], label [[RET:%.*]]
1227; CHECK:       loop:
1228; CHECK-NEXT:    [[LOOP_COND:%.*]] = call i1 @loop.cond()
1229; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[RET]], label [[LOOP]]
1230; CHECK:       ret:
1231; CHECK-NEXT:    ret float poison
1232;
1233entry:
1234  br i1 %cond0, label %loop, label %ret
1235
1236loop:
1237  %phi.loop = phi float [ 0x7FF0000000000000, %entry ], [ %phi.loop, %loop ]
1238  %loop.cond = call i1 @loop.cond()
1239  br i1 %loop.cond, label %ret, label %loop
1240
1241ret:
1242  %phi.ret = phi float [ 0x7FF0000000000000, %entry ], [ %phi.loop, %loop ]
1243  ret float %phi.ret
1244}
1245
1246; Should be able to fold inf initial values to poison
1247define nofpclass(inf) float @ret_nofpclass_inf__phi_switch_repeated_predecessor(i32 %switch, float %unknown) {
1248; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__phi_switch_repeated_predecessor
1249; CHECK-SAME: (i32 [[SWITCH:%.*]], float [[UNKNOWN:%.*]]) {
1250; CHECK-NEXT:  entry:
1251; CHECK-NEXT:    switch i32 [[SWITCH]], label [[RET:%.*]] [
1252; CHECK-NEXT:      i32 0, label [[LOOP:%.*]]
1253; CHECK-NEXT:      i32 1, label [[LOOP]]
1254; CHECK-NEXT:    ]
1255; CHECK:       loop:
1256; CHECK-NEXT:    [[PHI_LOOP:%.*]] = phi float [ 0x7FF0000000000000, [[ENTRY:%.*]] ], [ 0x7FF0000000000000, [[ENTRY]] ], [ [[UNKNOWN]], [[LOOP]] ]
1257; CHECK-NEXT:    [[LOOP_COND:%.*]] = call i1 @loop.cond()
1258; CHECK-NEXT:    br i1 [[LOOP_COND]], label [[RET]], label [[LOOP]]
1259; CHECK:       ret:
1260; CHECK-NEXT:    [[PHI_RET:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[PHI_LOOP]], [[LOOP]] ]
1261; CHECK-NEXT:    ret float [[PHI_RET]]
1262;
1263entry:
1264  switch i32 %switch, label %ret [
1265  i32 0, label %loop
1266  i32 1, label %loop
1267  ]
1268
1269loop:
1270  %phi.loop = phi float [ 0x7FF0000000000000, %entry ], [ 0x7FF0000000000000, %entry ], [ %unknown, %loop ]
1271  %loop.cond = call i1 @loop.cond()
1272  br i1 %loop.cond, label %ret, label %loop
1273
1274ret:
1275  %phi.ret = phi float [ 0.0, %entry ], [ %phi.loop, %loop ]
1276  ret float %phi.ret
1277}
1278
1279; Simplify to arithmetic.fence %x
1280define nofpclass(inf) float @ret_nofpclass_inf__arithmetic_fence_select_pinf_rhs(i1 %cond, float %x) {
1281; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__arithmetic_fence_select_pinf_rhs
1282; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
1283; CHECK-NEXT:    [[FENCE:%.*]] = call float @llvm.arithmetic.fence.f32(float [[X]])
1284; CHECK-NEXT:    ret float [[FENCE]]
1285;
1286  %select = select i1 %cond, float %x, float 0x7FF0000000000000
1287  %fence = call float @llvm.arithmetic.fence.f32(float %select)
1288  ret float %fence
1289}
1290
1291; Can simplify to %x
1292define nofpclass(pinf) float @ret_nofpclass_pinf__minnum_pinf(i1 %cond, float %x) {
1293; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__minnum_pinf
1294; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
1295; CHECK-NEXT:    [[MIN:%.*]] = call float @llvm.minnum.f32(float [[X]], float 0x7FF0000000000000)
1296; CHECK-NEXT:    ret float [[MIN]]
1297;
1298  %min = call float @llvm.minnum.f32(float %x, float 0x7FF0000000000000)
1299  ret float %min
1300}
1301
1302; Can fold to -inf
1303define nofpclass(pinf) float @ret_nofpclass_pinf__minnum_ninf(i1 %cond, float %x) {
1304; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__minnum_ninf
1305; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
1306; CHECK-NEXT:    ret float 0xFFF0000000000000
1307;
1308  %min = call float @llvm.minnum.f32(float %x, float 0xFFF0000000000000)
1309  ret float %min
1310}
1311
1312; Can simplify to %x
1313define nofpclass(ninf) float @ret_nofpclass_ninf__maxnum_ninf(i1 %cond, float %x) {
1314; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf__maxnum_ninf
1315; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
1316; CHECK-NEXT:    [[MAX:%.*]] = call float @llvm.maxnum.f32(float [[X]], float 0xFFF0000000000000)
1317; CHECK-NEXT:    ret float [[MAX]]
1318;
1319  %max = call float @llvm.maxnum.f32(float %x, float 0xFFF0000000000000)
1320  ret float %max
1321}
1322
1323; Can fold to +inf
1324define nofpclass(ninf) float @ret_nofpclass_ninf__maxnum_pinf(i1 %cond, float %x) {
1325; CHECK-LABEL: define nofpclass(ninf) float @ret_nofpclass_ninf__maxnum_pinf
1326; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
1327; CHECK-NEXT:    ret float 0x7FF0000000000000
1328;
1329  %max = call float @llvm.maxnum.f32(float %x, float 0x7FF0000000000000)
1330  ret float %max
1331}
1332