1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -instsimplify -S | FileCheck %s
3
4
5; Verify that floor(10.1) is folded to 10.0 when the exception behavior is 'ignore'.
6define double @floor_01() #0 {
7; CHECK-LABEL: @floor_01(
8; CHECK-NEXT:  entry:
9; CHECK-NEXT:    ret double 1.000000e+01
10;
11entry:
12  %result = call double @llvm.experimental.constrained.floor.f64(double 1.010000e+01, metadata !"fpexcept.ignore") #0
13  ret double %result
14}
15
16; Verify that floor(-10.1) is folded to -11.0 when the exception behavior is not 'ignore'.
17define double @floor_02() #0 {
18; CHECK-LABEL: @floor_02(
19; CHECK-NEXT:  entry:
20; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.floor.f64(double -1.010000e+01, metadata !"fpexcept.strict") #[[ATTR0:[0-9]+]]
21; CHECK-NEXT:    ret double -1.100000e+01
22;
23entry:
24  %result = call double @llvm.experimental.constrained.floor.f64(double -1.010000e+01, metadata !"fpexcept.strict") #0
25  ret double %result
26}
27
28; Verify that ceil(10.1) is folded to 11.0 when the exception behavior is 'ignore'.
29define double @ceil_01() #0 {
30; CHECK-LABEL: @ceil_01(
31; CHECK-NEXT:  entry:
32; CHECK-NEXT:    ret double 1.100000e+01
33;
34entry:
35  %result = call double @llvm.experimental.constrained.ceil.f64(double 1.010000e+01, metadata !"fpexcept.ignore") #0
36  ret double %result
37}
38
39; Verify that ceil(-10.1) is folded to -10.0 when the exception behavior is not 'ignore'.
40define double @ceil_02() #0 {
41; CHECK-LABEL: @ceil_02(
42; CHECK-NEXT:  entry:
43; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.ceil.f64(double -1.010000e+01, metadata !"fpexcept.strict") #[[ATTR0]]
44; CHECK-NEXT:    ret double -1.000000e+01
45;
46entry:
47  %result = call double @llvm.experimental.constrained.ceil.f64(double -1.010000e+01, metadata !"fpexcept.strict") #0
48  ret double %result
49}
50
51; Verify that trunc(10.1) is folded to 10.0 when the exception behavior is 'ignore'.
52define double @trunc_01() #0 {
53; CHECK-LABEL: @trunc_01(
54; CHECK-NEXT:  entry:
55; CHECK-NEXT:    ret double 1.000000e+01
56;
57entry:
58  %result = call double @llvm.experimental.constrained.trunc.f64(double 1.010000e+01, metadata !"fpexcept.ignore") #0
59  ret double %result
60}
61
62; Verify that trunc(-10.1) is folded to -10.0 when the exception behavior is NOT 'ignore'.
63define double @trunc_02() #0 {
64; CHECK-LABEL: @trunc_02(
65; CHECK-NEXT:  entry:
66; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.trunc.f64(double -1.010000e+01, metadata !"fpexcept.strict") #[[ATTR0]]
67; CHECK-NEXT:    ret double -1.000000e+01
68;
69entry:
70  %result = call double @llvm.experimental.constrained.trunc.f64(double -1.010000e+01, metadata !"fpexcept.strict") #0
71  ret double %result
72}
73
74; Verify that round(10.5) is folded to 11.0 when the exception behavior is 'ignore'.
75define double @round_01() #0 {
76; CHECK-LABEL: @round_01(
77; CHECK-NEXT:  entry:
78; CHECK-NEXT:    ret double 1.100000e+01
79;
80entry:
81  %result = call double @llvm.experimental.constrained.round.f64(double 1.050000e+01, metadata !"fpexcept.ignore") #0
82  ret double %result
83}
84
85; Verify that floor(-10.5) is folded to -11.0 when the exception behavior is NOT 'ignore'.
86define double @round_02() #0 {
87; CHECK-LABEL: @round_02(
88; CHECK-NEXT:  entry:
89; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.round.f64(double -1.050000e+01, metadata !"fpexcept.strict") #[[ATTR0]]
90; CHECK-NEXT:    ret double -1.100000e+01
91;
92entry:
93  %result = call double @llvm.experimental.constrained.round.f64(double -1.050000e+01, metadata !"fpexcept.strict") #0
94  ret double %result
95}
96
97; Verify that nearbyint(10.5) is folded to 11.0 when the rounding mode is 'upward'.
98define double @nearbyint_01() #0 {
99; CHECK-LABEL: @nearbyint_01(
100; CHECK-NEXT:  entry:
101; CHECK-NEXT:    ret double 1.100000e+01
102;
103entry:
104  %result = call double @llvm.experimental.constrained.nearbyint.f64(double 1.050000e+01, metadata !"round.upward", metadata !"fpexcept.ignore") #0
105  ret double %result
106}
107
108; Verify that nearbyint(10.5) is folded to 10.0 when the rounding mode is 'downward'.
109define double @nearbyint_02() #0 {
110; CHECK-LABEL: @nearbyint_02(
111; CHECK-NEXT:  entry:
112; CHECK-NEXT:    ret double 1.000000e+01
113;
114entry:
115  %result = call double @llvm.experimental.constrained.nearbyint.f64(double 1.050000e+01, metadata !"round.downward", metadata !"fpexcept.maytrap") #0
116  ret double %result
117}
118
119; Verify that nearbyint(10.5) is folded to 10.0 when the rounding mode is 'towardzero'.
120define double @nearbyint_03() #0 {
121; CHECK-LABEL: @nearbyint_03(
122; CHECK-NEXT:  entry:
123; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.nearbyint.f64(double 1.050000e+01, metadata !"round.towardzero", metadata !"fpexcept.strict") #[[ATTR0]]
124; CHECK-NEXT:    ret double 1.000000e+01
125;
126entry:
127  %result = call double @llvm.experimental.constrained.nearbyint.f64(double 1.050000e+01, metadata !"round.towardzero", metadata !"fpexcept.strict") #0
128  ret double %result
129}
130
131; Verify that nearbyint(10.5) is folded to 10.0 when the rounding mode is 'tonearest'.
132define double @nearbyint_04() #0 {
133; CHECK-LABEL: @nearbyint_04(
134; CHECK-NEXT:  entry:
135; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.nearbyint.f64(double 1.050000e+01, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]]
136; CHECK-NEXT:    ret double 1.000000e+01
137;
138entry:
139  %result = call double @llvm.experimental.constrained.nearbyint.f64(double 1.050000e+01, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
140  ret double %result
141}
142
143; Verify that nearbyint(10.5) is NOT folded if the rounding mode is 'dynamic'.
144define double @nearbyint_05() #0 {
145; CHECK-LABEL: @nearbyint_05(
146; CHECK-NEXT:  entry:
147; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.nearbyint.f64(double 1.050000e+01, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
148; CHECK-NEXT:    ret double [[RESULT]]
149;
150entry:
151  %result = call double @llvm.experimental.constrained.nearbyint.f64(double 1.050000e+01, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
152  ret double %result
153}
154
155; Verify that trunc(SNAN) is NOT folded if the exception behavior mode is not 'ignore'.
156define double @nonfinite_01() #0 {
157; CHECK-LABEL: @nonfinite_01(
158; CHECK-NEXT:  entry:
159; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.trunc.f64(double 0x7FF4000000000000, metadata !"fpexcept.strict") #[[ATTR0]]
160; CHECK-NEXT:    ret double [[RESULT]]
161;
162entry:
163  %result = call double @llvm.experimental.constrained.trunc.f64(double 0x7ff4000000000000, metadata !"fpexcept.strict") #0
164  ret double %result
165}
166
167; Verify that trunc(SNAN) is folded to QNAN if the exception behavior mode is 'ignore'.
168define double @nonfinite_02() #0 {
169; CHECK-LABEL: @nonfinite_02(
170; CHECK-NEXT:  entry:
171; CHECK-NEXT:    ret double 0x7FF8000000000000
172;
173entry:
174  %result = call double @llvm.experimental.constrained.trunc.f64(double 0x7ff4000000000000, metadata !"fpexcept.ignore") #0
175  ret double %result
176}
177
178; Verify that trunc(QNAN) is folded even if the exception behavior mode is not 'ignore'.
179define double @nonfinite_03() #0 {
180; CHECK-LABEL: @nonfinite_03(
181; CHECK-NEXT:  entry:
182; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.trunc.f64(double 0x7FF8000000000000, metadata !"fpexcept.strict") #[[ATTR0]]
183; CHECK-NEXT:    ret double 0x7FF8000000000000
184;
185entry:
186  %result = call double @llvm.experimental.constrained.trunc.f64(double 0x7ff8000000000000, metadata !"fpexcept.strict") #0
187  ret double %result
188}
189
190; Verify that trunc(+Inf) is folded even if the exception behavior mode is not 'ignore'.
191define double @nonfinite_04() #0 {
192; CHECK-LABEL: @nonfinite_04(
193; CHECK-NEXT:  entry:
194; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.trunc.f64(double 0x7FF0000000000000, metadata !"fpexcept.strict") #[[ATTR0]]
195; CHECK-NEXT:    ret double 0x7FF0000000000000
196;
197entry:
198  %result = call double @llvm.experimental.constrained.trunc.f64(double 0x7ff0000000000000, metadata !"fpexcept.strict") #0
199  ret double %result
200}
201
202; Verify that rint(10) is folded to 10.0 when the rounding mode is 'tonearest'.
203define double @rint_01() #0 {
204; CHECK-LABEL: @rint_01(
205; CHECK-NEXT:  entry:
206; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.rint.f64(double 1.000000e+01, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]]
207; CHECK-NEXT:    ret double 1.000000e+01
208;
209entry:
210  %result = call double @llvm.experimental.constrained.rint.f64(double 1.000000e+01, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
211  ret double %result
212}
213
214; Verify that rint(10.1) is NOT folded to 10.0 when the exception behavior is 'strict'.
215define double @rint_02() #0 {
216; CHECK-LABEL: @rint_02(
217; CHECK-NEXT:  entry:
218; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.rint.f64(double 1.010000e+01, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]]
219; CHECK-NEXT:    ret double [[RESULT]]
220;
221entry:
222  %result = call double @llvm.experimental.constrained.rint.f64(double 1.010000e+01, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
223  ret double %result
224}
225
226; Verify that rint(10.1) is folded to 10.0 when the exception behavior is not 'strict'.
227define double @rint_03() #0 {
228; CHECK-LABEL: @rint_03(
229; CHECK-NEXT:  entry:
230; CHECK-NEXT:    ret double 1.000000e+01
231;
232entry:
233  %result = call double @llvm.experimental.constrained.rint.f64(double 1.010000e+01, metadata !"round.tonearest", metadata !"fpexcept.maytrap") #0
234  ret double %result
235}
236
237define float @fadd_01() #0 {
238; CHECK-LABEL: @fadd_01(
239; CHECK-NEXT:  entry:
240; CHECK-NEXT:    ret float 3.000000e+01
241;
242entry:
243  %result = call float @llvm.experimental.constrained.fadd.f32(float 1.000000e+01, float 2.000000e+01, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
244  ret float %result
245}
246
247; Inexact result does not prevent from folding if exceptions are ignored and
248; rounding mode is known.
249define double @fadd_02() #0 {
250; CHECK-LABEL: @fadd_02(
251; CHECK-NEXT:  entry:
252; CHECK-NEXT:    ret double 2.000000e+00
253;
254entry:
255  %result = call double @llvm.experimental.constrained.fadd.f64(double 1.0, double 0x3FF0000000000001, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
256  ret double %result
257}
258
259define double @fadd_03() #0 {
260; CHECK-LABEL: @fadd_03(
261; CHECK-NEXT:  entry:
262; CHECK-NEXT:    ret double 0x4000000000000001
263;
264entry:
265  %result = call double @llvm.experimental.constrained.fadd.f64(double 1.0, double 0x3FF0000000000001, metadata !"round.upward", metadata !"fpexcept.ignore") #0
266  ret double %result
267}
268
269; Inexact result prevents from folding if exceptions may be checked.
270define double @fadd_04() #0 {
271; CHECK-LABEL: @fadd_04(
272; CHECK-NEXT:  entry:
273; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double 1.000000e+00, double 0x3FF0000000000001, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]]
274; CHECK-NEXT:    ret double [[RESULT]]
275;
276entry:
277  %result = call double @llvm.experimental.constrained.fadd.f64(double 1.0, double 0x3FF0000000000001, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
278  ret double %result
279}
280
281; If result is exact, folding is allowed even if exceptions may be checked.
282define double @fadd_05() #0 {
283; CHECK-LABEL: @fadd_05(
284; CHECK-NEXT:  entry:
285; CHECK-NEXT:    ret double 3.000000e+00
286;
287entry:
288  %result = call double @llvm.experimental.constrained.fadd.f64(double 1.0, double 2.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
289  ret double %result
290}
291
292; Dynamic rounding mode does not prevent from folding if the result is exact.
293define double @fadd_06() #0 {
294; CHECK-LABEL: @fadd_06(
295; CHECK-NEXT:  entry:
296; CHECK-NEXT:    ret double 3.000000e+00
297;
298entry:
299  %result = call double @llvm.experimental.constrained.fadd.f64(double 1.0, double 2.0, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
300  ret double %result
301}
302
303; Inexact results prevents from folding if rounding mode is unknown.
304define double @fadd_07() #0 {
305; CHECK-LABEL: @fadd_07(
306; CHECK-NEXT:  entry:
307; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double 1.000000e+00, double 0x3FF0000000000001, metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
308; CHECK-NEXT:    ret double [[RESULT]]
309;
310entry:
311  %result = call double @llvm.experimental.constrained.fadd.f64(double 1.0, double 0x3FF0000000000001, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
312  ret double %result
313}
314
315; Infinite result does not prevent from folding unless exceptions are tracked.
316define double @fadd_08() #0 {
317; CHECK-LABEL: @fadd_08(
318; CHECK-NEXT:  entry:
319; CHECK-NEXT:    ret double 0x7FF0000000000000
320;
321entry:
322  %result = call double @llvm.experimental.constrained.fadd.f64(double 0x7fEFFFFFFFFFFFFF, double 0x7fEFFFFFFFFFFFFF, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
323  ret double %result
324}
325
326define double @fadd_09() #0 {
327; CHECK-LABEL: @fadd_09(
328; CHECK-NEXT:  entry:
329; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double 0x7FEFFFFFFFFFFFFF, double 0x7FEFFFFFFFFFFFFF, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]]
330; CHECK-NEXT:    ret double [[RESULT]]
331;
332entry:
333  %result = call double @llvm.experimental.constrained.fadd.f64(double 0x7fEFFFFFFFFFFFFF, double 0x7fEFFFFFFFFFFFFF, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
334  ret double %result
335}
336
337define half @fadd_10() #0 {
338; CHECK-LABEL: @fadd_10(
339; CHECK-NEXT:  entry:
340; CHECK-NEXT:    ret half 0xH4200
341;
342entry:
343  %result = call half @llvm.experimental.constrained.fadd.f16(half 1.0, half 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
344  ret half %result
345}
346
347define bfloat @fadd_11() #0 {
348; CHECK-LABEL: @fadd_11(
349; CHECK-NEXT:  entry:
350; CHECK-NEXT:    ret bfloat 0xR4040
351;
352entry:
353  %result = call bfloat @llvm.experimental.constrained.fadd.bf16(bfloat 1.0, bfloat 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
354  ret bfloat %result
355}
356
357define double @fsub_01() #0 {
358; CHECK-LABEL: @fsub_01(
359; CHECK-NEXT:  entry:
360; CHECK-NEXT:    ret double -1.000000e+00
361;
362entry:
363  %result = call double @llvm.experimental.constrained.fsub.f64(double 1.0, double 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
364  ret double %result
365}
366
367define double @fmul_01() #0 {
368; CHECK-LABEL: @fmul_01(
369; CHECK-NEXT:  entry:
370; CHECK-NEXT:    ret double 2.000000e+00
371;
372entry:
373  %result = call double @llvm.experimental.constrained.fmul.f64(double 1.0, double 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
374  ret double %result
375}
376
377define double @fdiv_01() #0 {
378; CHECK-LABEL: @fdiv_01(
379; CHECK-NEXT:  entry:
380; CHECK-NEXT:    ret double 5.000000e-01
381;
382entry:
383  %result = call double @llvm.experimental.constrained.fdiv.f64(double 1.0, double 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
384  ret double %result
385}
386
387define double @frem_01() #0 {
388; CHECK-LABEL: @frem_01(
389; CHECK-NEXT:  entry:
390; CHECK-NEXT:    ret double 1.000000e+00
391;
392entry:
393  %result = call double @llvm.experimental.constrained.frem.f64(double 1.0, double 2.0, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
394  ret double %result
395}
396
397define double @fma_01() #0 {
398; CHECK-LABEL: @fma_01(
399; CHECK-NEXT:  entry:
400; CHECK-NEXT:    ret double 5.000000e+00
401;
402entry:
403  %result = call double @llvm.experimental.constrained.fma.f64(double 1.0, double 2.0, double 3.0, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
404  ret double %result
405}
406
407define double @fmuladd_01() #0 {
408; CHECK-LABEL: @fmuladd_01(
409; CHECK-NEXT:  entry:
410; CHECK-NEXT:    ret double 5.000000e+00
411;
412entry:
413  %result = call double @llvm.experimental.constrained.fmuladd.f64(double 1.0, double 2.0, double 3.0, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
414  ret double %result
415}
416
417
418attributes #0 = { strictfp }
419
420declare double @llvm.experimental.constrained.nearbyint.f64(double, metadata, metadata)
421declare double @llvm.experimental.constrained.floor.f64(double, metadata)
422declare double @llvm.experimental.constrained.ceil.f64(double, metadata)
423declare double @llvm.experimental.constrained.trunc.f64(double, metadata)
424declare double @llvm.experimental.constrained.round.f64(double, metadata)
425declare double @llvm.experimental.constrained.rint.f64(double, metadata, metadata)
426declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata)
427declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata)
428declare half @llvm.experimental.constrained.fadd.f16(half, half, metadata, metadata)
429declare bfloat @llvm.experimental.constrained.fadd.bf16(bfloat, bfloat, metadata, metadata)
430declare double @llvm.experimental.constrained.fsub.f64(double, double, metadata, metadata)
431declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata)
432declare double @llvm.experimental.constrained.fdiv.f64(double, double, metadata, metadata)
433declare double @llvm.experimental.constrained.frem.f64(double, double, metadata, metadata)
434declare double @llvm.experimental.constrained.fma.f64(double, double, double, metadata, metadata)
435declare double @llvm.experimental.constrained.fmuladd.f64(double, double, double, metadata, metadata)
436
437