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