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 %s 5 6 declare 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 31 define 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. 70 define 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. 112 define 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. 157 define 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. 201 define 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. 245 define 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. 284 define 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. 323 define 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. 355 define 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. 391 define 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 402 entry: 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 429 fallthru: 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 443 skip: 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. 462 define void @f11() { 463 ; CHECK-LABEL: f11: 464 ; CHECK-NOT: mvc [[OFFSET:[0-9]+]](8,%r15), [[OFFSET]](%r15) 465 ; CHECK: br %r14 466 entry: 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 494 a1: 495 call void @foo() 496 br label %join1 497 498 b1: 499 call void @foo() 500 br label %join1 501 502 join1: 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 516 a2: 517 call void @foo() 518 br label %join2 519 520 b2: 521 call void @foo() 522 br label %join2 523 524 join2: 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