436 lines · plain
1; Test strict multiplication of two f64s, producing an f128 result.2;3; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s4 5declare fp128 @llvm.experimental.constrained.fmul.f128(fp128, fp128, metadata, metadata)6declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata)7declare double @llvm.experimental.constrained.fptrunc.f64.f128(fp128, metadata, metadata)8declare fp128 @llvm.experimental.constrained.fpext.f128.f64(double, metadata)9 10declare double @foo()11 12; Check register multiplication. "mxdbr %f0, %f2" is not valid from LLVM's13; point of view, because %f2 is the low register of the FP128 %f0. Pass the14; multiplier in %f4 instead.15define void @f1(double %f1, double %dummy, double %f2, ptr %dst) #0 {16; CHECK-LABEL: f1:17; CHECK: mxdbr %f0, %f418; CHECK: std %f0, 0(%r2)19; CHECK: std %f2, 8(%r2)20; CHECK: br %r1421 %f1x = call fp128 @llvm.experimental.constrained.fpext.f128.f64(22 double %f1,23 metadata !"fpexcept.strict") #024 %f2x = call fp128 @llvm.experimental.constrained.fpext.f128.f64(25 double %f2,26 metadata !"fpexcept.strict") #027 %res = call fp128 @llvm.experimental.constrained.fmul.f128(28 fp128 %f1x, fp128 %f2x,29 metadata !"round.dynamic",30 metadata !"fpexcept.strict") #031 store fp128 %res, ptr %dst32 ret void33}34 35; Check the low end of the MXDB range.36define void @f2(double %f1, ptr %ptr, ptr %dst) #0 {37; CHECK-LABEL: f2:38; CHECK: mxdb %f0, 0(%r2)39; CHECK: std %f0, 0(%r3)40; CHECK: std %f2, 8(%r3)41; CHECK: br %r1442 %f2 = load double, ptr %ptr43 %f1x = call fp128 @llvm.experimental.constrained.fpext.f128.f64(44 double %f1,45 metadata !"fpexcept.strict") #046 %f2x = call fp128 @llvm.experimental.constrained.fpext.f128.f64(47 double %f2,48 metadata !"fpexcept.strict") #049 %res = call fp128 @llvm.experimental.constrained.fmul.f128(50 fp128 %f1x, fp128 %f2x,51 metadata !"round.dynamic",52 metadata !"fpexcept.strict") #053 store fp128 %res, ptr %dst54 ret void55}56 57; Check the high end of the aligned MXDB range.58define void @f3(double %f1, ptr %base, ptr %dst) #0 {59; CHECK-LABEL: f3:60; CHECK: mxdb %f0, 4088(%r2)61; CHECK: std %f0, 0(%r3)62; CHECK: std %f2, 8(%r3)63; CHECK: br %r1464 %ptr = getelementptr double, ptr %base, i64 51165 %f2 = load double, ptr %ptr66 %f1x = call fp128 @llvm.experimental.constrained.fpext.f128.f64(67 double %f1,68 metadata !"fpexcept.strict") #069 %f2x = call fp128 @llvm.experimental.constrained.fpext.f128.f64(70 double %f2,71 metadata !"fpexcept.strict") #072 %res = call fp128 @llvm.experimental.constrained.fmul.f128(73 fp128 %f1x, fp128 %f2x,74 metadata !"round.dynamic",75 metadata !"fpexcept.strict") #076 store fp128 %res, ptr %dst77 ret void78}79 80; Check the next doubleword up, which needs separate address logic.81; Other sequences besides this one would be OK.82define void @f4(double %f1, ptr %base, ptr %dst) #0 {83; CHECK-LABEL: f4:84; CHECK: aghi %r2, 409685; CHECK: mxdb %f0, 0(%r2)86; CHECK: std %f0, 0(%r3)87; CHECK: std %f2, 8(%r3)88; CHECK: br %r1489 %ptr = getelementptr double, ptr %base, i64 51290 %f2 = load double, ptr %ptr91 %f1x = call fp128 @llvm.experimental.constrained.fpext.f128.f64(92 double %f1,93 metadata !"fpexcept.strict") #094 %f2x = call fp128 @llvm.experimental.constrained.fpext.f128.f64(95 double %f2,96 metadata !"fpexcept.strict") #097 %res = call fp128 @llvm.experimental.constrained.fmul.f128(98 fp128 %f1x, fp128 %f2x,99 metadata !"round.dynamic",100 metadata !"fpexcept.strict") #0101 store fp128 %res, ptr %dst102 ret void103}104 105; Check negative displacements, which also need separate address logic.106define void @f5(double %f1, ptr %base, ptr %dst) #0 {107; CHECK-LABEL: f5:108; CHECK: aghi %r2, -8109; CHECK: mxdb %f0, 0(%r2)110; CHECK: std %f0, 0(%r3)111; CHECK: std %f2, 8(%r3)112; CHECK: br %r14113 %ptr = getelementptr double, ptr %base, i64 -1114 %f2 = load double, ptr %ptr115 %f1x = call fp128 @llvm.experimental.constrained.fpext.f128.f64(116 double %f1,117 metadata !"fpexcept.strict") #0118 %f2x = call fp128 @llvm.experimental.constrained.fpext.f128.f64(119 double %f2,120 metadata !"fpexcept.strict") #0121 %res = call fp128 @llvm.experimental.constrained.fmul.f128(122 fp128 %f1x, fp128 %f2x,123 metadata !"round.dynamic",124 metadata !"fpexcept.strict") #0125 store fp128 %res, ptr %dst126 ret void127}128 129; Check that MXDB allows indices.130define void @f6(double %f1, ptr %base, i64 %index, ptr %dst) #0 {131; CHECK-LABEL: f6:132; CHECK: sllg %r1, %r3, 3133; CHECK: mxdb %f0, 800(%r1,%r2)134; CHECK: std %f0, 0(%r4)135; CHECK: std %f2, 8(%r4)136; CHECK: br %r14137 %ptr1 = getelementptr double, ptr %base, i64 %index138 %ptr2 = getelementptr double, ptr %ptr1, i64 100139 %f2 = load double, ptr %ptr2140 %f1x = call fp128 @llvm.experimental.constrained.fpext.f128.f64(141 double %f1,142 metadata !"fpexcept.strict") #0143 %f2x = call fp128 @llvm.experimental.constrained.fpext.f128.f64(144 double %f2,145 metadata !"fpexcept.strict") #0146 %res = call fp128 @llvm.experimental.constrained.fmul.f128(147 fp128 %f1x, fp128 %f2x,148 metadata !"round.dynamic",149 metadata !"fpexcept.strict") #0150 store fp128 %res, ptr %dst151 ret void152}153 154; Check that multiplications of spilled values can use MXDB rather than MXDBR.155define double @f7(ptr %ptr0) #0 {156; CHECK-LABEL: f7:157; CHECK: brasl %r14, foo@PLT158; CHECK: mxdb %f0, 160(%r15)159; CHECK: br %r14160 %ptr1 = getelementptr double, ptr %ptr0, i64 2161 %ptr2 = getelementptr double, ptr %ptr0, i64 4162 %ptr3 = getelementptr double, ptr %ptr0, i64 6163 %ptr4 = getelementptr double, ptr %ptr0, i64 8164 %ptr5 = getelementptr double, ptr %ptr0, i64 10165 %ptr6 = getelementptr double, ptr %ptr0, i64 12166 %ptr7 = getelementptr double, ptr %ptr0, i64 14167 %ptr8 = getelementptr double, ptr %ptr0, i64 16168 %ptr9 = getelementptr double, ptr %ptr0, i64 18169 %ptr10 = getelementptr double, ptr %ptr0, i64 20170 171 %val0 = load double, ptr %ptr0172 %val1 = load double, ptr %ptr1173 %val2 = load double, ptr %ptr2174 %val3 = load double, ptr %ptr3175 %val4 = load double, ptr %ptr4176 %val5 = load double, ptr %ptr5177 %val6 = load double, ptr %ptr6178 %val7 = load double, ptr %ptr7179 %val8 = load double, ptr %ptr8180 %val9 = load double, ptr %ptr9181 %val10 = load double, ptr %ptr10182 183 %frob0 = call double @llvm.experimental.constrained.fadd.f64(184 double %val0, double %val0,185 metadata !"round.dynamic",186 metadata !"fpexcept.strict") #0187 %frob1 = call double @llvm.experimental.constrained.fadd.f64(188 double %val1, double %val1,189 metadata !"round.dynamic",190 metadata !"fpexcept.strict") #0191 %frob2 = call double @llvm.experimental.constrained.fadd.f64(192 double %val2, double %val2,193 metadata !"round.dynamic",194 metadata !"fpexcept.strict") #0195 %frob3 = call double @llvm.experimental.constrained.fadd.f64(196 double %val3, double %val3,197 metadata !"round.dynamic",198 metadata !"fpexcept.strict") #0199 %frob4 = call double @llvm.experimental.constrained.fadd.f64(200 double %val4, double %val4,201 metadata !"round.dynamic",202 metadata !"fpexcept.strict") #0203 %frob5 = call double @llvm.experimental.constrained.fadd.f64(204 double %val5, double %val5,205 metadata !"round.dynamic",206 metadata !"fpexcept.strict") #0207 %frob6 = call double @llvm.experimental.constrained.fadd.f64(208 double %val6, double %val6,209 metadata !"round.dynamic",210 metadata !"fpexcept.strict") #0211 %frob7 = call double @llvm.experimental.constrained.fadd.f64(212 double %val7, double %val7,213 metadata !"round.dynamic",214 metadata !"fpexcept.strict") #0215 %frob8 = call double @llvm.experimental.constrained.fadd.f64(216 double %val8, double %val8,217 metadata !"round.dynamic",218 metadata !"fpexcept.strict") #0219 %frob9 = call double @llvm.experimental.constrained.fadd.f64(220 double %val9, double %val9,221 metadata !"round.dynamic",222 metadata !"fpexcept.strict") #0223 %frob10 = call double @llvm.experimental.constrained.fadd.f64(224 double %val10, double %val10,225 metadata !"round.dynamic",226 metadata !"fpexcept.strict") #0227 228 store double %frob0, ptr %ptr0229 store double %frob1, ptr %ptr1230 store double %frob2, ptr %ptr2231 store double %frob3, ptr %ptr3232 store double %frob4, ptr %ptr4233 store double %frob5, ptr %ptr5234 store double %frob6, ptr %ptr6235 store double %frob7, ptr %ptr7236 store double %frob8, ptr %ptr8237 store double %frob9, ptr %ptr9238 store double %frob10, ptr %ptr10239 240 %ret = call double @foo() #0241 242 %accext0 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(243 double %ret,244 metadata !"fpexcept.strict") #0245 %ext0 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(246 double %frob0,247 metadata !"fpexcept.strict") #0248 %mul0 = call fp128 @llvm.experimental.constrained.fmul.f128(249 fp128 %accext0, fp128 %ext0,250 metadata !"round.dynamic",251 metadata !"fpexcept.strict") #0252 %extra0 = call fp128 @llvm.experimental.constrained.fmul.f128(253 fp128 %mul0, fp128 0xL00000000000000003fff000001000000,254 metadata !"round.dynamic",255 metadata !"fpexcept.strict") #0256 %trunc0 = call double @llvm.experimental.constrained.fptrunc.f64.f128(257 fp128 %extra0,258 metadata !"round.dynamic",259 metadata !"fpexcept.strict") #0260 261 %accext1 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(262 double %trunc0,263 metadata !"fpexcept.strict") #0264 %ext1 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(265 double %frob1,266 metadata !"fpexcept.strict") #0267 %mul1 = call fp128 @llvm.experimental.constrained.fmul.f128(268 fp128 %accext1, fp128 %ext1,269 metadata !"round.dynamic",270 metadata !"fpexcept.strict") #0271 %extra1 = call fp128 @llvm.experimental.constrained.fmul.f128(272 fp128 %mul1, fp128 0xL00000000000000003fff000002000000,273 metadata !"round.dynamic",274 metadata !"fpexcept.strict") #0275 %trunc1 = call double @llvm.experimental.constrained.fptrunc.f64.f128(276 fp128 %extra1,277 metadata !"round.dynamic",278 metadata !"fpexcept.strict") #0279 280 %accext2 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(281 double %trunc1,282 metadata !"fpexcept.strict") #0283 %ext2 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(284 double %frob2,285 metadata !"fpexcept.strict") #0286 %mul2 = call fp128 @llvm.experimental.constrained.fmul.f128(287 fp128 %accext2, fp128 %ext2,288 metadata !"round.dynamic",289 metadata !"fpexcept.strict") #0290 %extra2 = call fp128 @llvm.experimental.constrained.fmul.f128(291 fp128 %mul2, fp128 0xL00000000000000003fff000003000000,292 metadata !"round.dynamic",293 metadata !"fpexcept.strict") #0294 %trunc2 = call double @llvm.experimental.constrained.fptrunc.f64.f128(295 fp128 %extra2,296 metadata !"round.dynamic",297 metadata !"fpexcept.strict") #0298 299 %accext3 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(300 double %trunc2,301 metadata !"fpexcept.strict") #0302 %ext3 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(303 double %frob3,304 metadata !"fpexcept.strict") #0305 %mul3 = call fp128 @llvm.experimental.constrained.fmul.f128(306 fp128 %accext3, fp128 %ext3,307 metadata !"round.dynamic",308 metadata !"fpexcept.strict") #0309 %extra3 = call fp128 @llvm.experimental.constrained.fmul.f128(310 fp128 %mul3, fp128 0xL00000000000000003fff000004000000,311 metadata !"round.dynamic",312 metadata !"fpexcept.strict") #0313 %trunc3 = call double @llvm.experimental.constrained.fptrunc.f64.f128(314 fp128 %extra3,315 metadata !"round.dynamic",316 metadata !"fpexcept.strict") #0317 318 %accext4 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(319 double %trunc3,320 metadata !"fpexcept.strict") #0321 %ext4 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(322 double %frob4,323 metadata !"fpexcept.strict") #0324 %mul4 = call fp128 @llvm.experimental.constrained.fmul.f128(325 fp128 %accext4, fp128 %ext4,326 metadata !"round.dynamic",327 metadata !"fpexcept.strict") #0328 %extra4 = call fp128 @llvm.experimental.constrained.fmul.f128(329 fp128 %mul4, fp128 0xL00000000000000003fff000005000000,330 metadata !"round.dynamic",331 metadata !"fpexcept.strict") #0332 %trunc4 = call double @llvm.experimental.constrained.fptrunc.f64.f128(333 fp128 %extra4,334 metadata !"round.dynamic",335 metadata !"fpexcept.strict") #0336 337 %accext5 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(338 double %trunc4,339 metadata !"fpexcept.strict") #0340 %ext5 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(341 double %frob5,342 metadata !"fpexcept.strict") #0343 %mul5 = call fp128 @llvm.experimental.constrained.fmul.f128(344 fp128 %accext5, fp128 %ext5,345 metadata !"round.dynamic",346 metadata !"fpexcept.strict") #0347 %extra5 = call fp128 @llvm.experimental.constrained.fmul.f128(348 fp128 %mul5, fp128 0xL00000000000000003fff000006000000,349 metadata !"round.dynamic",350 metadata !"fpexcept.strict") #0351 %trunc5 = call double @llvm.experimental.constrained.fptrunc.f64.f128(352 fp128 %extra5,353 metadata !"round.dynamic",354 metadata !"fpexcept.strict") #0355 356 %accext6 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(357 double %trunc5,358 metadata !"fpexcept.strict") #0359 %ext6 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(360 double %frob6,361 metadata !"fpexcept.strict") #0362 %mul6 = call fp128 @llvm.experimental.constrained.fmul.f128(363 fp128 %accext6, fp128 %ext6,364 metadata !"round.dynamic",365 metadata !"fpexcept.strict") #0366 %extra6 = call fp128 @llvm.experimental.constrained.fmul.f128(367 fp128 %mul6, fp128 0xL00000000000000003fff000007000000,368 metadata !"round.dynamic",369 metadata !"fpexcept.strict") #0370 %trunc6 = call double @llvm.experimental.constrained.fptrunc.f64.f128(371 fp128 %extra6,372 metadata !"round.dynamic",373 metadata !"fpexcept.strict") #0374 375 %accext7 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(376 double %trunc6,377 metadata !"fpexcept.strict") #0378 %ext7 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(379 double %frob7,380 metadata !"fpexcept.strict") #0381 %mul7 = call fp128 @llvm.experimental.constrained.fmul.f128(382 fp128 %accext7, fp128 %ext7,383 metadata !"round.dynamic",384 metadata !"fpexcept.strict") #0385 %extra7 = call fp128 @llvm.experimental.constrained.fmul.f128(386 fp128 %mul7, fp128 0xL00000000000000003fff000008000000,387 metadata !"round.dynamic",388 metadata !"fpexcept.strict") #0389 %trunc7 = call double @llvm.experimental.constrained.fptrunc.f64.f128(390 fp128 %extra7,391 metadata !"round.dynamic",392 metadata !"fpexcept.strict") #0393 394 %accext8 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(395 double %trunc7,396 metadata !"fpexcept.strict") #0397 %ext8 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(398 double %frob8,399 metadata !"fpexcept.strict") #0400 %mul8 = call fp128 @llvm.experimental.constrained.fmul.f128(401 fp128 %accext8, fp128 %ext8,402 metadata !"round.dynamic",403 metadata !"fpexcept.strict") #0404 %extra8 = call fp128 @llvm.experimental.constrained.fmul.f128(405 fp128 %mul8, fp128 0xL00000000000000003fff000009000000,406 metadata !"round.dynamic",407 metadata !"fpexcept.strict") #0408 %trunc8 = call double @llvm.experimental.constrained.fptrunc.f64.f128(409 fp128 %extra8,410 metadata !"round.dynamic",411 metadata !"fpexcept.strict") #0412 413 %accext9 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(414 double %trunc8,415 metadata !"fpexcept.strict") #0416 %ext9 = call fp128 @llvm.experimental.constrained.fpext.f128.f64(417 double %frob9,418 metadata !"fpexcept.strict") #0419 %mul9 = call fp128 @llvm.experimental.constrained.fmul.f128(420 fp128 %accext9, fp128 %ext9,421 metadata !"round.dynamic",422 metadata !"fpexcept.strict") #0423 %extra9 = call fp128 @llvm.experimental.constrained.fmul.f128(424 fp128 %mul9, fp128 0xL00000000000000003fff00000a000000,425 metadata !"round.dynamic",426 metadata !"fpexcept.strict") #0427 %trunc9 = call double @llvm.experimental.constrained.fptrunc.f64.f128(428 fp128 %extra9,429 metadata !"round.dynamic",430 metadata !"fpexcept.strict") #0431 432 ret double %trunc9433}434 435attributes #0 = { strictfp }436