1 ; Test strict multiplication of two f32s, producing an f64 result.
2 ; FIXME: we do not have a strict version of fpext yet
4 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s
7 declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata)
9 ; Check register multiplication.
10 define double @f1(float %f1, float %f2) {
12 ; CHECK: mdebr %f0, %f2
14 %f1x = fpext float %f1 to double
15 %f2x = fpext float %f2 to double
16 %res = call double @llvm.experimental.constrained.fmul.f64(
17 double %f1x, double %f2x,
18 metadata !"round.dynamic",
19 metadata !"fpexcept.strict")
23 ; Check the low end of the MDEB range.
24 define double @f2(float %f1, float *%ptr) {
26 ; CHECK: mdeb %f0, 0(%r2)
28 %f2 = load float, float *%ptr
29 %f1x = fpext float %f1 to double
30 %f2x = fpext float %f2 to double
31 %res = call double @llvm.experimental.constrained.fmul.f64(
32 double %f1x, double %f2x,
33 metadata !"round.dynamic",
34 metadata !"fpexcept.strict")
38 ; Check the high end of the aligned MDEB range.
39 define double @f3(float %f1, float *%base) {
41 ; CHECK: mdeb %f0, 4092(%r2)
43 %ptr = getelementptr float, float *%base, i64 1023
44 %f2 = load float, float *%ptr
45 %f1x = fpext float %f1 to double
46 %f2x = fpext float %f2 to double
47 %res = call double @llvm.experimental.constrained.fmul.f64(
48 double %f1x, double %f2x,
49 metadata !"round.dynamic",
50 metadata !"fpexcept.strict")
54 ; Check the next word up, which needs separate address logic.
55 ; Other sequences besides this one would be OK.
56 define double @f4(float %f1, float *%base) {
58 ; CHECK: aghi %r2, 4096
59 ; CHECK: mdeb %f0, 0(%r2)
61 %ptr = getelementptr float, float *%base, i64 1024
62 %f2 = load float, float *%ptr
63 %f1x = fpext float %f1 to double
64 %f2x = fpext float %f2 to double
65 %res = call double @llvm.experimental.constrained.fmul.f64(
66 double %f1x, double %f2x,
67 metadata !"round.dynamic",
68 metadata !"fpexcept.strict")
72 ; Check negative displacements, which also need separate address logic.
73 define double @f5(float %f1, float *%base) {
76 ; CHECK: mdeb %f0, 0(%r2)
78 %ptr = getelementptr float, float *%base, i64 -1
79 %f2 = load float, float *%ptr
80 %f1x = fpext float %f1 to double
81 %f2x = fpext float %f2 to double
82 %res = call double @llvm.experimental.constrained.fmul.f64(
83 double %f1x, double %f2x,
84 metadata !"round.dynamic",
85 metadata !"fpexcept.strict")
89 ; Check that MDEB allows indices.
90 define double @f6(float %f1, float *%base, i64 %index) {
92 ; CHECK: sllg %r1, %r3, 2
93 ; CHECK: mdeb %f0, 400(%r1,%r2)
95 %ptr1 = getelementptr float, float *%base, i64 %index
96 %ptr2 = getelementptr float, float *%ptr1, i64 100
97 %f2 = load float, float *%ptr2
98 %f1x = fpext float %f1 to double
99 %f2x = fpext float %f2 to double
100 %res = call double @llvm.experimental.constrained.fmul.f64(
101 double %f1x, double %f2x,
102 metadata !"round.dynamic",
103 metadata !"fpexcept.strict")
107 ; Check that multiplications of spilled values can use MDEB rather than MDEBR.
108 define float @f7(float *%ptr0) {
110 ; CHECK: brasl %r14, foo@PLT
111 ; CHECK: mdeb %f0, 16{{[04]}}(%r15)
113 %ptr1 = getelementptr float, float *%ptr0, i64 2
114 %ptr2 = getelementptr float, float *%ptr0, i64 4
115 %ptr3 = getelementptr float, float *%ptr0, i64 6
116 %ptr4 = getelementptr float, float *%ptr0, i64 8
117 %ptr5 = getelementptr float, float *%ptr0, i64 10
118 %ptr6 = getelementptr float, float *%ptr0, i64 12
119 %ptr7 = getelementptr float, float *%ptr0, i64 14
120 %ptr8 = getelementptr float, float *%ptr0, i64 16
121 %ptr9 = getelementptr float, float *%ptr0, i64 18
122 %ptr10 = getelementptr float, float *%ptr0, i64 20
124 %val0 = load float, float *%ptr0
125 %val1 = load float, float *%ptr1
126 %val2 = load float, float *%ptr2
127 %val3 = load float, float *%ptr3
128 %val4 = load float, float *%ptr4
129 %val5 = load float, float *%ptr5
130 %val6 = load float, float *%ptr6
131 %val7 = load float, float *%ptr7
132 %val8 = load float, float *%ptr8
133 %val9 = load float, float *%ptr9
134 %val10 = load float, float *%ptr10
136 %frob0 = fadd float %val0, %val0
137 %frob1 = fadd float %val1, %val1
138 %frob2 = fadd float %val2, %val2
139 %frob3 = fadd float %val3, %val3
140 %frob4 = fadd float %val4, %val4
141 %frob5 = fadd float %val5, %val5
142 %frob6 = fadd float %val6, %val6
143 %frob7 = fadd float %val7, %val7
144 %frob8 = fadd float %val8, %val8
145 %frob9 = fadd float %val9, %val9
146 %frob10 = fadd float %val9, %val10
148 store float %frob0, float *%ptr0
149 store float %frob1, float *%ptr1
150 store float %frob2, float *%ptr2
151 store float %frob3, float *%ptr3
152 store float %frob4, float *%ptr4
153 store float %frob5, float *%ptr5
154 store float %frob6, float *%ptr6
155 store float %frob7, float *%ptr7
156 store float %frob8, float *%ptr8
157 store float %frob9, float *%ptr9
158 store float %frob10, float *%ptr10
160 %ret = call float @foo()
162 %accext0 = fpext float %ret to double
163 %ext0 = fpext float %frob0 to double
164 %mul0 = call double @llvm.experimental.constrained.fmul.f64(
165 double %accext0, double %ext0,
166 metadata !"round.dynamic",
167 metadata !"fpexcept.strict")
168 %extra0 = call double @llvm.experimental.constrained.fmul.f64(
169 double %mul0, double 1.01,
170 metadata !"round.dynamic",
171 metadata !"fpexcept.strict")
172 %trunc0 = fptrunc double %extra0 to float
174 %accext1 = fpext float %trunc0 to double
175 %ext1 = fpext float %frob1 to double
176 %mul1 = call double @llvm.experimental.constrained.fmul.f64(
177 double %accext1, double %ext1,
178 metadata !"round.dynamic",
179 metadata !"fpexcept.strict")
180 %extra1 = call double @llvm.experimental.constrained.fmul.f64(
181 double %mul1, double 1.11,
182 metadata !"round.dynamic",
183 metadata !"fpexcept.strict")
184 %trunc1 = fptrunc double %extra1 to float
186 %accext2 = fpext float %trunc1 to double
187 %ext2 = fpext float %frob2 to double
188 %mul2 = call double @llvm.experimental.constrained.fmul.f64(
189 double %accext2, double %ext2,
190 metadata !"round.dynamic",
191 metadata !"fpexcept.strict")
192 %extra2 = call double @llvm.experimental.constrained.fmul.f64(
193 double %mul2, double 1.21,
194 metadata !"round.dynamic",
195 metadata !"fpexcept.strict")
196 %trunc2 = fptrunc double %extra2 to float
198 %accext3 = fpext float %trunc2 to double
199 %ext3 = fpext float %frob3 to double
200 %mul3 = call double @llvm.experimental.constrained.fmul.f64(
201 double %accext3, double %ext3,
202 metadata !"round.dynamic",
203 metadata !"fpexcept.strict")
204 %extra3 = call double @llvm.experimental.constrained.fmul.f64(
205 double %mul3, double 1.31,
206 metadata !"round.dynamic",
207 metadata !"fpexcept.strict")
208 %trunc3 = fptrunc double %extra3 to float
210 %accext4 = fpext float %trunc3 to double
211 %ext4 = fpext float %frob4 to double
212 %mul4 = call double @llvm.experimental.constrained.fmul.f64(
213 double %accext4, double %ext4,
214 metadata !"round.dynamic",
215 metadata !"fpexcept.strict")
216 %extra4 = call double @llvm.experimental.constrained.fmul.f64(
217 double %mul4, double 1.41,
218 metadata !"round.dynamic",
219 metadata !"fpexcept.strict")
220 %trunc4 = fptrunc double %extra4 to float
222 %accext5 = fpext float %trunc4 to double
223 %ext5 = fpext float %frob5 to double
224 %mul5 = call double @llvm.experimental.constrained.fmul.f64(
225 double %accext5, double %ext5,
226 metadata !"round.dynamic",
227 metadata !"fpexcept.strict")
228 %extra5 = call double @llvm.experimental.constrained.fmul.f64(
229 double %mul5, double 1.51,
230 metadata !"round.dynamic",
231 metadata !"fpexcept.strict")
232 %trunc5 = fptrunc double %extra5 to float
234 %accext6 = fpext float %trunc5 to double
235 %ext6 = fpext float %frob6 to double
236 %mul6 = call double @llvm.experimental.constrained.fmul.f64(
237 double %accext6, double %ext6,
238 metadata !"round.dynamic",
239 metadata !"fpexcept.strict")
240 %extra6 = call double @llvm.experimental.constrained.fmul.f64(
241 double %mul6, double 1.61,
242 metadata !"round.dynamic",
243 metadata !"fpexcept.strict")
244 %trunc6 = fptrunc double %extra6 to float
246 %accext7 = fpext float %trunc6 to double
247 %ext7 = fpext float %frob7 to double
248 %mul7 = call double @llvm.experimental.constrained.fmul.f64(
249 double %accext7, double %ext7,
250 metadata !"round.dynamic",
251 metadata !"fpexcept.strict")
252 %extra7 = call double @llvm.experimental.constrained.fmul.f64(
253 double %mul7, double 1.71,
254 metadata !"round.dynamic",
255 metadata !"fpexcept.strict")
256 %trunc7 = fptrunc double %extra7 to float
258 %accext8 = fpext float %trunc7 to double
259 %ext8 = fpext float %frob8 to double
260 %mul8 = call double @llvm.experimental.constrained.fmul.f64(
261 double %accext8, double %ext8,
262 metadata !"round.dynamic",
263 metadata !"fpexcept.strict")
264 %extra8 = call double @llvm.experimental.constrained.fmul.f64(
265 double %mul8, double 1.81,
266 metadata !"round.dynamic",
267 metadata !"fpexcept.strict")
268 %trunc8 = fptrunc double %extra8 to float
270 %accext9 = fpext float %trunc8 to double
271 %ext9 = fpext float %frob9 to double
272 %mul9 = call double @llvm.experimental.constrained.fmul.f64(
273 double %accext9, double %ext9,
274 metadata !"round.dynamic",
275 metadata !"fpexcept.strict")
276 %extra9 = call double @llvm.experimental.constrained.fmul.f64(
277 double %mul9, double 1.91,
278 metadata !"round.dynamic",
279 metadata !"fpexcept.strict")
280 %trunc9 = fptrunc double %extra9 to float