1 ; Test spilling using MVC. 2 ; 3 ; RUN: llc < %s -mtriple=s390x-linux-gnu | FileCheck %s 4 5 declare void @foo() 6 7 @g0 = global i32 0 8 @g1 = global i32 1 9 @g2 = global i32 2 10 @g3 = global i32 3 11 @g4 = global i32 4 12 @g5 = global i32 5 13 @g6 = global i32 6 14 @g7 = global i32 7 15 @g8 = global i32 8 16 @g9 = global i32 9 17 18 @h0 = global i64 0 19 @h1 = global i64 1 20 @h2 = global i64 2 21 @h3 = global i64 3 22 @h4 = global i64 4 23 @h5 = global i64 5 24 @h6 = global i64 6 25 @h7 = global i64 7 26 @h8 = global i64 8 27 @h9 = global i64 9 28 29 ; This function shouldn't spill anything 30 define void @f1(i32 *%ptr0) { 31 ; CHECK-LABEL: f1: 32 ; CHECK: stmg 33 ; CHECK: aghi %r15, -160 34 ; CHECK-NOT: %r15 35 ; CHECK: brasl %r14, foo@PLT 36 ; CHECK-NOT: %r15 37 ; CHECK: lmg 38 ; CHECK: br %r14 39 %ptr1 = getelementptr i32 *%ptr0, i32 2 40 %ptr2 = getelementptr i32 *%ptr0, i32 4 41 %ptr3 = getelementptr i32 *%ptr0, i32 6 42 %ptr4 = getelementptr i32 *%ptr0, i32 8 43 %ptr5 = getelementptr i32 *%ptr0, i32 10 44 %ptr6 = getelementptr i32 *%ptr0, i32 12 45 46 %val0 = load i32 *%ptr0 47 %val1 = load i32 *%ptr1 48 %val2 = load i32 *%ptr2 49 %val3 = load i32 *%ptr3 50 %val4 = load i32 *%ptr4 51 %val5 = load i32 *%ptr5 52 %val6 = load i32 *%ptr6 53 54 call void @foo() 55 56 store i32 %val0, i32 *%ptr0 57 store i32 %val1, i32 *%ptr1 58 store i32 %val2, i32 *%ptr2 59 store i32 %val3, i32 *%ptr3 60 store i32 %val4, i32 *%ptr4 61 store i32 %val5, i32 *%ptr5 62 store i32 %val6, i32 *%ptr6 63 64 ret void 65 } 66 67 ; Test a case where at least one i32 load and at least one i32 store 68 ; need spills. 69 define void @f2(i32 *%ptr0) { 70 ; CHECK-LABEL: f2: 71 ; CHECK: mvc [[OFFSET1:16[04]]](4,%r15), [[OFFSET2:[0-9]+]]({{%r[0-9]+}}) 72 ; CHECK: brasl %r14, foo@PLT 73 ; CHECK: mvc [[OFFSET2]](4,{{%r[0-9]+}}), [[OFFSET1]](%r15) 74 ; CHECK: br %r14 75 %ptr1 = getelementptr i32 *%ptr0, i64 2 76 %ptr2 = getelementptr i32 *%ptr0, i64 4 77 %ptr3 = getelementptr i32 *%ptr0, i64 6 78 %ptr4 = getelementptr i32 *%ptr0, i64 8 79 %ptr5 = getelementptr i32 *%ptr0, i64 10 80 %ptr6 = getelementptr i32 *%ptr0, i64 12 81 %ptr7 = getelementptr i32 *%ptr0, i64 14 82 %ptr8 = getelementptr i32 *%ptr0, i64 16 83 84 %val0 = load i32 *%ptr0 85 %val1 = load i32 *%ptr1 86 %val2 = load i32 *%ptr2 87 %val3 = load i32 *%ptr3 88 %val4 = load i32 *%ptr4 89 %val5 = load i32 *%ptr5 90 %val6 = load i32 *%ptr6 91 %val7 = load i32 *%ptr7 92 %val8 = load i32 *%ptr8 93 94 call void @foo() 95 96 store i32 %val0, i32 *%ptr0 97 store i32 %val1, i32 *%ptr1 98 store i32 %val2, i32 *%ptr2 99 store i32 %val3, i32 *%ptr3 100 store i32 %val4, i32 *%ptr4 101 store i32 %val5, i32 *%ptr5 102 store i32 %val6, i32 *%ptr6 103 store i32 %val7, i32 *%ptr7 104 store i32 %val8, i32 *%ptr8 105 106 ret void 107 } 108 109 ; Test a case where at least one i64 load and at least one i64 store 110 ; need spills. 111 define void @f3(i64 *%ptr0) { 112 ; CHECK-LABEL: f3: 113 ; CHECK: mvc 160(8,%r15), [[OFFSET:[0-9]+]]({{%r[0-9]+}}) 114 ; CHECK: brasl %r14, foo@PLT 115 ; CHECK: mvc [[OFFSET]](8,{{%r[0-9]+}}), 160(%r15) 116 ; CHECK: br %r14 117 %ptr1 = getelementptr i64 *%ptr0, i64 2 118 %ptr2 = getelementptr i64 *%ptr0, i64 4 119 %ptr3 = getelementptr i64 *%ptr0, i64 6 120 %ptr4 = getelementptr i64 *%ptr0, i64 8 121 %ptr5 = getelementptr i64 *%ptr0, i64 10 122 %ptr6 = getelementptr i64 *%ptr0, i64 12 123 %ptr7 = getelementptr i64 *%ptr0, i64 14 124 %ptr8 = getelementptr i64 *%ptr0, i64 16 125 126 %val0 = load i64 *%ptr0 127 %val1 = load i64 *%ptr1 128 %val2 = load i64 *%ptr2 129 %val3 = load i64 *%ptr3 130 %val4 = load i64 *%ptr4 131 %val5 = load i64 *%ptr5 132 %val6 = load i64 *%ptr6 133 %val7 = load i64 *%ptr7 134 %val8 = load i64 *%ptr8 135 136 call void @foo() 137 138 store i64 %val0, i64 *%ptr0 139 store i64 %val1, i64 *%ptr1 140 store i64 %val2, i64 *%ptr2 141 store i64 %val3, i64 *%ptr3 142 store i64 %val4, i64 *%ptr4 143 store i64 %val5, i64 *%ptr5 144 store i64 %val6, i64 *%ptr6 145 store i64 %val7, i64 *%ptr7 146 store i64 %val8, i64 *%ptr8 147 148 ret void 149 } 150 151 152 ; Test a case where at least at least one f32 load and at least one f32 store 153 ; need spills. The 8 call-saved FPRs could be used for 8 of the %vals 154 ; (and are at the time of writing), but it would really be better to use 155 ; MVC for all 10. 156 define void @f4(float *%ptr0) { 157 ; CHECK-LABEL: f4: 158 ; CHECK: mvc [[OFFSET1:16[04]]](4,%r15), [[OFFSET2:[0-9]+]]({{%r[0-9]+}}) 159 ; CHECK: brasl %r14, foo@PLT 160 ; CHECK: mvc [[OFFSET2]](4,{{%r[0-9]+}}), [[OFFSET1]](%r15) 161 ; CHECK: br %r14 162 %ptr1 = getelementptr float *%ptr0, i64 2 163 %ptr2 = getelementptr float *%ptr0, i64 4 164 %ptr3 = getelementptr float *%ptr0, i64 6 165 %ptr4 = getelementptr float *%ptr0, i64 8 166 %ptr5 = getelementptr float *%ptr0, i64 10 167 %ptr6 = getelementptr float *%ptr0, i64 12 168 %ptr7 = getelementptr float *%ptr0, i64 14 169 %ptr8 = getelementptr float *%ptr0, i64 16 170 %ptr9 = getelementptr float *%ptr0, i64 18 171 172 %val0 = load float *%ptr0 173 %val1 = load float *%ptr1 174 %val2 = load float *%ptr2 175 %val3 = load float *%ptr3 176 %val4 = load float *%ptr4 177 %val5 = load float *%ptr5 178 %val6 = load float *%ptr6 179 %val7 = load float *%ptr7 180 %val8 = load float *%ptr8 181 %val9 = load float *%ptr9 182 183 call void @foo() 184 185 store float %val0, float *%ptr0 186 store float %val1, float *%ptr1 187 store float %val2, float *%ptr2 188 store float %val3, float *%ptr3 189 store float %val4, float *%ptr4 190 store float %val5, float *%ptr5 191 store float %val6, float *%ptr6 192 store float %val7, float *%ptr7 193 store float %val8, float *%ptr8 194 store float %val9, float *%ptr9 195 196 ret void 197 } 198 199 ; Similarly for f64. 200 define void @f5(double *%ptr0) { 201 ; CHECK-LABEL: f5: 202 ; CHECK: mvc 160(8,%r15), [[OFFSET:[0-9]+]]({{%r[0-9]+}}) 203 ; CHECK: brasl %r14, foo@PLT 204 ; CHECK: mvc [[OFFSET]](8,{{%r[0-9]+}}), 160(%r15) 205 ; CHECK: br %r14 206 %ptr1 = getelementptr double *%ptr0, i64 2 207 %ptr2 = getelementptr double *%ptr0, i64 4 208 %ptr3 = getelementptr double *%ptr0, i64 6 209 %ptr4 = getelementptr double *%ptr0, i64 8 210 %ptr5 = getelementptr double *%ptr0, i64 10 211 %ptr6 = getelementptr double *%ptr0, i64 12 212 %ptr7 = getelementptr double *%ptr0, i64 14 213 %ptr8 = getelementptr double *%ptr0, i64 16 214 %ptr9 = getelementptr double *%ptr0, i64 18 215 216 %val0 = load double *%ptr0 217 %val1 = load double *%ptr1 218 %val2 = load double *%ptr2 219 %val3 = load double *%ptr3 220 %val4 = load double *%ptr4 221 %val5 = load double *%ptr5 222 %val6 = load double *%ptr6 223 %val7 = load double *%ptr7 224 %val8 = load double *%ptr8 225 %val9 = load double *%ptr9 226 227 call void @foo() 228 229 store double %val0, double *%ptr0 230 store double %val1, double *%ptr1 231 store double %val2, double *%ptr2 232 store double %val3, double *%ptr3 233 store double %val4, double *%ptr4 234 store double %val5, double *%ptr5 235 store double %val6, double *%ptr6 236 store double %val7, double *%ptr7 237 store double %val8, double *%ptr8 238 store double %val9, double *%ptr9 239 240 ret void 241 } 242 243 ; Repeat f2 with atomic accesses. We shouldn't use MVC here. 244 define void @f6(i32 *%ptr0) { 245 ; CHECK-LABEL: f6: 246 ; CHECK-NOT: mvc 247 ; CHECK: br %r14 248 %ptr1 = getelementptr i32 *%ptr0, i64 2 249 %ptr2 = getelementptr i32 *%ptr0, i64 4 250 %ptr3 = getelementptr i32 *%ptr0, i64 6 251 %ptr4 = getelementptr i32 *%ptr0, i64 8 252 %ptr5 = getelementptr i32 *%ptr0, i64 10 253 %ptr6 = getelementptr i32 *%ptr0, i64 12 254 %ptr7 = getelementptr i32 *%ptr0, i64 14 255 %ptr8 = getelementptr i32 *%ptr0, i64 16 256 257 %val0 = load atomic i32 *%ptr0 unordered, align 4 258 %val1 = load atomic i32 *%ptr1 unordered, align 4 259 %val2 = load atomic i32 *%ptr2 unordered, align 4 260 %val3 = load atomic i32 *%ptr3 unordered, align 4 261 %val4 = load atomic i32 *%ptr4 unordered, align 4 262 %val5 = load atomic i32 *%ptr5 unordered, align 4 263 %val6 = load atomic i32 *%ptr6 unordered, align 4 264 %val7 = load atomic i32 *%ptr7 unordered, align 4 265 %val8 = load atomic i32 *%ptr8 unordered, align 4 266 267 call void @foo() 268 269 store atomic i32 %val0, i32 *%ptr0 unordered, align 4 270 store atomic i32 %val1, i32 *%ptr1 unordered, align 4 271 store atomic i32 %val2, i32 *%ptr2 unordered, align 4 272 store atomic i32 %val3, i32 *%ptr3 unordered, align 4 273 store atomic i32 %val4, i32 *%ptr4 unordered, align 4 274 store atomic i32 %val5, i32 *%ptr5 unordered, align 4 275 store atomic i32 %val6, i32 *%ptr6 unordered, align 4 276 store atomic i32 %val7, i32 *%ptr7 unordered, align 4 277 store atomic i32 %val8, i32 *%ptr8 unordered, align 4 278 279 ret void 280 } 281 282 ; ...likewise volatile accesses. 283 define void @f7(i32 *%ptr0) { 284 ; CHECK-LABEL: f7: 285 ; CHECK-NOT: mvc 286 ; CHECK: br %r14 287 %ptr1 = getelementptr i32 *%ptr0, i64 2 288 %ptr2 = getelementptr i32 *%ptr0, i64 4 289 %ptr3 = getelementptr i32 *%ptr0, i64 6 290 %ptr4 = getelementptr i32 *%ptr0, i64 8 291 %ptr5 = getelementptr i32 *%ptr0, i64 10 292 %ptr6 = getelementptr i32 *%ptr0, i64 12 293 %ptr7 = getelementptr i32 *%ptr0, i64 14 294 %ptr8 = getelementptr i32 *%ptr0, i64 16 295 296 %val0 = load volatile i32 *%ptr0 297 %val1 = load volatile i32 *%ptr1 298 %val2 = load volatile i32 *%ptr2 299 %val3 = load volatile i32 *%ptr3 300 %val4 = load volatile i32 *%ptr4 301 %val5 = load volatile i32 *%ptr5 302 %val6 = load volatile i32 *%ptr6 303 %val7 = load volatile i32 *%ptr7 304 %val8 = load volatile i32 *%ptr8 305 306 call void @foo() 307 308 store volatile i32 %val0, i32 *%ptr0 309 store volatile i32 %val1, i32 *%ptr1 310 store volatile i32 %val2, i32 *%ptr2 311 store volatile i32 %val3, i32 *%ptr3 312 store volatile i32 %val4, i32 *%ptr4 313 store volatile i32 %val5, i32 *%ptr5 314 store volatile i32 %val6, i32 *%ptr6 315 store volatile i32 %val7, i32 *%ptr7 316 store volatile i32 %val8, i32 *%ptr8 317 318 ret void 319 } 320 321 ; Check that LRL and STRL are not converted. 322 define void @f8() { 323 ; CHECK-LABEL: f8: 324 ; CHECK-NOT: mvc 325 ; CHECK: br %r14 326 %val0 = load i32 *@g0 327 %val1 = load i32 *@g1 328 %val2 = load i32 *@g2 329 %val3 = load i32 *@g3 330 %val4 = load i32 *@g4 331 %val5 = load i32 *@g5 332 %val6 = load i32 *@g6 333 %val7 = load i32 *@g7 334 %val8 = load i32 *@g8 335 %val9 = load i32 *@g9 336 337 call void @foo() 338 339 store i32 %val0, i32 *@g0 340 store i32 %val1, i32 *@g1 341 store i32 %val2, i32 *@g2 342 store i32 %val3, i32 *@g3 343 store i32 %val4, i32 *@g4 344 store i32 %val5, i32 *@g5 345 store i32 %val6, i32 *@g6 346 store i32 %val7, i32 *@g7 347 store i32 %val8, i32 *@g8 348 store i32 %val9, i32 *@g9 349 350 ret void 351 } 352 353 ; Likewise LGRL and STGRL. 354 define void @f9() { 355 ; CHECK-LABEL: f9: 356 ; CHECK-NOT: mvc 357 ; CHECK: br %r14 358 %val0 = load i64 *@h0 359 %val1 = load i64 *@h1 360 %val2 = load i64 *@h2 361 %val3 = load i64 *@h3 362 %val4 = load i64 *@h4 363 %val5 = load i64 *@h5 364 %val6 = load i64 *@h6 365 %val7 = load i64 *@h7 366 %val8 = load i64 *@h8 367 %val9 = load i64 *@h9 368 369 call void @foo() 370 371 store i64 %val0, i64 *@h0 372 store i64 %val1, i64 *@h1 373 store i64 %val2, i64 *@h2 374 store i64 %val3, i64 *@h3 375 store i64 %val4, i64 *@h4 376 store i64 %val5, i64 *@h5 377 store i64 %val6, i64 *@h6 378 store i64 %val7, i64 *@h7 379 store i64 %val8, i64 *@h8 380 store i64 %val9, i64 *@h9 381 382 ret void 383 } 384 385 ; This showed a problem with the way stack coloring updated instructions. 386 ; The copy from %val9 to %newval8 can be done using an MVC, which then 387 ; has two frame index operands. Stack coloring chose a valid renumbering 388 ; [FI0, FI1] -> [FI1, FI2], but applied it in the form FI0 -> FI1 -> FI2, 389 ; so that both operands ended up being the same. 390 define void @f10() { 391 ; CHECK-LABEL: f10: 392 ; CHECK: lgrl [[REG:%r[0-9]+]], h9 393 ; CHECK: stg [[REG]], [[VAL9:[0-9]+]](%r15) 394 ; CHECK: brasl %r14, foo@PLT 395 ; CHECK: brasl %r14, foo@PLT 396 ; CHECK: mvc [[NEWVAL8:[0-9]+]](8,%r15), [[VAL9]](%r15) 397 ; CHECK: brasl %r14, foo@PLT 398 ; CHECK: lg [[REG:%r[0-9]+]], [[NEWVAL8]](%r15) 399 ; CHECK: stgrl [[REG]], h8 400 ; CHECK: br %r14 401 entry: 402 %val0 = load volatile i64 *@h0 403 %val1 = load volatile i64 *@h1 404 %val2 = load volatile i64 *@h2 405 %val3 = load volatile i64 *@h3 406 %val4 = load volatile i64 *@h4 407 %val5 = load volatile i64 *@h5 408 %val6 = load volatile i64 *@h6 409 %val7 = load volatile i64 *@h7 410 %val8 = load volatile i64 *@h8 411 %val9 = load volatile i64 *@h9 412 413 call void @foo() 414 415 store volatile i64 %val0, i64 *@h0 416 store volatile i64 %val1, i64 *@h1 417 store volatile i64 %val2, i64 *@h2 418 store volatile i64 %val3, i64 *@h3 419 store volatile i64 %val4, i64 *@h4 420 store volatile i64 %val5, i64 *@h5 421 store volatile i64 %val6, i64 *@h6 422 store volatile i64 %val7, i64 *@h7 423 424 %check = load volatile i64 *@h0 425 %cond = icmp eq i64 %check, 0 426 br i1 %cond, label %skip, label %fallthru 427 428 fallthru: 429 call void @foo() 430 431 store volatile i64 %val0, i64 *@h0 432 store volatile i64 %val1, i64 *@h1 433 store volatile i64 %val2, i64 *@h2 434 store volatile i64 %val3, i64 *@h3 435 store volatile i64 %val4, i64 *@h4 436 store volatile i64 %val5, i64 *@h5 437 store volatile i64 %val6, i64 *@h6 438 store volatile i64 %val7, i64 *@h7 439 store volatile i64 %val8, i64 *@h8 440 br label %skip 441 442 skip: 443 %newval8 = phi i64 [ %val8, %entry ], [ %val9, %fallthru ] 444 call void @foo() 445 446 store volatile i64 %val0, i64 *@h0 447 store volatile i64 %val1, i64 *@h1 448 store volatile i64 %val2, i64 *@h2 449 store volatile i64 %val3, i64 *@h3 450 store volatile i64 %val4, i64 *@h4 451 store volatile i64 %val5, i64 *@h5 452 store volatile i64 %val6, i64 *@h6 453 store volatile i64 %val7, i64 *@h7 454 store volatile i64 %newval8, i64 *@h8 455 store volatile i64 %val9, i64 *@h9 456 457 ret void 458 } 459 460 ; This used to generate a no-op MVC. It is very sensitive to spill heuristics. 461 define void @f11() { 462 ; CHECK-LABEL: f11: 463 ; CHECK-NOT: mvc [[OFFSET:[0-9]+]](8,%r15), [[OFFSET]](%r15) 464 ; CHECK: br %r14 465 entry: 466 %val0 = load volatile i64 *@h0 467 %val1 = load volatile i64 *@h1 468 %val2 = load volatile i64 *@h2 469 %val3 = load volatile i64 *@h3 470 %val4 = load volatile i64 *@h4 471 %val5 = load volatile i64 *@h5 472 %val6 = load volatile i64 *@h6 473 %val7 = load volatile i64 *@h7 474 475 %altval0 = load volatile i64 *@h0 476 %altval1 = load volatile i64 *@h1 477 478 call void @foo() 479 480 store volatile i64 %val0, i64 *@h0 481 store volatile i64 %val1, i64 *@h1 482 store volatile i64 %val2, i64 *@h2 483 store volatile i64 %val3, i64 *@h3 484 store volatile i64 %val4, i64 *@h4 485 store volatile i64 %val5, i64 *@h5 486 store volatile i64 %val6, i64 *@h6 487 store volatile i64 %val7, i64 *@h7 488 489 %check = load volatile i64 *@h0 490 %cond = icmp eq i64 %check, 0 491 br i1 %cond, label %a1, label %b1 492 493 a1: 494 call void @foo() 495 br label %join1 496 497 b1: 498 call void @foo() 499 br label %join1 500 501 join1: 502 %newval0 = phi i64 [ %val0, %a1 ], [ %altval0, %b1 ] 503 504 call void @foo() 505 506 store volatile i64 %val1, i64 *@h1 507 store volatile i64 %val2, i64 *@h2 508 store volatile i64 %val3, i64 *@h3 509 store volatile i64 %val4, i64 *@h4 510 store volatile i64 %val5, i64 *@h5 511 store volatile i64 %val6, i64 *@h6 512 store volatile i64 %val7, i64 *@h7 513 br i1 %cond, label %a2, label %b2 514 515 a2: 516 call void @foo() 517 br label %join2 518 519 b2: 520 call void @foo() 521 br label %join2 522 523 join2: 524 %newval1 = phi i64 [ %val1, %a2 ], [ %altval1, %b2 ] 525 526 call void @foo() 527 528 store volatile i64 %val2, i64 *@h2 529 store volatile i64 %val3, i64 *@h3 530 store volatile i64 %val4, i64 *@h4 531 store volatile i64 %val5, i64 *@h5 532 store volatile i64 %val6, i64 *@h6 533 store volatile i64 %val7, i64 *@h7 534 535 call void @foo() 536 537 store volatile i64 %newval0, i64 *@h0 538 store volatile i64 %newval1, i64 *@h1 539 store volatile i64 %val2, i64 *@h2 540 store volatile i64 %val3, i64 *@h3 541 store volatile i64 %val4, i64 *@h4 542 store volatile i64 %val5, i64 *@h5 543 store volatile i64 %val6, i64 *@h6 544 store volatile i64 %val7, i64 *@h7 545 546 ret void 547 } 548