xref: /llvm-project/llvm/test/Transforms/InstSimplify/constfold-constrained.ll (revision 6982c38cb120ec7cd6a895b0363643678e362557)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=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:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double 1.000000e+00, double 2.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]]
286; CHECK-NEXT:    ret double 3.000000e+00
287;
288entry:
289  %result = call double @llvm.experimental.constrained.fadd.f64(double 1.0, double 2.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
290  ret double %result
291}
292
293; Dynamic rounding mode does not prevent from folding if the result is exact.
294define double @fadd_06() #0 {
295; CHECK-LABEL: @fadd_06(
296; CHECK-NEXT:  entry:
297; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double 1.000000e+00, double 2.000000e+00, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]]
298; CHECK-NEXT:    ret double 3.000000e+00
299;
300entry:
301  %result = call double @llvm.experimental.constrained.fadd.f64(double 1.0, double 2.0, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
302  ret double %result
303}
304
305; Inexact results prevents from folding if rounding mode is unknown.
306define double @fadd_07() #0 {
307; CHECK-LABEL: @fadd_07(
308; CHECK-NEXT:  entry:
309; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double 1.000000e+00, double 0x3FF0000000000001, metadata !"round.dynamic", metadata !"fpexcept.ignore") #[[ATTR0]]
310; CHECK-NEXT:    ret double [[RESULT]]
311;
312entry:
313  %result = call double @llvm.experimental.constrained.fadd.f64(double 1.0, double 0x3FF0000000000001, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
314  ret double %result
315}
316
317; Infinite result does not prevent from folding unless exceptions are tracked.
318define double @fadd_08() #0 {
319; CHECK-LABEL: @fadd_08(
320; CHECK-NEXT:  entry:
321; CHECK-NEXT:    ret double 0x7FF0000000000000
322;
323entry:
324  %result = call double @llvm.experimental.constrained.fadd.f64(double 0x7fEFFFFFFFFFFFFF, double 0x7fEFFFFFFFFFFFFF, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
325  ret double %result
326}
327
328define double @fadd_09() #0 {
329; CHECK-LABEL: @fadd_09(
330; CHECK-NEXT:  entry:
331; CHECK-NEXT:    [[RESULT:%.*]] = call double @llvm.experimental.constrained.fadd.f64(double 0x7FEFFFFFFFFFFFFF, double 0x7FEFFFFFFFFFFFFF, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]]
332; CHECK-NEXT:    ret double [[RESULT]]
333;
334entry:
335  %result = call double @llvm.experimental.constrained.fadd.f64(double 0x7fEFFFFFFFFFFFFF, double 0x7fEFFFFFFFFFFFFF, metadata !"round.tonearest", metadata !"fpexcept.strict") #0
336  ret double %result
337}
338
339define half @fadd_10() #0 {
340; CHECK-LABEL: @fadd_10(
341; CHECK-NEXT:  entry:
342; CHECK-NEXT:    ret half 0xH4200
343;
344entry:
345  %result = call half @llvm.experimental.constrained.fadd.f16(half 1.0, half 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
346  ret half %result
347}
348
349define bfloat @fadd_11() #0 {
350; CHECK-LABEL: @fadd_11(
351; CHECK-NEXT:  entry:
352; CHECK-NEXT:    ret bfloat 0xR4040
353;
354entry:
355  %result = call bfloat @llvm.experimental.constrained.fadd.bf16(bfloat 1.0, bfloat 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
356  ret bfloat %result
357}
358
359define double @fsub_01() #0 {
360; CHECK-LABEL: @fsub_01(
361; CHECK-NEXT:  entry:
362; CHECK-NEXT:    ret double -1.000000e+00
363;
364entry:
365  %result = call double @llvm.experimental.constrained.fsub.f64(double 1.0, double 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
366  ret double %result
367}
368
369define double @fmul_01() #0 {
370; CHECK-LABEL: @fmul_01(
371; CHECK-NEXT:  entry:
372; CHECK-NEXT:    ret double 2.000000e+00
373;
374entry:
375  %result = call double @llvm.experimental.constrained.fmul.f64(double 1.0, double 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
376  ret double %result
377}
378
379define double @fdiv_01() #0 {
380; CHECK-LABEL: @fdiv_01(
381; CHECK-NEXT:  entry:
382; CHECK-NEXT:    ret double 5.000000e-01
383;
384entry:
385  %result = call double @llvm.experimental.constrained.fdiv.f64(double 1.0, double 2.0, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
386  ret double %result
387}
388
389define double @frem_01() #0 {
390; CHECK-LABEL: @frem_01(
391; CHECK-NEXT:  entry:
392; CHECK-NEXT:    ret double 1.000000e+00
393;
394entry:
395  %result = call double @llvm.experimental.constrained.frem.f64(double 1.0, double 2.0, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
396  ret double %result
397}
398
399define double @fma_01() #0 {
400; CHECK-LABEL: @fma_01(
401; CHECK-NEXT:  entry:
402; CHECK-NEXT:    ret double 5.000000e+00
403;
404entry:
405  %result = call double @llvm.experimental.constrained.fma.f64(double 1.0, double 2.0, double 3.0, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
406  ret double %result
407}
408
409define double @fmuladd_01() #0 {
410; CHECK-LABEL: @fmuladd_01(
411; CHECK-NEXT:  entry:
412; CHECK-NEXT:    ret double 5.000000e+00
413;
414entry:
415  %result = call double @llvm.experimental.constrained.fmuladd.f64(double 1.0, double 2.0, double 3.0, metadata !"round.dynamic", metadata !"fpexcept.ignore") #0
416  ret double %result
417}
418
419
420; When exceptions are ignored, comparison of constants can be folded, even for (signaling) NaNs.
421define i1 @cmp_eq_01() #0 {
422; CHECK-LABEL: @cmp_eq_01(
423; CHECK-NEXT:  entry:
424; CHECK-NEXT:    ret i1 false
425;
426entry:
427  %result = call i1 @llvm.experimental.constrained.fcmp.f64(double 1.0, double 2.0, metadata !"oeq", metadata !"fpexcept.ignore") #0
428  ret i1 %result
429}
430
431define i1 @cmp_eq_02() #0 {
432; CHECK-LABEL: @cmp_eq_02(
433; CHECK-NEXT:  entry:
434; CHECK-NEXT:    ret i1 true
435;
436entry:
437  %result = call i1 @llvm.experimental.constrained.fcmp.f64(double 2.0, double 2.0, metadata !"oeq", metadata !"fpexcept.ignore") #0
438  ret i1 %result
439}
440
441define <2 x i1> @cmp_eq_02a() #0 {
442; CHECK-LABEL: @cmp_eq_02a(
443; CHECK-NEXT:  entry:
444; CHECK-NEXT:    ret <2 x i1> <i1 true, i1 false>
445;
446entry:
447  %result = call <2 x i1> @llvm.experimental.constrained.fcmp.v2f64(<2 x double> <double 2.0, double 3.0>, <2 x double> <double 2.0, double 2.0>, metadata !"oeq", metadata !"fpexcept.ignore") #0
448  ret <2 x i1> %result
449}
450
451define i1 @cmp_eq_03() #0 {
452; CHECK-LABEL: @cmp_eq_03(
453; CHECK-NEXT:  entry:
454; CHECK-NEXT:    ret i1 false
455;
456entry:
457  %result = call i1 @llvm.experimental.constrained.fcmp.f64(double 2.0, double 0x7ff8000000000000, metadata !"oeq", metadata !"fpexcept.ignore") #0
458  ret i1 %result
459}
460
461define i1 @cmp_eq_04() #0 {
462; CHECK-LABEL: @cmp_eq_04(
463; CHECK-NEXT:  entry:
464; CHECK-NEXT:    ret i1 false
465;
466entry:
467  %result = call i1 @llvm.experimental.constrained.fcmp.f64(double 2.0, double 0x7ff4000000000000, metadata !"oeq", metadata !"fpexcept.ignore") #0
468  ret i1 %result
469}
470
471define i1 @cmp_eq_05() #0 {
472; CHECK-LABEL: @cmp_eq_05(
473; CHECK-NEXT:  entry:
474; CHECK-NEXT:    ret i1 false
475;
476entry:
477  %result = call i1 @llvm.experimental.constrained.fcmps.f64(double 2.0, double 0x7ff8000000000000, metadata !"oeq", metadata !"fpexcept.ignore") #0
478  ret i1 %result
479}
480
481define i1 @cmp_eq_06() #0 {
482; CHECK-LABEL: @cmp_eq_06(
483; CHECK-NEXT:  entry:
484; CHECK-NEXT:    ret i1 false
485;
486entry:
487  %result = call i1 @llvm.experimental.constrained.fcmps.f64(double 2.0, double 0x7ff4000000000000, metadata !"oeq", metadata !"fpexcept.ignore") #0
488  ret i1 %result
489}
490
491; Compare with SNAN is NOT folded if the exception behavior mode is not 'ignore'.
492define i1 @cmp_eq_nan_01() #0 {
493; CHECK-LABEL: @cmp_eq_nan_01(
494; CHECK-NEXT:  entry:
495; CHECK-NEXT:    [[RESULT:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f64(double 0x7FF4000000000000, double 1.000000e+00, metadata !"oeq", metadata !"fpexcept.strict") #[[ATTR0]]
496; CHECK-NEXT:    ret i1 [[RESULT]]
497;
498entry:
499  %result = call i1 @llvm.experimental.constrained.fcmp.f64(double 0x7ff4000000000000, double 1.0, metadata !"oeq", metadata !"fpexcept.strict") #0
500  ret i1 %result
501}
502
503define i1 @cmp_eq_nan_02() #0 {
504; CHECK-LABEL: @cmp_eq_nan_02(
505; CHECK-NEXT:  entry:
506; CHECK-NEXT:    [[RESULT:%.*]] = call i1 @llvm.experimental.constrained.fcmps.f64(double 0x7FF4000000000000, double 1.000000e+00, metadata !"oeq", metadata !"fpexcept.strict") #[[ATTR0]]
507; CHECK-NEXT:    ret i1 [[RESULT]]
508;
509entry:
510  %result = call i1 @llvm.experimental.constrained.fcmps.f64(double 0x7ff4000000000000, double 1.0, metadata !"oeq", metadata !"fpexcept.strict") #0
511  ret i1 %result
512}
513
514; Compare with QNAN is folded for fcmp but is NOT folded for fcmps if the exception behavior mode is not 'ignore'.
515define i1 @cmp_eq_nan_03() #0 {
516; CHECK-LABEL: @cmp_eq_nan_03(
517; CHECK-NEXT:  entry:
518; CHECK-NEXT:    [[RESULT:%.*]] = call i1 @llvm.experimental.constrained.fcmp.f64(double 0x7FF8000000000000, double 1.000000e+00, metadata !"oeq", metadata !"fpexcept.strict") #[[ATTR0]]
519; CHECK-NEXT:    ret i1 false
520;
521entry:
522  %result = call i1 @llvm.experimental.constrained.fcmp.f64(double 0x7ff8000000000000, double 1.0, metadata !"oeq", metadata !"fpexcept.strict") #0
523  ret i1 %result
524}
525
526define i1 @cmp_eq_nan_04() #0 {
527; CHECK-LABEL: @cmp_eq_nan_04(
528; CHECK-NEXT:  entry:
529; CHECK-NEXT:    [[RESULT:%.*]] = call i1 @llvm.experimental.constrained.fcmps.f64(double 0x7FF8000000000000, double 1.000000e+00, metadata !"oeq", metadata !"fpexcept.strict") #[[ATTR0]]
530; CHECK-NEXT:    ret i1 [[RESULT]]
531;
532entry:
533  %result = call i1 @llvm.experimental.constrained.fcmps.f64(double 0x7ff8000000000000, double 1.0, metadata !"oeq", metadata !"fpexcept.strict") #0
534  ret i1 %result
535}
536
537
538attributes #0 = { strictfp }
539
540declare double @llvm.experimental.constrained.nearbyint.f64(double, metadata, metadata)
541declare double @llvm.experimental.constrained.floor.f64(double, metadata)
542declare double @llvm.experimental.constrained.ceil.f64(double, metadata)
543declare double @llvm.experimental.constrained.trunc.f64(double, metadata)
544declare double @llvm.experimental.constrained.round.f64(double, metadata)
545declare double @llvm.experimental.constrained.rint.f64(double, metadata, metadata)
546declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata)
547declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata)
548declare half @llvm.experimental.constrained.fadd.f16(half, half, metadata, metadata)
549declare bfloat @llvm.experimental.constrained.fadd.bf16(bfloat, bfloat, metadata, metadata)
550declare double @llvm.experimental.constrained.fsub.f64(double, double, metadata, metadata)
551declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata)
552declare double @llvm.experimental.constrained.fdiv.f64(double, double, metadata, metadata)
553declare double @llvm.experimental.constrained.frem.f64(double, double, metadata, metadata)
554declare double @llvm.experimental.constrained.fma.f64(double, double, double, metadata, metadata)
555declare double @llvm.experimental.constrained.fmuladd.f64(double, double, double, metadata, metadata)
556declare i1 @llvm.experimental.constrained.fcmp.f64(double, double, metadata, metadata)
557declare <2 x i1> @llvm.experimental.constrained.fcmp.v2f64(<2 x double>, <2 x double>, metadata, metadata)
558declare i1 @llvm.experimental.constrained.fcmps.f64(double, double, metadata, metadata)
559
560