xref: /llvm-project/llvm/test/Transforms/Inline/inline-strictfp.ll (revision e5369823bc0655806469724335d0ca5a4c17d8c7)
1; RUN: opt -passes=inline %s -S | FileCheck %s
2
3
4; Ordinary function is inlined into strictfp function.
5
6define float @inlined_01(float %a) {
7entry:
8  %add = fadd float %a, %a
9  ret float %add
10}
11
12define float @host_02(float %a) #0 {
13entry:
14  %0 = call float @inlined_01(float %a) #0
15  %add = call float @llvm.experimental.constrained.fadd.f32(float %0, float 2.000000e+00, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
16  ret float %add
17; CHECK-LABEL: @host_02
18; CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
19; CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float 2.000000e+00, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
20}
21
22
23; strictfp function is inlined into another strictfp function.
24
25define float @inlined_03(float %a) #0 {
26entry:
27  %add = call float @llvm.experimental.constrained.fadd.f32(float %a, float %a, metadata !"round.downward", metadata !"fpexcept.maytrap") #0
28  ret float %add
29}
30
31define float @host_04(float %a) #0 {
32entry:
33  %0 = call float @inlined_03(float %a) #0
34  %add = call float @llvm.experimental.constrained.fadd.f32(float %0, float 2.000000e+00, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
35  ret float %add
36; CHECK-LABEL: @host_04
37; CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.downward", metadata !"fpexcept.maytrap") #0
38; CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float 2.000000e+00, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
39}
40
41
42; strictfp function is NOT inlined into ordinary function.
43
44define float @inlined_05(float %a) strictfp {
45entry:
46  %add = call float @llvm.experimental.constrained.fadd.f32(float %a, float %a, metadata !"round.downward", metadata !"fpexcept.maytrap") #0
47  ret float %add
48}
49
50define float @host_06(float %a) {
51entry:
52  %0 = call float @inlined_05(float %a)
53  %add = fadd float %0, 2.000000e+00
54  ret float %add
55; CHECK-LABEL: @host_06
56; CHECK: call float @inlined_05(float %a)
57; CHECK: fadd float %0, 2.000000e+00
58}
59
60
61; Calls in inlined function must get strictfp attribute.
62
63declare float @func_ext(float);
64
65define float @inlined_07(float %a) {
66entry:
67  %0 = call float @func_ext(float %a)
68  %add = fadd float %0, %a
69
70  ret float %add
71}
72
73define float @host_08(float %a) #0 {
74entry:
75  %0 = call float @inlined_07(float %a) #0
76  %add = call float @llvm.experimental.constrained.fadd.f32(float %0, float 2.000000e+00, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
77  ret float %add
78; CHECK-LABEL: @host_08
79; CHECK: call float @func_ext(float {{.*}}) #0
80; CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float {{.*}}, metadata !"round.tonearest", metadata !"fpexcept.ignore") #0
81; CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float 2.000000e+00, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
82}
83
84
85; Cloning particular instructions.
86
87; fpext has two overloaded types.
88define double @inlined_09(float %a) {
89entry:
90  %t = fpext float %a to double
91  ret double %t
92}
93
94define double @host_10(float %a) #0 {
95entry:
96  %0 = call double @inlined_09(float %a) #0
97  %add = call double @llvm.experimental.constrained.fadd.f64(double %0, double 2.000000e+00, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
98  ret double %add
99; CHECK-LABEL: @host_10
100; CHECK: call double @llvm.experimental.constrained.fpext.f64.f32(float {{.*}}, metadata !"fpexcept.ignore") #0
101; CHECK: call double @llvm.experimental.constrained.fadd.f64(double {{.*}}, double 2.000000e+00, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
102}
103
104; fcmp does not depend on rounding mode and has metadata argument.
105define i1 @inlined_11(float %a, float %b) {
106entry:
107  %t = fcmp oeq float %a, %b
108  ret i1 %t
109}
110
111define i1 @host_12(float %a, float %b) #0 {
112entry:
113  %add = call float @llvm.experimental.constrained.fadd.f32(float %a, float %b, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
114  %cmp = call i1 @inlined_11(float %a, float %b) #0
115  ret i1 %cmp
116; CHECK-LABEL: @host_12
117; CHECK: call float @llvm.experimental.constrained.fadd.f32(float %a, float %b, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
118; CHECK: call i1 @llvm.experimental.constrained.fcmp.f32(float {{.*}}, metadata !"oeq", metadata !"fpexcept.ignore") #0
119}
120
121; Intrinsic 'ceil' has constrained variant.
122define float @inlined_13(float %a) {
123entry:
124  %t = call float @llvm.ceil.f32(float %a)
125  ret float %t
126}
127
128define float @host_14(float %a) #0 {
129entry:
130  %0 = call float @inlined_13(float %a) #0
131  %add = call float @llvm.experimental.constrained.fadd.f32(float %0, float 2.000000e+00, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
132  ret float %add
133; CHECK-LABEL: @host_14
134; CHECK: call float @llvm.experimental.constrained.ceil.f32(float %a, metadata !"fpexcept.ignore") #0
135; CHECK: call float @llvm.experimental.constrained.fadd.f32(float {{.*}}, float 2.000000e+00, metadata !"round.dynamic", metadata !"fpexcept.strict") #0
136}
137
138attributes #0 = { strictfp }
139
140declare float  @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata)
141declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata)
142declare double @llvm.experimental.constrained.fpext.f64.f32(float, metadata)
143declare i1     @llvm.experimental.constrained.fcmp.f32(float, float, metadata, metadata)
144declare float  @llvm.experimental.constrained.ceil.f32(float, metadata)
145declare float  @llvm.ceil.f32(float)
146