Home | History | Annotate | Download | only in SystemZ
      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