549 lines · plain
1; Test spilling using MVC. The tests here assume z10 register pressure,2; without the high words being available.3;4; RUN: llc < %s -mtriple=s390x-linux-gnu -mcpu=z10 -verify-machineinstrs | FileCheck %s5 6declare void @foo()7 8@g0 = dso_local global i32 09@g1 = dso_local global i32 110@g2 = dso_local global i32 211@g3 = dso_local global i32 312@g4 = dso_local global i32 413@g5 = dso_local global i32 514@g6 = dso_local global i32 615@g7 = dso_local global i32 716@g8 = dso_local global i32 817@g9 = dso_local global i32 918 19@h0 = dso_local global i64 020@h1 = dso_local global i64 121@h2 = dso_local global i64 222@h3 = dso_local global i64 323@h4 = dso_local global i64 424@h5 = dso_local global i64 525@h6 = dso_local global i64 626@h7 = dso_local global i64 727@h8 = dso_local global i64 828@h9 = dso_local global i64 929 30; This function shouldn't spill anything31define dso_local void @f1(ptr %ptr0) {32; CHECK-LABEL: f1:33; CHECK: stmg34; CHECK: aghi %r15, -16035; CHECK-NOT: %r1536; CHECK: brasl %r14, foo@PLT37; CHECK-NOT: %r1538; CHECK: lmg39; CHECK: br %r1440 %ptr1 = getelementptr i32, ptr %ptr0, i32 241 %ptr2 = getelementptr i32, ptr %ptr0, i32 442 %ptr3 = getelementptr i32, ptr %ptr0, i32 643 %ptr4 = getelementptr i32, ptr %ptr0, i32 844 %ptr5 = getelementptr i32, ptr %ptr0, i32 1045 %ptr6 = getelementptr i32, ptr %ptr0, i32 1246 47 %val0 = load i32, ptr %ptr048 %val1 = load i32, ptr %ptr149 %val2 = load i32, ptr %ptr250 %val3 = load i32, ptr %ptr351 %val4 = load i32, ptr %ptr452 %val5 = load i32, ptr %ptr553 %val6 = load i32, ptr %ptr654 55 call void @foo()56 57 store i32 %val0, ptr %ptr058 store i32 %val1, ptr %ptr159 store i32 %val2, ptr %ptr260 store i32 %val3, ptr %ptr361 store i32 %val4, ptr %ptr462 store i32 %val5, ptr %ptr563 store i32 %val6, ptr %ptr664 65 ret void66}67 68; Test a case where at least one i32 load and at least one i32 store69; need spills.70define dso_local void @f2(ptr %ptr0) {71; CHECK-LABEL: f2:72; CHECK: mvc [[OFFSET1:16[04]]](4,%r15), [[OFFSET2:[0-9]+]]({{%r[0-9]+}})73; CHECK: brasl %r14, foo@PLT74; CHECK: mvc [[OFFSET2]](4,{{%r[0-9]+}}), [[OFFSET1]](%r15)75; CHECK: br %r1476 %ptr1 = getelementptr i32, ptr %ptr0, i64 277 %ptr2 = getelementptr i32, ptr %ptr0, i64 478 %ptr3 = getelementptr i32, ptr %ptr0, i64 679 %ptr4 = getelementptr i32, ptr %ptr0, i64 880 %ptr5 = getelementptr i32, ptr %ptr0, i64 1081 %ptr6 = getelementptr i32, ptr %ptr0, i64 1282 %ptr7 = getelementptr i32, ptr %ptr0, i64 1483 %ptr8 = getelementptr i32, ptr %ptr0, i64 1684 85 %val0 = load i32, ptr %ptr086 %val1 = load i32, ptr %ptr187 %val2 = load i32, ptr %ptr288 %val3 = load i32, ptr %ptr389 %val4 = load i32, ptr %ptr490 %val5 = load i32, ptr %ptr591 %val6 = load i32, ptr %ptr692 %val7 = load i32, ptr %ptr793 %val8 = load i32, ptr %ptr894 95 call void @foo()96 97 store i32 %val0, ptr %ptr098 store i32 %val1, ptr %ptr199 store i32 %val2, ptr %ptr2100 store i32 %val3, ptr %ptr3101 store i32 %val4, ptr %ptr4102 store i32 %val5, ptr %ptr5103 store i32 %val6, ptr %ptr6104 store i32 %val7, ptr %ptr7105 store i32 %val8, ptr %ptr8106 107 ret void108}109 110; Test a case where at least one i64 load and at least one i64 store111; need spills.112define dso_local void @f3(ptr %ptr0) {113; CHECK-LABEL: f3:114; CHECK: mvc 160(8,%r15), [[OFFSET:[0-9]+]]({{%r[0-9]+}})115; CHECK: brasl %r14, foo@PLT116; CHECK: mvc [[OFFSET]](8,{{%r[0-9]+}}), 160(%r15)117; CHECK: br %r14118 %ptr1 = getelementptr i64, ptr %ptr0, i64 2119 %ptr2 = getelementptr i64, ptr %ptr0, i64 4120 %ptr3 = getelementptr i64, ptr %ptr0, i64 6121 %ptr4 = getelementptr i64, ptr %ptr0, i64 8122 %ptr5 = getelementptr i64, ptr %ptr0, i64 10123 %ptr6 = getelementptr i64, ptr %ptr0, i64 12124 %ptr7 = getelementptr i64, ptr %ptr0, i64 14125 %ptr8 = getelementptr i64, ptr %ptr0, i64 16126 127 %val0 = load i64, ptr %ptr0128 %val1 = load i64, ptr %ptr1129 %val2 = load i64, ptr %ptr2130 %val3 = load i64, ptr %ptr3131 %val4 = load i64, ptr %ptr4132 %val5 = load i64, ptr %ptr5133 %val6 = load i64, ptr %ptr6134 %val7 = load i64, ptr %ptr7135 %val8 = load i64, ptr %ptr8136 137 call void @foo()138 139 store i64 %val0, ptr %ptr0140 store i64 %val1, ptr %ptr1141 store i64 %val2, ptr %ptr2142 store i64 %val3, ptr %ptr3143 store i64 %val4, ptr %ptr4144 store i64 %val5, ptr %ptr5145 store i64 %val6, ptr %ptr6146 store i64 %val7, ptr %ptr7147 store i64 %val8, ptr %ptr8148 149 ret void150}151 152 153; Test a case where at least at least one f32 load and at least one f32 store154; need spills. The 8 call-saved FPRs could be used for 8 of the %vals155; (and are at the time of writing), but it would really be better to use156; MVC for all 10.157define dso_local void @f4(ptr %ptr0) {158; CHECK-LABEL: f4:159; CHECK: mvc [[OFFSET1:16[04]]](4,%r15), [[OFFSET2:[0-9]+]]({{%r[0-9]+}})160; CHECK: brasl %r14, foo@PLT161; CHECK: mvc [[OFFSET2]](4,{{%r[0-9]+}}), [[OFFSET1]](%r15)162; CHECK: br %r14163 %ptr1 = getelementptr float, ptr %ptr0, i64 2164 %ptr2 = getelementptr float, ptr %ptr0, i64 4165 %ptr3 = getelementptr float, ptr %ptr0, i64 6166 %ptr4 = getelementptr float, ptr %ptr0, i64 8167 %ptr5 = getelementptr float, ptr %ptr0, i64 10168 %ptr6 = getelementptr float, ptr %ptr0, i64 12169 %ptr7 = getelementptr float, ptr %ptr0, i64 14170 %ptr8 = getelementptr float, ptr %ptr0, i64 16171 %ptr9 = getelementptr float, ptr %ptr0, i64 18172 173 %val0 = load float, ptr %ptr0174 %val1 = load float, ptr %ptr1175 %val2 = load float, ptr %ptr2176 %val3 = load float, ptr %ptr3177 %val4 = load float, ptr %ptr4178 %val5 = load float, ptr %ptr5179 %val6 = load float, ptr %ptr6180 %val7 = load float, ptr %ptr7181 %val8 = load float, ptr %ptr8182 %val9 = load float, ptr %ptr9183 184 call void @foo()185 186 store float %val0, ptr %ptr0187 store float %val1, ptr %ptr1188 store float %val2, ptr %ptr2189 store float %val3, ptr %ptr3190 store float %val4, ptr %ptr4191 store float %val5, ptr %ptr5192 store float %val6, ptr %ptr6193 store float %val7, ptr %ptr7194 store float %val8, ptr %ptr8195 store float %val9, ptr %ptr9196 197 ret void198}199 200; Similarly for f64.201define dso_local void @f5(ptr %ptr0) {202; CHECK-LABEL: f5:203; CHECK: mvc 160(8,%r15), [[OFFSET:[0-9]+]]({{%r[0-9]+}})204; CHECK: brasl %r14, foo@PLT205; CHECK: mvc [[OFFSET]](8,{{%r[0-9]+}}), 160(%r15)206; CHECK: br %r14207 %ptr1 = getelementptr double, ptr %ptr0, i64 2208 %ptr2 = getelementptr double, ptr %ptr0, i64 4209 %ptr3 = getelementptr double, ptr %ptr0, i64 6210 %ptr4 = getelementptr double, ptr %ptr0, i64 8211 %ptr5 = getelementptr double, ptr %ptr0, i64 10212 %ptr6 = getelementptr double, ptr %ptr0, i64 12213 %ptr7 = getelementptr double, ptr %ptr0, i64 14214 %ptr8 = getelementptr double, ptr %ptr0, i64 16215 %ptr9 = getelementptr double, ptr %ptr0, i64 18216 217 %val0 = load double, ptr %ptr0218 %val1 = load double, ptr %ptr1219 %val2 = load double, ptr %ptr2220 %val3 = load double, ptr %ptr3221 %val4 = load double, ptr %ptr4222 %val5 = load double, ptr %ptr5223 %val6 = load double, ptr %ptr6224 %val7 = load double, ptr %ptr7225 %val8 = load double, ptr %ptr8226 %val9 = load double, ptr %ptr9227 228 call void @foo()229 230 store double %val0, ptr %ptr0231 store double %val1, ptr %ptr1232 store double %val2, ptr %ptr2233 store double %val3, ptr %ptr3234 store double %val4, ptr %ptr4235 store double %val5, ptr %ptr5236 store double %val6, ptr %ptr6237 store double %val7, ptr %ptr7238 store double %val8, ptr %ptr8239 store double %val9, ptr %ptr9240 241 ret void242}243 244; Repeat f2 with atomic accesses. We shouldn't use MVC here.245define dso_local void @f6(ptr %ptr0) {246; CHECK-LABEL: f6:247; CHECK-NOT: mvc248; CHECK: br %r14249 %ptr1 = getelementptr i32, ptr %ptr0, i64 2250 %ptr2 = getelementptr i32, ptr %ptr0, i64 4251 %ptr3 = getelementptr i32, ptr %ptr0, i64 6252 %ptr4 = getelementptr i32, ptr %ptr0, i64 8253 %ptr5 = getelementptr i32, ptr %ptr0, i64 10254 %ptr6 = getelementptr i32, ptr %ptr0, i64 12255 %ptr7 = getelementptr i32, ptr %ptr0, i64 14256 %ptr8 = getelementptr i32, ptr %ptr0, i64 16257 258 %val0 = load atomic i32, ptr %ptr0 unordered, align 4259 %val1 = load atomic i32, ptr %ptr1 unordered, align 4260 %val2 = load atomic i32, ptr %ptr2 unordered, align 4261 %val3 = load atomic i32, ptr %ptr3 unordered, align 4262 %val4 = load atomic i32, ptr %ptr4 unordered, align 4263 %val5 = load atomic i32, ptr %ptr5 unordered, align 4264 %val6 = load atomic i32, ptr %ptr6 unordered, align 4265 %val7 = load atomic i32, ptr %ptr7 unordered, align 4266 %val8 = load atomic i32, ptr %ptr8 unordered, align 4267 268 call void @foo()269 270 store atomic i32 %val0, ptr %ptr0 unordered, align 4271 store atomic i32 %val1, ptr %ptr1 unordered, align 4272 store atomic i32 %val2, ptr %ptr2 unordered, align 4273 store atomic i32 %val3, ptr %ptr3 unordered, align 4274 store atomic i32 %val4, ptr %ptr4 unordered, align 4275 store atomic i32 %val5, ptr %ptr5 unordered, align 4276 store atomic i32 %val6, ptr %ptr6 unordered, align 4277 store atomic i32 %val7, ptr %ptr7 unordered, align 4278 store atomic i32 %val8, ptr %ptr8 unordered, align 4279 280 ret void281}282 283; ...likewise volatile accesses.284define dso_local void @f7(ptr %ptr0) {285; CHECK-LABEL: f7:286; CHECK-NOT: mvc287; CHECK: br %r14288 %ptr1 = getelementptr i32, ptr %ptr0, i64 2289 %ptr2 = getelementptr i32, ptr %ptr0, i64 4290 %ptr3 = getelementptr i32, ptr %ptr0, i64 6291 %ptr4 = getelementptr i32, ptr %ptr0, i64 8292 %ptr5 = getelementptr i32, ptr %ptr0, i64 10293 %ptr6 = getelementptr i32, ptr %ptr0, i64 12294 %ptr7 = getelementptr i32, ptr %ptr0, i64 14295 %ptr8 = getelementptr i32, ptr %ptr0, i64 16296 297 %val0 = load volatile i32, ptr %ptr0298 %val1 = load volatile i32, ptr %ptr1299 %val2 = load volatile i32, ptr %ptr2300 %val3 = load volatile i32, ptr %ptr3301 %val4 = load volatile i32, ptr %ptr4302 %val5 = load volatile i32, ptr %ptr5303 %val6 = load volatile i32, ptr %ptr6304 %val7 = load volatile i32, ptr %ptr7305 %val8 = load volatile i32, ptr %ptr8306 307 call void @foo()308 309 store volatile i32 %val0, ptr %ptr0310 store volatile i32 %val1, ptr %ptr1311 store volatile i32 %val2, ptr %ptr2312 store volatile i32 %val3, ptr %ptr3313 store volatile i32 %val4, ptr %ptr4314 store volatile i32 %val5, ptr %ptr5315 store volatile i32 %val6, ptr %ptr6316 store volatile i32 %val7, ptr %ptr7317 store volatile i32 %val8, ptr %ptr8318 319 ret void320}321 322; Check that LRL and STRL are not converted.323define dso_local void @f8() {324; CHECK-LABEL: f8:325; CHECK-NOT: mvc326; CHECK: br %r14327 %val0 = load i32, ptr@g0328 %val1 = load i32, ptr@g1329 %val2 = load i32, ptr@g2330 %val3 = load i32, ptr@g3331 %val4 = load i32, ptr@g4332 %val5 = load i32, ptr@g5333 %val6 = load i32, ptr@g6334 %val7 = load i32, ptr@g7335 %val8 = load i32, ptr@g8336 %val9 = load i32, ptr@g9337 338 call void @foo()339 340 store i32 %val0, ptr@g0341 store i32 %val1, ptr@g1342 store i32 %val2, ptr@g2343 store i32 %val3, ptr@g3344 store i32 %val4, ptr@g4345 store i32 %val5, ptr@g5346 store i32 %val6, ptr@g6347 store i32 %val7, ptr@g7348 store i32 %val8, ptr@g8349 store i32 %val9, ptr@g9350 351 ret void352}353 354; Likewise LGRL and STGRL.355define dso_local void @f9() {356; CHECK-LABEL: f9:357; CHECK-NOT: mvc358; CHECK: br %r14359 %val0 = load i64, ptr@h0360 %val1 = load i64, ptr@h1361 %val2 = load i64, ptr@h2362 %val3 = load i64, ptr@h3363 %val4 = load i64, ptr@h4364 %val5 = load i64, ptr@h5365 %val6 = load i64, ptr@h6366 %val7 = load i64, ptr@h7367 %val8 = load i64, ptr@h8368 %val9 = load i64, ptr@h9369 370 call void @foo()371 372 store i64 %val0, ptr@h0373 store i64 %val1, ptr@h1374 store i64 %val2, ptr@h2375 store i64 %val3, ptr@h3376 store i64 %val4, ptr@h4377 store i64 %val5, ptr@h5378 store i64 %val6, ptr@h6379 store i64 %val7, ptr@h7380 store i64 %val8, ptr@h8381 store i64 %val9, ptr@h9382 383 ret void384}385 386; This showed a problem with the way stack coloring updated instructions.387; The copy from %val9 to %newval8 can be done using an MVC, which then388; has two frame index operands. Stack coloring chose a valid renumbering389; [FI0, FI1] -> [FI1, FI2], but applied it in the form FI0 -> FI1 -> FI2,390; so that both operands ended up being the same.391define dso_local void @f10() {392; CHECK-LABEL: f10:393; CHECK: lgrl [[REG:%r[0-9]+]], h9394; CHECK: stg [[REG]], [[VAL9:[0-9]+]](%r15)395; CHECK: brasl %r14, foo@PLT396; CHECK: brasl %r14, foo@PLT397; CHECK: mvc [[NEWVAL8:[0-9]+]](8,%r15), [[VAL9]](%r15)398; CHECK: brasl %r14, foo@PLT399; CHECK: lg [[REG:%r[0-9]+]], [[NEWVAL8]](%r15)400; CHECK: stgrl [[REG]], h8401; CHECK: br %r14402entry:403 %val8 = load volatile i64, ptr@h8404 %val0 = load volatile i64, ptr@h0405 %val1 = load volatile i64, ptr@h1406 %val2 = load volatile i64, ptr@h2407 %val3 = load volatile i64, ptr@h3408 %val4 = load volatile i64, ptr@h4409 %val5 = load volatile i64, ptr@h5410 %val6 = load volatile i64, ptr@h6411 %val7 = load volatile i64, ptr@h7412 %val9 = load volatile i64, ptr@h9413 414 call void @foo()415 416 store volatile i64 %val0, ptr@h0417 store volatile i64 %val1, ptr@h1418 store volatile i64 %val2, ptr@h2419 store volatile i64 %val3, ptr@h3420 store volatile i64 %val4, ptr@h4421 store volatile i64 %val5, ptr@h5422 store volatile i64 %val6, ptr@h6423 store volatile i64 %val7, ptr@h7424 425 %check = load volatile i64, ptr@h0426 %cond = icmp eq i64 %check, 0427 br i1 %cond, label %skip, label %fallthru428 429fallthru:430 call void @foo()431 432 store volatile i64 %val0, ptr@h0433 store volatile i64 %val1, ptr@h1434 store volatile i64 %val2, ptr@h2435 store volatile i64 %val3, ptr@h3436 store volatile i64 %val4, ptr@h4437 store volatile i64 %val5, ptr@h5438 store volatile i64 %val6, ptr@h6439 store volatile i64 %val7, ptr@h7440 store volatile i64 %val8, ptr@h8441 br label %skip442 443skip:444 %newval8 = phi i64 [ %val8, %entry ], [ %val9, %fallthru ]445 call void @foo()446 447 store volatile i64 %val0, ptr@h0448 store volatile i64 %val1, ptr@h1449 store volatile i64 %val2, ptr@h2450 store volatile i64 %val3, ptr@h3451 store volatile i64 %val4, ptr@h4452 store volatile i64 %val5, ptr@h5453 store volatile i64 %val6, ptr@h6454 store volatile i64 %val7, ptr@h7455 store volatile i64 %newval8, ptr@h8456 store volatile i64 %val9, ptr@h9457 458 ret void459}460 461; This used to generate a no-op MVC. It is very sensitive to spill heuristics.462define dso_local void @f11() {463; CHECK-LABEL: f11:464; CHECK-NOT: mvc [[OFFSET:[0-9]+]](8,%r15), [[OFFSET]](%r15)465; CHECK: br %r14466entry:467 %val0 = load volatile i64, ptr@h0468 %val1 = load volatile i64, ptr@h1469 %val2 = load volatile i64, ptr@h2470 %val3 = load volatile i64, ptr@h3471 %val4 = load volatile i64, ptr@h4472 %val5 = load volatile i64, ptr@h5473 %val6 = load volatile i64, ptr@h6474 %val7 = load volatile i64, ptr@h7475 476 %altval0 = load volatile i64, ptr@h0477 %altval1 = load volatile i64, ptr@h1478 479 call void @foo()480 481 store volatile i64 %val0, ptr@h0482 store volatile i64 %val1, ptr@h1483 store volatile i64 %val2, ptr@h2484 store volatile i64 %val3, ptr@h3485 store volatile i64 %val4, ptr@h4486 store volatile i64 %val5, ptr@h5487 store volatile i64 %val6, ptr@h6488 store volatile i64 %val7, ptr@h7489 490 %check = load volatile i64, ptr@h0491 %cond = icmp eq i64 %check, 0492 br i1 %cond, label %a1, label %b1493 494a1:495 call void @foo()496 br label %join1497 498b1:499 call void @foo()500 br label %join1501 502join1:503 %newval0 = phi i64 [ %val0, %a1 ], [ %altval0, %b1 ]504 505 call void @foo()506 507 store volatile i64 %val1, ptr@h1508 store volatile i64 %val2, ptr@h2509 store volatile i64 %val3, ptr@h3510 store volatile i64 %val4, ptr@h4511 store volatile i64 %val5, ptr@h5512 store volatile i64 %val6, ptr@h6513 store volatile i64 %val7, ptr@h7514 br i1 %cond, label %a2, label %b2515 516a2:517 call void @foo()518 br label %join2519 520b2:521 call void @foo()522 br label %join2523 524join2:525 %newval1 = phi i64 [ %val1, %a2 ], [ %altval1, %b2 ]526 527 call void @foo()528 529 store volatile i64 %val2, ptr@h2530 store volatile i64 %val3, ptr@h3531 store volatile i64 %val4, ptr@h4532 store volatile i64 %val5, ptr@h5533 store volatile i64 %val6, ptr@h6534 store volatile i64 %val7, ptr@h7535 536 call void @foo()537 538 store volatile i64 %newval0, ptr@h0539 store volatile i64 %newval1, ptr@h1540 store volatile i64 %val2, ptr@h2541 store volatile i64 %val3, ptr@h3542 store volatile i64 %val4, ptr@h4543 store volatile i64 %val5, ptr@h5544 store volatile i64 %val6, ptr@h6545 store volatile i64 %val7, ptr@h7546 547 ret void548}549