xref: /llvm-project/llvm/test/Transforms/InstSimplify/ldexp.ll (revision d9a5aa8e2d755643cf4e7fa86aa831ed226fe54d)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=instsimplify < %s | FileCheck %s
3
4define float @ldexp_f32_undef_undef() {
5; CHECK-LABEL: @ldexp_f32_undef_undef(
6; CHECK-NEXT:    ret float 0x7FF8000000000000
7;
8  %call = call float @llvm.ldexp.f32.i32(float undef, i32 undef)
9  ret float %call
10}
11
12define float @ldexp_f32_poison_undef() {
13; CHECK-LABEL: @ldexp_f32_poison_undef(
14; CHECK-NEXT:    ret float poison
15;
16  %call = call float @llvm.ldexp.f32.i32(float poison, i32 undef)
17  ret float %call
18}
19
20define float @ldexp_f32_undef_poison() {
21; CHECK-LABEL: @ldexp_f32_undef_poison(
22; CHECK-NEXT:    ret float undef
23;
24  %call = call float @llvm.ldexp.f32.i32(float undef, i32 poison)
25  ret float %call
26}
27
28define float @ldexp_f32_poison_poison() {
29; CHECK-LABEL: @ldexp_f32_poison_poison(
30; CHECK-NEXT:    ret float poison
31;
32  %call = call float @llvm.ldexp.f32.i32(float poison, i32 poison)
33  ret float %call
34}
35
36; If the exponent is 0, it doesn't matter if the first argument is
37; constant or not.
38define void @ldexp_f32_exp0(float %x) {
39; CHECK-LABEL: @ldexp_f32_exp0(
40; CHECK-NEXT:    store volatile float [[X:%.*]], ptr addrspace(1) undef, align 4
41; CHECK-NEXT:    store volatile float [[X]], ptr addrspace(1) undef, align 4
42; CHECK-NEXT:    [[ONE:%.*]] = call float @llvm.ldexp.f32.i32(float [[X]], i32 1)
43; CHECK-NEXT:    store volatile float [[ONE]], ptr addrspace(1) undef, align 4
44; CHECK-NEXT:    ret void
45;
46  %zero = call float @llvm.ldexp.f32.i32(float %x, i32 0)
47  store volatile float %zero, ptr addrspace(1) undef
48
49  %undef = call float @llvm.ldexp.f32.i32(float %x, i32 undef)
50  store volatile float %undef, ptr addrspace(1) undef
51
52  %one = call float @llvm.ldexp.f32.i32(float %x, i32 1)
53  store volatile float %one, ptr addrspace(1) undef
54  ret void
55}
56
57define void @ldexp_v2f32_exp0(<2 x float> %x) {
58; CHECK-LABEL: @ldexp_v2f32_exp0(
59; CHECK-NEXT:    store volatile <2 x float> [[X:%.*]], ptr addrspace(1) undef, align 8
60; CHECK-NEXT:    [[PART_UNDEF1:%.*]] = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> [[X]], <2 x i32> <i32 undef, i32 0>)
61; CHECK-NEXT:    store volatile <2 x float> [[PART_UNDEF1]], ptr addrspace(1) undef, align 8
62; CHECK-NEXT:    store volatile <2 x float> [[X]], ptr addrspace(1) undef, align 8
63; CHECK-NEXT:    ret void
64;
65  %part.undef0 = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %x, <2 x i32> <i32 0, i32 poison>)
66  store volatile <2 x float> %part.undef0, ptr addrspace(1) undef
67
68  %part.undef1 = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %x, <2 x i32> <i32 undef, i32 0>)
69  store volatile <2 x float> %part.undef1, ptr addrspace(1) undef
70
71  %zero = call <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float> %x, <2 x i32> zeroinitializer)
72  store volatile <2 x float> %zero, ptr addrspace(1) undef
73  ret void
74}
75
76; Test variable exponent but zero or undef value.
77define void @ldexp_f32_val0(i32 %y) {
78; CHECK-LABEL: @ldexp_f32_val0(
79; CHECK-NEXT:    store volatile float 0.000000e+00, ptr addrspace(1) undef, align 4
80; CHECK-NEXT:    store volatile float -0.000000e+00, ptr addrspace(1) undef, align 4
81; CHECK-NEXT:    store volatile float 0x7FF8000000000000, ptr addrspace(1) undef, align 4
82; CHECK-NEXT:    ret void
83;
84  %zero = call float @llvm.ldexp.f32.i32(float 0.0, i32 %y)
85  store volatile float %zero, ptr addrspace(1) undef
86
87  %neg.zero = call float @llvm.ldexp.f32.i32(float -0.0, i32 %y)
88  store volatile float %neg.zero, ptr addrspace(1) undef
89
90  %undef = call float @llvm.ldexp.f32.i32(float undef, i32 %y)
91  store volatile float %undef, ptr addrspace(1) undef
92  ret void
93}
94
95define void @ldexp_f32_val_infinity(i32 %y) {
96; CHECK-LABEL: @ldexp_f32_val_infinity(
97; CHECK-NEXT:    store volatile float 0x7FF0000000000000, ptr addrspace(1) undef, align 4
98; CHECK-NEXT:    store volatile float 0xFFF0000000000000, ptr addrspace(1) undef, align 4
99; CHECK-NEXT:    store volatile float 0x7FF0000000000000, ptr addrspace(1) undef, align 4
100; CHECK-NEXT:    store volatile float 0xFFF0000000000000, ptr addrspace(1) undef, align 4
101; CHECK-NEXT:    ret void
102;
103  %inf = call float @llvm.ldexp.f32.i32(float 0x7ff0000000000000, i32 %y)
104  store volatile float %inf, ptr addrspace(1) undef
105
106  %neg.inf = call float @llvm.ldexp.f32.i32(float 0xfff0000000000000, i32 %y)
107  store volatile float %neg.inf, ptr addrspace(1) undef
108
109  %inf.zero = call float @llvm.ldexp.f32.i32(float 0x7ff0000000000000, i32 0)
110  store volatile float %inf.zero, ptr addrspace(1) undef
111
112  %neg.inf.zero = call float @llvm.ldexp.f32.i32(float 0xfff0000000000000, i32 0)
113  store volatile float %neg.inf.zero, ptr addrspace(1) undef
114
115  ret void
116}
117
118; Signaling nan should be quieted.
119; Technically this depends on the ieee_mode in the mode register.
120define void @ldexp_f32_val_nan(i32 %y) {
121; CHECK-LABEL: @ldexp_f32_val_nan(
122; CHECK-NEXT:    store volatile float 0x7FF8001000000000, ptr addrspace(1) undef, align 4
123; CHECK-NEXT:    store volatile float 0xFFF8000100000000, ptr addrspace(1) undef, align 4
124; CHECK-NEXT:    store volatile float 0x7FF8000020000000, ptr addrspace(1) undef, align 4
125; CHECK-NEXT:    store volatile float 0xFFFFFFFFE0000000, ptr addrspace(1) undef, align 4
126; CHECK-NEXT:    ret void
127;
128  %plus.qnan = call float @llvm.ldexp.f32.i32(float 0x7ff0001000000000, i32 %y)
129  store volatile float %plus.qnan, ptr addrspace(1) undef
130
131  %neg.qnan = call float @llvm.ldexp.f32.i32(float 0xfff0000100000000, i32 %y)
132  store volatile float %neg.qnan, ptr addrspace(1) undef
133
134  %plus.snan = call float @llvm.ldexp.f32.i32(float 0x7FF0000020000000, i32 %y)
135  store volatile float %plus.snan, ptr addrspace(1) undef
136
137  %neg.snan = call float @llvm.ldexp.f32.i32(float 0xFFF7FFFFE0000000, i32 %y)
138  store volatile float %neg.snan, ptr addrspace(1) undef
139
140  ret void
141}
142
143define void @ldexp_f32_val_nan_strictfp_maytrap(i32 %y) #0 {
144; CHECK-LABEL: @ldexp_f32_val_nan_strictfp_maytrap(
145; CHECK-NEXT:    [[PLUS_QNAN:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x7FF0001000000000, i32 [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0:[0-9]+]]
146; CHECK-NEXT:    store volatile float [[PLUS_QNAN]], ptr addrspace(1) undef, align 4
147; CHECK-NEXT:    [[NEG_QNAN:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0xFFF0000100000000, i32 [[Y]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
148; CHECK-NEXT:    store volatile float [[NEG_QNAN]], ptr addrspace(1) undef, align 4
149; CHECK-NEXT:    [[PLUS_SNAN:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x7FF0000020000000, i32 [[Y]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
150; CHECK-NEXT:    store volatile float [[PLUS_SNAN]], ptr addrspace(1) undef, align 4
151; CHECK-NEXT:    [[NEG_SNAN:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0xFFF7FFFFE0000000, i32 [[Y]], metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
152; CHECK-NEXT:    store volatile float [[NEG_SNAN]], ptr addrspace(1) undef, align 4
153; CHECK-NEXT:    store volatile float 0x7FF8000000000000, ptr addrspace(1) undef, align 4
154; CHECK-NEXT:    ret void
155;
156  %plus.qnan = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x7ff0001000000000, i32 %y, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
157  store volatile float %plus.qnan, ptr addrspace(1) undef
158
159  %neg.qnan = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0xfff0000100000000, i32 %y, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
160  store volatile float %neg.qnan, ptr addrspace(1) undef
161
162  %plus.snan = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x7FF0000020000000, i32 %y, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
163  store volatile float %plus.snan, ptr addrspace(1) undef
164
165  %neg.snan = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0xFFF7FFFFE0000000, i32 %y, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
166  store volatile float %neg.snan, ptr addrspace(1) undef
167
168  %undef = call float @llvm.experimental.constrained.ldexp.f32.i32(float undef, i32 %y, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
169  store volatile float %undef, ptr addrspace(1) undef
170
171  ret void
172}
173
174
175define void @ldexp_f32_val_nan_strictfp_strict(i32 %y) #0 {
176; CHECK-LABEL: @ldexp_f32_val_nan_strictfp_strict(
177; CHECK-NEXT:    [[PLUS_QNAN:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x7FF0001000000000, i32 [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
178; CHECK-NEXT:    store volatile float [[PLUS_QNAN]], ptr addrspace(1) undef, align 4
179; CHECK-NEXT:    [[NEG_QNAN:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0xFFF0000100000000, i32 [[Y]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
180; CHECK-NEXT:    store volatile float [[NEG_QNAN]], ptr addrspace(1) undef, align 4
181; CHECK-NEXT:    [[PLUS_SNAN:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x7FF0000020000000, i32 [[Y]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
182; CHECK-NEXT:    store volatile float [[PLUS_SNAN]], ptr addrspace(1) undef, align 4
183; CHECK-NEXT:    [[NEG_SNAN:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0xFFF7FFFFE0000000, i32 [[Y]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
184; CHECK-NEXT:    store volatile float [[NEG_SNAN]], ptr addrspace(1) undef, align 4
185; CHECK-NEXT:    [[UNDEF:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float undef, i32 [[Y]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
186; CHECK-NEXT:    store volatile float 0x7FF8000000000000, ptr addrspace(1) undef, align 4
187; CHECK-NEXT:    ret void
188;
189  %plus.qnan = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x7ff0001000000000, i32 %y, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
190  store volatile float %plus.qnan, ptr addrspace(1) undef
191
192  %neg.qnan = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0xfff0000100000000, i32 %y, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
193  store volatile float %neg.qnan, ptr addrspace(1) undef
194
195  %plus.snan = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x7FF0000020000000, i32 %y, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
196  store volatile float %plus.snan, ptr addrspace(1) undef
197
198  %neg.snan = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0xFFF7FFFFE0000000, i32 %y, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
199  store volatile float %neg.snan, ptr addrspace(1) undef
200
201  %undef = call float @llvm.experimental.constrained.ldexp.f32.i32(float undef, i32 %y, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
202  store volatile float %undef, ptr addrspace(1) undef
203
204  ret void
205}
206
207define void @ldexp_f32_0() {
208; CHECK-LABEL: @ldexp_f32_0(
209; CHECK-NEXT:    store volatile float 0.000000e+00, ptr addrspace(1) undef, align 4
210; CHECK-NEXT:    store volatile float -0.000000e+00, ptr addrspace(1) undef, align 4
211; CHECK-NEXT:    store volatile float 0.000000e+00, ptr addrspace(1) undef, align 4
212; CHECK-NEXT:    store volatile float 0.000000e+00, ptr addrspace(1) undef, align 4
213; CHECK-NEXT:    store volatile float 0.000000e+00, ptr addrspace(1) undef, align 4
214; CHECK-NEXT:    store volatile float 0.000000e+00, ptr addrspace(1) undef, align 4
215; CHECK-NEXT:    store volatile float 0.000000e+00, ptr addrspace(1) undef, align 4
216; CHECK-NEXT:    ret void
217;
218  %zero = call float @llvm.ldexp.f32.i32(float 0.0, i32 0)
219  store volatile float %zero, ptr addrspace(1) undef
220
221  %neg.zero = call float @llvm.ldexp.f32.i32(float -0.0, i32 0)
222  store volatile float %neg.zero, ptr addrspace(1) undef
223
224  %one = call float @llvm.ldexp.f32.i32(float 0.0, i32 1)
225  store volatile float %one, ptr addrspace(1) undef
226
227  %min.exp = call float @llvm.ldexp.f32.i32(float 0.0, i32 -126)
228  store volatile float %min.exp, ptr addrspace(1) undef
229
230  %min.exp.sub1 = call float @llvm.ldexp.f32.i32(float 0.0, i32 -127)
231  store volatile float %min.exp.sub1, ptr addrspace(1) undef
232
233  %max.exp = call float @llvm.ldexp.f32.i32(float 0.0, i32 127)
234  store volatile float %max.exp, ptr addrspace(1) undef
235
236  %max.exp.plus1 = call float @llvm.ldexp.f32.i32(float 0.0, i32 128)
237  store volatile float %max.exp.plus1, ptr addrspace(1) undef
238
239  ret void
240}
241
242define void @ldexp_f32_undef_strictfp(float %x, i32 %y) #0 {
243; CHECK-LABEL: @ldexp_f32_undef_strictfp(
244; CHECK-NEXT:    [[UNDEF_EXP:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float [[X:%.*]], i32 undef, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
245; CHECK-NEXT:    store volatile float [[UNDEF_EXP]], ptr addrspace(1) undef, align 4
246; CHECK-NEXT:    store volatile float [[X]], ptr addrspace(1) undef, align 4
247; CHECK-NEXT:    store volatile float 0x7FF8000000000000, ptr addrspace(1) undef, align 4
248; CHECK-NEXT:    store volatile float poison, ptr addrspace(1) undef, align 4
249; CHECK-NEXT:    store volatile float poison, ptr addrspace(1) undef, align 4
250; CHECK-NEXT:    store volatile float undef, ptr addrspace(1) undef, align 4
251; CHECK-NEXT:    ret void
252;
253  %undef.exp = call float @llvm.experimental.constrained.ldexp.f32.i32(float %x, i32 undef, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
254  store volatile float %undef.exp, ptr addrspace(1) undef
255  %poison.exp = call float @llvm.experimental.constrained.ldexp.f32.i32(float %x, i32 poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
256  store volatile float %poison.exp, ptr addrspace(1) undef
257  %undef.val = call float @llvm.experimental.constrained.ldexp.f32.i32(float undef, i32 %y, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
258  store volatile float %undef.val, ptr addrspace(1) undef
259  %poison.val = call float @llvm.experimental.constrained.ldexp.f32.i32(float poison, i32 %y, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
260  store volatile float %poison.val, ptr addrspace(1) undef
261  %poison.undef = call float @llvm.experimental.constrained.ldexp.f32.i32(float poison, i32 undef, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
262  store volatile float %poison.undef, ptr addrspace(1) undef
263  %undef.poison = call float @llvm.experimental.constrained.ldexp.f32.i32(float undef, i32 poison, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
264  store volatile float %undef.poison, ptr addrspace(1) undef
265  ret void
266}
267
268; Should be able to ignore strictfp in this case
269define void @ldexp_f32_0_strictfp(float %x) #0 {
270; CHECK-LABEL: @ldexp_f32_0_strictfp(
271; CHECK-NEXT:    store volatile float 0.000000e+00, ptr addrspace(1) undef, align 4
272; CHECK-NEXT:    store volatile float -0.000000e+00, ptr addrspace(1) undef, align 4
273; CHECK-NEXT:    store volatile float 0.000000e+00, ptr addrspace(1) undef, align 4
274; CHECK-NEXT:    [[UNKNOWN_ZERO:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float [[X:%.*]], i32 0, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
275; CHECK-NEXT:    store volatile float [[UNKNOWN_ZERO]], ptr addrspace(1) undef, align 4
276; CHECK-NEXT:    [[UNKNOWN_UNDEF:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float [[X]], i32 undef, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
277; CHECK-NEXT:    store volatile float [[UNKNOWN_UNDEF]], ptr addrspace(1) undef, align 4
278; CHECK-NEXT:    [[DENORMAL_0:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x380FFFFFC0000000, i32 0, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
279; CHECK-NEXT:    store volatile float [[DENORMAL_0]], ptr addrspace(1) undef, align 4
280; CHECK-NEXT:    [[DENORMAL_1:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x380FFFFFC0000000, i32 1, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #[[ATTR0]]
281; CHECK-NEXT:    store volatile float [[DENORMAL_1]], ptr addrspace(1) undef, align 4
282; CHECK-NEXT:    ret void
283;
284  %zero = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0.0, i32 0, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
285  store volatile float %zero, ptr addrspace(1) undef
286
287  %neg.zero = call float @llvm.experimental.constrained.ldexp.f32.i32(float -0.0, i32 0, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
288  store volatile float %neg.zero, ptr addrspace(1) undef
289
290  %one = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0.0, i32 1, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
291  store volatile float %one, ptr addrspace(1) undef
292
293  %unknown.zero = call float @llvm.experimental.constrained.ldexp.f32.i32(float %x, i32 0, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
294  store volatile float %unknown.zero, ptr addrspace(1) undef
295
296  %unknown.undef = call float @llvm.experimental.constrained.ldexp.f32.i32(float %x, i32 undef, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
297  store volatile float %unknown.undef, ptr addrspace(1) undef
298
299  %denormal.0 = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x380FFFFFC0000000, i32 0, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
300  store volatile float %denormal.0, ptr addrspace(1) undef
301
302  %denormal.1 = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x380FFFFFC0000000, i32 1, metadata !"round.dynamic", metadata !"fpexcept.maytrap") #0
303  store volatile float %denormal.1, ptr addrspace(1) undef
304
305  ret void
306}
307
308define void @ldexp_f32() {
309; CHECK-LABEL: @ldexp_f32(
310; CHECK-NEXT:    store volatile float 2.000000e+00, ptr addrspace(1) undef, align 4
311; CHECK-NEXT:    store volatile float 4.000000e+00, ptr addrspace(1) undef, align 4
312; CHECK-NEXT:    store volatile float 8.000000e+00, ptr addrspace(1) undef, align 4
313; CHECK-NEXT:    store volatile float 5.000000e-01, ptr addrspace(1) undef, align 4
314; CHECK-NEXT:    store volatile float 0x3810000000000000, ptr addrspace(1) undef, align 4
315; CHECK-NEXT:    store volatile float 0x3800000000000000, ptr addrspace(1) undef, align 4
316; CHECK-NEXT:    store volatile float 0x47E0000000000000, ptr addrspace(1) undef, align 4
317; CHECK-NEXT:    store volatile float 0x7FF0000000000000, ptr addrspace(1) undef, align 4
318; CHECK-NEXT:    store volatile float -2.000000e+00, ptr addrspace(1) undef, align 4
319; CHECK-NEXT:    store volatile float -4.000000e+00, ptr addrspace(1) undef, align 4
320; CHECK-NEXT:    store volatile float -8.000000e+00, ptr addrspace(1) undef, align 4
321; CHECK-NEXT:    store volatile float -5.000000e-01, ptr addrspace(1) undef, align 4
322; CHECK-NEXT:    store volatile float 0xB810000000000000, ptr addrspace(1) undef, align 4
323; CHECK-NEXT:    store volatile float 0xB800000000000000, ptr addrspace(1) undef, align 4
324; CHECK-NEXT:    store volatile float 0xC7E0000000000000, ptr addrspace(1) undef, align 4
325; CHECK-NEXT:    store volatile float 0xFFF0000000000000, ptr addrspace(1) undef, align 4
326; CHECK-NEXT:    store volatile float 0x44D5000000000000, ptr addrspace(1) undef, align 4
327; CHECK-NEXT:    ret void
328;
329  %one.one = call float @llvm.ldexp.f32.i32(float 1.0, i32 1)
330  store volatile float %one.one, ptr addrspace(1) undef
331
332  %one.two = call float @llvm.ldexp.f32.i32(float 1.0, i32 2)
333  store volatile float %one.two, ptr addrspace(1) undef
334
335  %one.three = call float @llvm.ldexp.f32.i32(float 1.0, i32 3)
336  store volatile float %one.three, ptr addrspace(1) undef
337
338  %one.negone = call float @llvm.ldexp.f32.i32(float 1.0, i32 -1)
339  store volatile float %one.negone, ptr addrspace(1) undef
340
341  %one.min.exp = call float @llvm.ldexp.f32.i32(float 1.0, i32 -126)
342  store volatile float %one.min.exp, ptr addrspace(1) undef
343
344  %one.min.exp.sub1 = call float @llvm.ldexp.f32.i32(float 1.0, i32 -127)
345  store volatile float %one.min.exp.sub1, ptr addrspace(1) undef
346
347  %one.max.exp = call float @llvm.ldexp.f32.i32(float 1.0, i32 127)
348  store volatile float %one.max.exp, ptr addrspace(1) undef
349
350  %one.max.exp.plus1 = call float @llvm.ldexp.f32.i32(float 1.0, i32 128)
351  store volatile float %one.max.exp.plus1, ptr addrspace(1) undef
352
353  %neg.one.one = call float @llvm.ldexp.f32.i32(float -1.0, i32 1)
354  store volatile float %neg.one.one, ptr addrspace(1) undef
355
356  %neg.one.two = call float @llvm.ldexp.f32.i32(float -1.0, i32 2)
357  store volatile float %neg.one.two, ptr addrspace(1) undef
358
359  %neg.one.three = call float @llvm.ldexp.f32.i32(float -1.0, i32 3)
360  store volatile float %neg.one.three, ptr addrspace(1) undef
361
362  %neg.one.negone = call float @llvm.ldexp.f32.i32(float -1.0, i32 -1)
363  store volatile float %neg.one.negone, ptr addrspace(1) undef
364
365  %neg.one.min.exp = call float @llvm.ldexp.f32.i32(float -1.0, i32 -126)
366  store volatile float %neg.one.min.exp, ptr addrspace(1) undef
367
368  %neg.one.min.exp.sub1 = call float @llvm.ldexp.f32.i32(float -1.0, i32 -127)
369  store volatile float %neg.one.min.exp.sub1, ptr addrspace(1) undef
370
371  %neg.one.max.exp = call float @llvm.ldexp.f32.i32(float -1.0, i32 127)
372  store volatile float %neg.one.max.exp, ptr addrspace(1) undef
373
374  %neg.one.max.exp.plus1 = call float @llvm.ldexp.f32.i32(float -1.0, i32 128)
375  store volatile float %neg.one.max.exp.plus1, ptr addrspace(1) undef
376
377  %fortytwo.seven = call float @llvm.ldexp.f32.i32(float 42.0, i32 73)
378  store volatile float %fortytwo.seven, ptr addrspace(1) undef
379
380  ret void
381}
382
383; Technically we should probably flush these depending on the expected
384; denormal mode of the function, but no other IR constant folding
385; considers this.
386define void @ldexp_f32_denormal() {
387; CHECK-LABEL: @ldexp_f32_denormal(
388; CHECK-NEXT:    store volatile float 0x380FFFFFC0000000, ptr addrspace(1) undef, align 4
389; CHECK-NEXT:    store volatile float 0x381FFFFFC0000000, ptr addrspace(1) undef, align 4
390; CHECK-NEXT:    ret void
391;
392  %denormal.0 = call float @llvm.ldexp.f32.i32(float 0x380FFFFFC0000000, i32 0)
393  store volatile float %denormal.0, ptr addrspace(1) undef
394
395  %denormal.1 = call float @llvm.ldexp.f32.i32(float 0x380FFFFFC0000000, i32 1)
396  store volatile float %denormal.1, ptr addrspace(1) undef
397
398  ret void
399}
400
401define void @ldexp_f64() {
402; CHECK-LABEL: @ldexp_f64(
403; CHECK-NEXT:    store volatile double 2.000000e+00, ptr addrspace(1) undef, align 8
404; CHECK-NEXT:    store volatile double 4.000000e+00, ptr addrspace(1) undef, align 8
405; CHECK-NEXT:    store volatile double 0x44D5000000000000, ptr addrspace(1) undef, align 8
406; CHECK-NEXT:    ret void
407;
408  %one.one = call double @llvm.ldexp.f64.i32(double 1.0, i32 1)
409  store volatile double %one.one, ptr addrspace(1) undef
410
411  %one.two = call double @llvm.ldexp.f64.i32(double 1.0, i32 2)
412  store volatile double %one.two, ptr addrspace(1) undef
413
414  %fortytwo.seven = call double @llvm.ldexp.f64.i32(double 42.0, i32 73)
415  store volatile double %fortytwo.seven, ptr addrspace(1) undef
416
417  ret void
418}
419
420define void @ldexp_f16() {
421; CHECK-LABEL: @ldexp_f16(
422; CHECK-NEXT:    store volatile half 0xH4000, ptr addrspace(1) undef, align 2
423; CHECK-NEXT:    store volatile half 0xH4400, ptr addrspace(1) undef, align 2
424; CHECK-NEXT:    store volatile half 0xH7C00, ptr addrspace(1) undef, align 2
425; CHECK-NEXT:    ret void
426;
427  %one.one = call half @llvm.ldexp.f16.i32(half 1.0, i32 1)
428  store volatile half %one.one, ptr addrspace(1) undef
429
430  %one.two = call half @llvm.ldexp.f16.i32(half 1.0, i32 2)
431  store volatile half %one.two, ptr addrspace(1) undef
432
433  %fortytwo.seven = call half @llvm.ldexp.f16.i32(half 42.0, i32 73)
434  store volatile half %fortytwo.seven, ptr addrspace(1) undef
435
436  ret void
437}
438
439define void @ldexp_ppcf128() {
440; CHECK-LABEL: @ldexp_ppcf128(
441; CHECK-NEXT:    store volatile ppc_fp128 0xMFFF00000000000000000000000000000, ptr addrspace(1) undef, align 16
442; CHECK-NEXT:    store volatile ppc_fp128 0xMFFFC0000000000000000000000000000, ptr addrspace(1) undef, align 16
443; CHECK-NEXT:    store volatile ppc_fp128 0xM3FD00000000000000000000000000000, ptr addrspace(1) undef, align 16
444; CHECK-NEXT:    store volatile ppc_fp128 0xM41700000000000000000000000000000, ptr addrspace(1) undef, align 16
445; CHECK-NEXT:    store volatile ppc_fp128 0xMC0700000000000000000000000000000, ptr addrspace(1) undef, align 16
446; CHECK-NEXT:    ret void
447;
448  %neginf = call ppc_fp128 @llvm.ldexp.ppcf128.i32(ppc_fp128 0xMFFF00000000000000000000000000000, i32 0)
449  store volatile ppc_fp128 %neginf, ptr addrspace(1) undef
450
451  %snan = call ppc_fp128 @llvm.ldexp.ppcf128.i32(ppc_fp128 0xMFFFC0000000000000000000000000000, i32 0)
452  store volatile ppc_fp128 %snan, ptr addrspace(1) undef
453
454  %one.neg2 = call ppc_fp128 @llvm.ldexp.ppcf128.i32(ppc_fp128 0xM3FF00000000000000000000000000000, i32 -2)
455  store volatile ppc_fp128 %one.neg2, ptr addrspace(1) undef
456
457  %one.24 = call ppc_fp128 @llvm.ldexp.ppcf128.i32(ppc_fp128 0xM3FF00000000000000000000000000000, i32 24)
458  store volatile ppc_fp128 %one.24, ptr addrspace(1) undef
459
460  %negone.8 = call ppc_fp128 @llvm.ldexp.ppcf128.i32(ppc_fp128 0xMBFF00000000000000000000000000000, i32 8)
461  store volatile ppc_fp128 %negone.8, ptr addrspace(1) undef
462
463  ret void
464}
465
466define void @constant_fold_ldexp_f32_val_strictfp(i32 %y) #0 {
467; CHECK-LABEL: @constant_fold_ldexp_f32_val_strictfp(
468; CHECK-NEXT:    [[SNAN_MAY_TRAP:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x7FF0000020000000, i32 3, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #[[ATTR0]]
469; CHECK-NEXT:    store volatile float [[SNAN_MAY_TRAP]], ptr addrspace(1) undef, align 4
470; CHECK-NEXT:    [[SNAN_MAY_NOT_TRAP:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x7FF0000020000000, i32 3, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
471; CHECK-NEXT:    store volatile float [[SNAN_MAY_NOT_TRAP]], ptr addrspace(1) undef, align 4
472; CHECK-NEXT:    [[UNKNOWN_ROUNDING:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float 2.500000e+00, i32 42, metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
473; CHECK-NEXT:    store volatile float [[UNKNOWN_ROUNDING]], ptr addrspace(1) undef, align 4
474; CHECK-NEXT:    [[NORMAL:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float 2.500000e+00, i32 42, metadata !"round.tonearest", metadata !"fpexcept.ignore") #[[ATTR0]]
475; CHECK-NEXT:    store volatile float [[NORMAL]], ptr addrspace(1) undef, align 4
476; CHECK-NEXT:    [[NORMAL_DOWN:%.*]] = call float @llvm.experimental.constrained.ldexp.f32.i32(float 2.500000e+00, i32 42, metadata !"round.downward", metadata !"fpexcept.ignore") #[[ATTR0]]
477; CHECK-NEXT:    store volatile float [[NORMAL_DOWN]], ptr addrspace(1) undef, align 4
478; CHECK-NEXT:    ret void
479;
480  %snan.may.trap = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x7FF0000020000000, i32 3, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0
481  store volatile float %snan.may.trap, ptr addrspace(1) undef
482
483  %snan.may.not.trap = call float @llvm.experimental.constrained.ldexp.f32.i32(float 0x7FF0000020000000, i32 3, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
484  store volatile float %snan.may.not.trap, ptr addrspace(1) undef
485
486  %unknown.rounding = call float @llvm.experimental.constrained.ldexp.f32.i32(float 2.5, i32 42, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
487  store volatile float %unknown.rounding, ptr addrspace(1) undef
488
489  %normal = call float @llvm.experimental.constrained.ldexp.f32.i32(float 2.5, i32 42, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
490  store volatile float %normal, ptr addrspace(1) undef
491
492  %normal.down = call float @llvm.experimental.constrained.ldexp.f32.i32(float 2.5, i32 42, metadata !"round.downward", metadata !"fpexcept.ignore") #0
493  store volatile float %normal.down, ptr addrspace(1) undef
494
495  ret void
496}
497
498declare half @llvm.ldexp.f16.i32(half, i32) #1
499declare float @llvm.ldexp.f32.i32(float, i32) #1
500declare double @llvm.ldexp.f64.i32(double, i32) #1
501declare <2 x float> @llvm.ldexp.v2f32.v2i32(<2 x float>, <2 x i32>) #1
502declare float @llvm.experimental.constrained.ldexp.f32.i32(float, i32, metadata, metadata) #1
503declare ppc_fp128 @llvm.ldexp.ppcf128.i32(ppc_fp128, i32) #1
504
505attributes #0 = { strictfp }
506attributes #1 = { nounwind readnone speculatable }
507