[AArch64][NFC] NFC for const vector as Instruction operand (#116790)
[llvm-project.git] / llvm / test / Transforms / InstCombine / simplify-demanded-fpclass.ll
blobad88287f1d99e49ee59f179b2355b13ccd3e484e
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
4 declare float @llvm.fabs.f32(float)
5 declare float @llvm.copysign.f32(float, float)
6 declare void @llvm.assume(i1 noundef)
7 declare float @llvm.log2.f32(float)
8 declare float @llvm.exp2.f32(float)
9 declare float @llvm.trunc.f32(float)
10 declare float @llvm.arithmetic.fence.f32(float)
11 declare float @llvm.minnum.f32(float, float)
12 declare float @llvm.maxnum.f32(float, float)
15 define 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]]
22   %select = select i1 %cond, float %x, float 0x7FF0000000000000
23   %ninf.user = fmul ninf float %y, %select
24   ret float %ninf.user
27 define nofpclass(inf) float @ret_nofpclass_inf_poison() {
28 ; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf_poison() {
29 ; CHECK-NEXT:    ret float poison
31   ret float poison
34 define nofpclass(inf) float @ret_nofpclass_inf_undef() {
35 ; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf_undef() {
36 ; CHECK-NEXT:    ret float undef
38   ret float undef
41 ; Make sure there's no infinite loop
42 define 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
47   ret float %arg
50 ; Make sure there's no infinite loop
51 define 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
56   ret <2 x float> %arg
59 define 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
63   ret float 0.0
66 define nofpclass(inf) float @ret_nofpclass_inf__pinf() {
67 ; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__pinf() {
68 ; CHECK-NEXT:    ret float poison
70   ret float 0x7FF0000000000000
73 define nofpclass(pinf) float @ret_nofpclass_pinf__pinf() {
74 ; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__pinf() {
75 ; CHECK-NEXT:    ret float poison
77   ret float 0x7FF0000000000000
80 define nofpclass(pinf) float @ret_nofpclass_pinf__ninf() {
81 ; CHECK-LABEL: define nofpclass(pinf) float @ret_nofpclass_pinf__ninf() {
82 ; CHECK-NEXT:    ret float 0xFFF0000000000000
84   ret float 0xFFF0000000000000
87 define nofpclass(inf) float @ret_nofpclass_inf__ninf() {
88 ; CHECK-LABEL: define nofpclass(inf) float @ret_nofpclass_inf__ninf() {
89 ; CHECK-NEXT:    ret float poison
91   ret float 0xFFF0000000000000
94 ; Basic aggregate tests to ensure this does not crash.
95 define 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
100 entry:
101   ret { float } zeroinitializer
104 define 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
109 entry:
110   ret { float, float } zeroinitializer
113 define 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
118 entry:
119   ret { <4 x float>, <4 x float> } zeroinitializer
122 define 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
127 entry:
128   ret [ 5 x float ] zeroinitializer
131 define 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
136 entry:
137   ret [ 2 x [ 5 x float ]] zeroinitializer
140 define 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 }
145 entry:
146   ret { float } { float 0xFFF0000000000000 }
149 define 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 }
154 entry:
155   ret { float, float } { float 0xFFF0000000000000, float 0xFFF0000000000000 }
158 define 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) }
163 entry:
164   ret { <2 x float>} { <2 x float> <float 0xFFF0000000000000, float 0xFFF0000000000000> }
167 ; UTC_ARGS: --disable
168 ; FileCheck does not like the nested square brackets.
169 define 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
174 entry:
175   ret [ 1 x [ 1 x float ]] [[ 1 x float ] [float 0xFFF0000000000000]]
177 ; UTC_ARGS: --enable
179 define 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 }
184 entry:
185   ret { float, float } { float -0.0, float -0.0 }
188 define 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 }
193 entry:
194   ret { float, float } { float 0x7FF0000000000000, float 0x7FF0000000000000 }
197 ; FIXME (should be poison): Support computeKnownFPClass() for non-zero aggregates.
198 define 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 }
203 entry:
204   ret { float, float } { float 0x7FF0000000000000, float 0x7FF0000000000000 }
207 ; FIXME (should be poison): Support computeKnownFPClass() for non-zero aggregates.
208 define 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]
213 entry:
214   ret [ 1 x float ] [ float -0.0 ]
217 ; Negative test, do nothing
218 define 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]]
224   %select = select i1 %cond, float %x, float %y
225   ret float %select
228 ; Make sure nofpclass from source argument is used, fold to %y
229 define 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]]
234   %select = select i1 %cond, float %x, float %y
235   ret float %select
238 ; Make sure nofpclass from source argument is used, fold to %x
239 define 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]]
244   %select = select i1 %cond, float %x, float %y
245   ret float %select
248 ; Fold to ret %y
249 define 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]]
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
258 ; Fold to ret %x
259 define 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]]
264   %select = select i1 %cond, float 0x7FF0000000000000, float %x
265   ret float %select
268 ; Fold to ret %x
269 define 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]]
274   %select = select i1 %cond, float %x, float 0x7FF0000000000000
275   ret float %select
278 ; Fold to poison
279 define 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
284   %select = select i1 %cond, float 0x7FF0000000000000, float 0xFFF0000000000000
285   ret float %select
288 ; Fold to poison
289 define 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
294   %select = select i1 %cond, float 0xFFF0000000000000, float 0x7FF0000000000000
295   ret float %select
298 ; Fold to pos inf
299 define 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
304   %select = select i1 %cond, float 0xFFF0000000000000, float 0x7FF0000000000000
305   ret float %select
308 ; Fold to neg inf
309 define 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
314   %select = select i1 %cond, float 0xFFF0000000000000, float 0x7FF0000000000000
315   ret float %select
318 ; Fold to poison
319 define 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
324   %select = select i1 %cond, float 0.0, float -0.0
325   ret float %select
328 ; Fold to +0
329 define 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
334   %select = select i1 %cond, float 0.0, float -0.0
335   ret float %select
338 ; Fold to -0
339 define 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
344   %select = select i1 %cond, float 0.0, float -0.0
345   ret float %select
348 ; Fold to ret %x
349 define 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]]
354   %select = select <2 x i1> %cond, <2 x float> <float 0x7FF0000000000000, float 0x7FF0000000000000>, <2 x float> %x
355   ret <2 x float> %select
358 ; Fold to ret %x
359 define 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]]
364   %select = select <2 x i1> %cond, <2 x float> <float 0x7FF0000000000000, float poison>, <2 x float> %x
365   ret <2 x float> %select
368 ; Fold to ret %x
369 define 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]]
374   %select = select <2 x i1> %cond, <2 x float> <float 0x7FF0000000000000, float 0xFFF0000000000000>, <2 x float> %x
375   ret <2 x float> %select
378 ; Can't delete the select
379 define 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]]
386   %select = select i1 %cond, float 0x7FF0000000000000, float %x
387   store float %select, ptr %ptr
388   ret float %select
391 ; Can't do anything
392 define 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]]
398   %select = select i1 %cond, float 0.0, float %x
399   ret float %select
402 ; Can't do anything
403 define 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]]
409   %select = select i1 %cond, float %x, float 0.0
410   ret float %select
413 ; Can't do anything
414 define 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]]
420   %select = select i1 %cond, float 0x7FF0000000000000, float %x
421   ret float %select
424 ; Can't do anything
425 define 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]]
431   %select = select i1 %cond, float %x, float 0x7FF0000000000000
432   ret float %select
435 define 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]]
440   %select0 = select i1 %cond, float 0x7FF8000000000000, float %x
441   %select1 = select i1 %cond, float 0x7FF0000000000000, float %select0
442   ret float %select1
445 define 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
450   %select0 = select i1 %cond, float %x, float 0x7FF8000000000000
451   %select1 = select i1 %cond, float 0x7FF0000000000000, float %select0
452   ret float %select1
455 define 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]]
461   %select0 = select i1 %cond, float 0x7FF8000000000000, float %x
462   %select1 = select i1 %cond, float 0x7FF0000000000000, float %select0
463   ret float %select1
466 define 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]]
471   %select0 = select i1 %cond, float 0x7FF8000000000000, float %x
472   %select1 = select i1 %cond, float 0x7FF0000000000000, float %select0
473   ret float %select1
476 define 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
481   %select0 = select i1 %cond, float 0x7FF8000000000000, float %x
482   %select1 = select i1 %cond, float %select0, float 0x7FF0000000000000
483   ret float %select1
486 ; Simplify to fabs %x
487 define 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]]
493   %select = select i1 %cond, float %x, float 0xFFF0000000000000
494   %fabs = call float @llvm.fabs.f32(float %select)
495   ret float %fabs
498 ; Simplify to fabs %x
499 define 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]]
505   %select = select i1 %cond, float %x, float 0x7FF0000000000000
506   %fabs = call float @llvm.fabs.f32(float %select)
507   ret float %fabs
510 define 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]]
517   %select = select i1 %cond, float %x, float 0x7FF0000000000000
518   %fabs = call float @llvm.fabs.f32(float %select)
519   ret float %fabs
522 ; Fold to fabs(%x), preserving a possible nan's payload bits
523 define 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]]
529   %select = select i1 %cond, float %x, float 0x7FF0000000000000
530   %fabs = call float @llvm.fabs.f32(float %select)
531   ret float %fabs
534 define 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]]
541   %select = select i1 %cond, float %x, float 0x7FF0000000000000
542   %fabs = call float @llvm.fabs.f32(float %select)
543   ret float %fabs
546 ; Can fold to poison
547 define 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
552   %select = select i1 %cond, float %x, float 0x7FF0000000000000
553   %fabs = call float @llvm.fabs.f32(float %select)
554   ret float %fabs
557 ; Simplify to fneg %x
558 define 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]]
564   %select = select i1 %cond, float %x, float 0xFFF0000000000000
565   %fneg = fneg float %select
566   ret float %fneg
569 ; Simplify to fneg %x
570 define 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]]
576   %select = select i1 %cond, float %x, float 0x7FF0000000000000
577   %fneg = fneg float %select
578   ret float %fneg
581 ; Simplify to fneg %x
582 define 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]]
588   %select = select i1 %cond, float 0xFFF0000000000000, float %x
589   %fneg = fneg float %select
590   ret float %fneg
593 define 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]]
600   %select = select i1 %cond, float %x, float 0x7FF0000000000000
601   %fneg = fneg float %select
602   ret float %fneg
605 ; Fold to fneg fabs
606 define 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]]
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
619 ; Fold to fneg fabs, may need to preserve a nan payload
620 define 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]]
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
634 ; Fold to poison
635 define 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
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
646 ; should fold to ret copysign(%x)
647 define 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]]
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
658 define 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]]
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
669 define 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]]
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
681 ; can fold to fneg(fabs(x))
682 define 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]]
689   %copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign)
690   ret float %copysign
693 ; can fold to fneg(fabs(x))
694 define 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]]
701   %copysign = call nnan float @llvm.copysign.f32(float %x, float %unknown.sign)
702   ret float %copysign
705 ; can fold to fneg(fabs(x))
706 define 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]]
713   %copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign)
714   ret float %copysign
717 ; can fold to fabs(x)
718 define 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]]
724   %copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign)
725   ret float %copysign
728 ; can fold to fabs(x)
729 define 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]]
735   %copysign = call nnan float @llvm.copysign.f32(float %x, float %unknown.sign)
736   ret float %copysign
739 ; can fold to fabs(x)
740 define 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]]
746   %copysign = call float @llvm.copysign.f32(float %x, float %unknown.sign)
747   ret float %copysign
750 define 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]]
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
762 ; Can fold to copysign %x
763 define 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]]
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
774 ; Can fold to copysign %x
775 define 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]]
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
787 ; Can't fold because it could have nan payload bits
788 define 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]]
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
800 ; Can't fold because it could be nan
801 define 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]]
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
814 ; Could fold to copysign with constant
815 define 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]]
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
827 ; Could fold to copysign %x with constant
828 define 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]]
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
841 ; Do nothing
842 define 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]]
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
854 ; Can fold to ret %x, assumed to be nan
855 define 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]]
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
867 ; Can fold to ret +0
868 define 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]]
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
880 ; Can fold to ret poison
881 define 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]]
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
891 ; Can fold to ret %x, assumed to be nan
892 define 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]]
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
902 ; Assume should allow folding ret %y
903 define 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]]
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
918 ; Ideally should be able to fold out everything after the exp2 call.
919 define 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]]
935 entry:
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
954 ; Different implementation of powr
955 define 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]]
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
985 ; implementation of pow with some prunable cases
986 define 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]]
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
1044 declare float @extern()
1046 ; Make sure nofpclass from arbitrary callsite is used, fold to %y
1047 define 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]]
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
1058 define 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
1064   %must.be.inf = call nofpclass(nan norm zero sub) float @extern()
1065   ret float %must.be.inf
1068 define 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
1074   %must.be.inf = call nofpclass(nan norm zero sub) float @extern()
1075   ret float %must.be.inf
1078 define 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
1084   %must.be.zero = call nofpclass(nan sub norm inf) float @extern()
1085   ret float %must.be.zero
1088 define 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
1094   %must.be.zero = call nofpclass(nan sub norm inf) float @extern()
1095   ret float %must.be.zero
1098 ; Should not fold this, should not assume payload/sign bits are canonical
1099 define 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]]
1105   %must.be.nan = call nofpclass(inf norm zero sub) float @extern()
1106   ret float %must.be.nan
1109 ; Should not fold this, should not assume payload/sign bits are canonical
1110 define 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]]
1116   %must.be.nan = call nofpclass(inf norm zero sub) float @extern()
1117   ret float %must.be.nan
1120 ; Assume call should allow folding this to %y
1121 ; TODO: Not working, multiple user problem.
1122 define 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]]
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
1140 define 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]]
1151 entry:
1152   br i1 %cond, label %bb0, label %ret
1154 bb0:
1155   br label %ret
1157 ret:
1158   %phi = phi float [ 0x7FF0000000000000, %entry ], [ %x, %bb0 ]
1159   ret float %phi
1162 declare i1 @loop.cond()
1164 declare float @loop.func()
1167 ; Should be able to fold inf initial value to poison
1168 define 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]]
1182 entry:
1183   br i1 %cond0, label %loop, label %ret
1185 loop:
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
1191 ret:
1192   %phi.ret = phi float [ 0.0, %entry ], [ %phi.loop, %loop ]
1193   ret float %phi.ret
1196 ; fold to ret 0
1197 define 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
1208 entry:
1209   br i1 %cond0, label %loop, label %ret
1211 loop:
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
1216 ret:
1217   %phi.ret = phi float [ 0.0, %entry ], [ %phi.loop, %loop ]
1218   ret float %phi.ret
1221 ; fold to ret poison
1222 define 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
1233 entry:
1234   br i1 %cond0, label %loop, label %ret
1236 loop:
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
1241 ret:
1242   %phi.ret = phi float [ 0x7FF0000000000000, %entry ], [ %phi.loop, %loop ]
1243   ret float %phi.ret
1246 ; Should be able to fold inf initial values to poison
1247 define 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]]
1263 entry:
1264   switch i32 %switch, label %ret [
1265   i32 0, label %loop
1266   i32 1, label %loop
1267   ]
1269 loop:
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
1274 ret:
1275   %phi.ret = phi float [ 0.0, %entry ], [ %phi.loop, %loop ]
1276   ret float %phi.ret
1279 ; Simplify to arithmetic.fence %x
1280 define 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]]
1286   %select = select i1 %cond, float %x, float 0x7FF0000000000000
1287   %fence = call float @llvm.arithmetic.fence.f32(float %select)
1288   ret float %fence
1291 ; Can simplify to %x
1292 define 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]]
1298   %min = call float @llvm.minnum.f32(float %x, float 0x7FF0000000000000)
1299   ret float %min
1302 ; Can fold to -inf
1303 define 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
1308   %min = call float @llvm.minnum.f32(float %x, float 0xFFF0000000000000)
1309   ret float %min
1312 ; Can simplify to %x
1313 define 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]]
1319   %max = call float @llvm.maxnum.f32(float %x, float 0xFFF0000000000000)
1320   ret float %max
1323 ; Can fold to +inf
1324 define 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
1329   %max = call float @llvm.maxnum.f32(float %x, float 0x7FF0000000000000)
1330   ret float %max