Home | History | Annotate | Download | only in AMDGPU
      1 # RUN: llc -march=amdgcn -run-pass detect-dead-lanes -o - %s | FileCheck %s
      2 ...
      3 ---
      4 # Combined use/def transfer check, the basics.
      5 # CHECK-LABEL: name: test0
      6 # CHECK: S_NOP 0, implicit-def %0
      7 # CHECK: S_NOP 0, implicit-def %1
      8 # CHECK: S_NOP 0, implicit-def dead %2
      9 # CHECK: %3:sreg_128 = REG_SEQUENCE %0,  %subreg.sub0, %1,  %subreg.sub1, undef %2, %subreg.sub3
     10 # CHECK: S_NOP 0, implicit %3.sub0
     11 # CHECK: S_NOP 0, implicit %3.sub1
     12 # CHECK: S_NOP 0, implicit undef %3.sub2
     13 # CHECK: %4:sreg_64 = COPY %3.sub0_sub1
     14 # CHECK: %5:sreg_64 = COPY undef %3.sub2_sub3
     15 # CHECK: S_NOP 0, implicit %4.sub0
     16 # CHECK: S_NOP 0, implicit %4.sub1
     17 # CHECK: S_NOP 0, implicit undef %5.sub0
     18 name: test0
     19 registers:
     20   - { id: 0, class: sreg_32_xm0 }
     21   - { id: 1, class: sreg_32_xm0 }
     22   - { id: 2, class: sreg_32_xm0 }
     23   - { id: 3, class: sreg_128 }
     24   - { id: 4, class: sreg_64 }
     25   - { id: 5, class: sreg_64 }
     26 body: |
     27   bb.0:
     28     S_NOP 0, implicit-def %0
     29     S_NOP 0, implicit-def %1
     30     S_NOP 0, implicit-def %2
     31     %3 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub3
     32     S_NOP 0, implicit %3.sub0
     33     S_NOP 0, implicit %3.sub1
     34     S_NOP 0, implicit %3.sub2
     35     %4 = COPY %3.sub0_sub1
     36     %5 = COPY %3.sub2_sub3
     37     S_NOP 0, implicit %4.sub0
     38     S_NOP 0, implicit %4.sub1
     39     S_NOP 0, implicit %5.sub0
     40 ...
     41 ---
     42 # Check defined lanes transfer; Includes checking for some special cases like
     43 # undef operands or IMPLICIT_DEF definitions.
     44 # CHECK-LABEL: name: test1
     45 # CHECK: %0:sreg_128 = REG_SEQUENCE $sgpr0, %subreg.sub0, $sgpr0, %subreg.sub2
     46 # CHECK: %1:sreg_128 = INSERT_SUBREG %0, $sgpr1,  %subreg.sub3
     47 # CHECK: %2:sreg_64 = INSERT_SUBREG %0.sub2_sub3, $sgpr42,  %subreg.sub0
     48 # CHECK: S_NOP 0, implicit %1.sub0
     49 # CHECK: S_NOP 0, implicit undef %1.sub1
     50 # CHECK: S_NOP 0, implicit %1.sub2
     51 # CHECK: S_NOP 0, implicit %1.sub3
     52 # CHECK: S_NOP 0, implicit %2.sub0
     53 # CHECK: S_NOP 0, implicit undef %2.sub1
     54 
     55 # CHECK: %3:sreg_32_xm0 = IMPLICIT_DEF
     56 # CHECK: %4:sreg_128 = INSERT_SUBREG %0, undef %3, %subreg.sub0
     57 # CHECK: S_NOP 0, implicit undef %4.sub0
     58 # CHECK: S_NOP 0, implicit undef %4.sub1
     59 # CHECK: S_NOP 0, implicit %4.sub2
     60 # CHECK: S_NOP 0, implicit undef %4.sub3
     61 
     62 # CHECK: %5:sreg_64 = EXTRACT_SUBREG %0, %subreg.sub0_sub1
     63 # CHECK: %6:sreg_32_xm0 = EXTRACT_SUBREG %5, %subreg.sub0
     64 # CHECK: %7:sreg_32_xm0 = EXTRACT_SUBREG %5, %subreg.sub1
     65 # CHECK: S_NOP 0, implicit %5
     66 # CHECK: S_NOP 0, implicit %6
     67 # CHECK: S_NOP 0, implicit undef %7
     68 
     69 # CHECK: %8:sreg_64 = IMPLICIT_DEF
     70 # CHECK: %9:sreg_32_xm0 = EXTRACT_SUBREG undef %8, %subreg.sub1
     71 # CHECK: S_NOP 0, implicit undef %9
     72 
     73 # CHECK: %10:sreg_128 = EXTRACT_SUBREG undef %0, %subreg.sub2_sub3
     74 # CHECK: S_NOP 0, implicit undef %10
     75 name: test1
     76 registers:
     77   - { id: 0, class: sreg_128 }
     78   - { id: 1, class: sreg_128 }
     79   - { id: 2, class: sreg_64 }
     80   - { id: 3, class: sreg_32_xm0 }
     81   - { id: 4, class: sreg_128 }
     82   - { id: 5, class: sreg_64 }
     83   - { id: 6, class: sreg_32_xm0 }
     84   - { id: 7, class: sreg_32_xm0 }
     85   - { id: 8, class: sreg_64 }
     86   - { id: 9, class: sreg_32_xm0 }
     87   - { id: 10, class: sreg_128 }
     88 body: |
     89   bb.0:
     90     %0 = REG_SEQUENCE $sgpr0, %subreg.sub0, $sgpr0, %subreg.sub2
     91     %1 = INSERT_SUBREG %0, $sgpr1, %subreg.sub3
     92     %2 = INSERT_SUBREG %0.sub2_sub3, $sgpr42, %subreg.sub0
     93     S_NOP 0, implicit %1.sub0
     94     S_NOP 0, implicit %1.sub1
     95     S_NOP 0, implicit %1.sub2
     96     S_NOP 0, implicit %1.sub3
     97     S_NOP 0, implicit %2.sub0
     98     S_NOP 0, implicit %2.sub1
     99 
    100     %3 = IMPLICIT_DEF
    101     %4 = INSERT_SUBREG %0, %3, %subreg.sub0
    102     S_NOP 0, implicit %4.sub0
    103     S_NOP 0, implicit %4.sub1
    104     S_NOP 0, implicit %4.sub2
    105     S_NOP 0, implicit %4.sub3
    106 
    107     %5 = EXTRACT_SUBREG %0, %subreg.sub0_sub1
    108     %6 = EXTRACT_SUBREG %5, %subreg.sub0
    109     %7 = EXTRACT_SUBREG %5, %subreg.sub1
    110     S_NOP 0, implicit %5
    111     S_NOP 0, implicit %6
    112     S_NOP 0, implicit %7
    113 
    114     %8 = IMPLICIT_DEF
    115     %9 = EXTRACT_SUBREG %8, %subreg.sub1
    116     S_NOP 0, implicit %9
    117 
    118     %10 = EXTRACT_SUBREG undef %0, %subreg.sub2_sub3
    119     S_NOP 0, implicit %10
    120 ...
    121 ---
    122 # Check used lanes transfer; Includes checking for some special cases like
    123 # undef operands.
    124 # CHECK-LABEL: name: test2
    125 # CHECK: S_NOP 0, implicit-def dead %0
    126 # CHECK: S_NOP 0, implicit-def %1
    127 # CHECK: S_NOP 0, implicit-def %2
    128 # CHECK: %3:sreg_128 = REG_SEQUENCE undef %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2_sub3
    129 # CHECK: S_NOP 0, implicit %3.sub1
    130 # CHECK: S_NOP 0, implicit %3.sub3
    131 
    132 # CHECK: S_NOP 0, implicit-def %4
    133 # CHECK: S_NOP 0, implicit-def dead %5
    134 # CHECK: %6:sreg_64 = REG_SEQUENCE %4, %subreg.sub0, undef %5, %subreg.sub1
    135 # CHECK: S_NOP 0, implicit %6
    136 
    137 # CHECK: S_NOP 0, implicit-def dead %7
    138 # CHECK: S_NOP 0, implicit-def %8
    139 # CHECK: %9:sreg_128 = INSERT_SUBREG undef %7, %8, %subreg.sub2_sub3
    140 # CHECK: S_NOP 0, implicit %9.sub2
    141 
    142 # CHECK: S_NOP 0, implicit-def %10
    143 # CHECK: S_NOP 0, implicit-def dead %11
    144 # CHECK: %12:sreg_128 = INSERT_SUBREG %10, undef %11, %subreg.sub0_sub1
    145 # CHECK: S_NOP 0, implicit %12.sub3
    146 
    147 # CHECK: S_NOP 0, implicit-def %13
    148 # CHECK: S_NOP 0, implicit-def dead %14
    149 # CHECK: %15:sreg_128 = REG_SEQUENCE %13, %subreg.sub0_sub1, undef %14, %subreg.sub2_sub3
    150 # CHECK: %16:sreg_64 = EXTRACT_SUBREG %15, %subreg.sub0_sub1
    151 # CHECK: S_NOP 0, implicit %16.sub1
    152 
    153 name: test2
    154 registers:
    155   - { id: 0, class: sreg_32_xm0 }
    156   - { id: 1, class: sreg_32_xm0 }
    157   - { id: 2, class: sreg_64 }
    158   - { id: 3, class: sreg_128 }
    159   - { id: 4, class: sreg_32_xm0 }
    160   - { id: 5, class: sreg_32_xm0 }
    161   - { id: 6, class: sreg_64 }
    162   - { id: 7, class: sreg_128 }
    163   - { id: 8, class: sreg_64 }
    164   - { id: 9, class: sreg_128 }
    165   - { id: 10, class: sreg_128 }
    166   - { id: 11, class: sreg_64 }
    167   - { id: 12, class: sreg_128 }
    168   - { id: 13, class: sreg_64 }
    169   - { id: 14, class: sreg_64 }
    170   - { id: 15, class: sreg_128 }
    171   - { id: 16, class: sreg_64 }
    172 body: |
    173   bb.0:
    174     S_NOP 0, implicit-def %0
    175     S_NOP 0, implicit-def %1
    176     S_NOP 0, implicit-def %2
    177     %3 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2_sub3
    178     S_NOP 0, implicit %3.sub1
    179     S_NOP 0, implicit %3.sub3
    180 
    181     S_NOP 0, implicit-def %4
    182     S_NOP 0, implicit-def %5
    183     %6 = REG_SEQUENCE %4, %subreg.sub0, undef %5, %subreg.sub1
    184     S_NOP 0, implicit %6
    185 
    186     S_NOP 0, implicit-def %7
    187     S_NOP 0, implicit-def %8
    188     %9 = INSERT_SUBREG %7, %8, %subreg.sub2_sub3
    189     S_NOP 0, implicit %9.sub2
    190 
    191     S_NOP 0, implicit-def %10
    192     S_NOP 0, implicit-def %11
    193     %12 = INSERT_SUBREG %10, %11, %subreg.sub0_sub1
    194     S_NOP 0, implicit %12.sub3
    195 
    196     S_NOP 0, implicit-def %13
    197     S_NOP 0, implicit-def %14
    198     %15 = REG_SEQUENCE %13, %subreg.sub0_sub1, %14, %subreg.sub2_sub3
    199     %16 = EXTRACT_SUBREG %15, %subreg.sub0_sub1
    200     S_NOP 0, implicit %16.sub1
    201 ...
    202 ---
    203 # Check that copies to physregs use all lanes, copies from physregs define all
    204 # lanes. So we should not get a dead/undef flag here.
    205 # CHECK-LABEL: name: test3
    206 # CHECK: S_NOP 0, implicit-def %0
    207 # CHECK: $vcc = COPY %0
    208 # CHECK: %1:sreg_64 = COPY $vcc
    209 # CHECK: S_NOP 0, implicit %1
    210 name: test3
    211 tracksRegLiveness: true
    212 registers:
    213   - { id: 0, class: sreg_64 }
    214   - { id: 1, class: sreg_64 }
    215 body: |
    216   bb.0:
    217     S_NOP 0, implicit-def %0
    218     $vcc = COPY %0
    219 
    220     %1 = COPY $vcc
    221     S_NOP 0, implicit %1
    222 ...
    223 ---
    224 # Check that implicit-def/kill do not count as def/uses.
    225 # CHECK-LABEL: name: test4
    226 # CHECK: S_NOP 0, implicit-def dead %0
    227 # CHECK: KILL undef %0
    228 # CHECK: %1:sreg_64 = IMPLICIT_DEF
    229 # CHECK: S_NOP 0, implicit undef %1
    230 name: test4
    231 tracksRegLiveness: true
    232 registers:
    233   - { id: 0, class: sreg_64 }
    234   - { id: 1, class: sreg_64 }
    235 body: |
    236   bb.0:
    237     S_NOP 0, implicit-def %0
    238     KILL %0
    239 
    240     %1 = IMPLICIT_DEF
    241     S_NOP 0, implicit %1
    242 ...
    243 ---
    244 # Check that unused inputs are marked as undef, even if the vreg itself is
    245 # used.
    246 # CHECK-LABEL: name: test5
    247 # CHECK: S_NOP 0, implicit-def %0
    248 # CHECK: %1:sreg_64 = REG_SEQUENCE undef %0, %subreg.sub0, %0, %subreg.sub1
    249 # CHECK: S_NOP 0, implicit %1.sub1
    250 name: test5
    251 tracksRegLiveness: true
    252 registers:
    253   - { id: 0, class: sreg_32_xm0 }
    254   - { id: 1, class: sreg_64 }
    255 body: |
    256   bb.0:
    257     S_NOP 0, implicit-def %0
    258     %1 = REG_SEQUENCE %0, %subreg.sub0, %0, %subreg.sub1
    259     S_NOP 0, implicit %1.sub1
    260 ...
    261 ---
    262 # Check "optimistic" dataflow fixpoint in phi-loops.
    263 # CHECK-LABEL: name: loop0
    264 # CHECK: bb.0:
    265 # CHECK: S_NOP 0, implicit-def %0
    266 # CHECK: S_NOP 0, implicit-def dead %1
    267 # CHECK: S_NOP 0, implicit-def dead %2
    268 # CHECK: %3:sreg_128 = REG_SEQUENCE %0,  %subreg.sub0, undef %1,  %subreg.sub1, undef %2,  %subreg.sub2
    269 
    270 # CHECK: bb.1:
    271 # CHECK: %4:sreg_128 = PHI %3, %bb.0, %5, %bb.1
    272 
    273 # CHECK: bb.2:
    274 # CHECK:   S_NOP 0, implicit %4.sub0
    275 # CHECK:   S_NOP 0, implicit undef %4.sub3
    276 name: loop0
    277 tracksRegLiveness: true
    278 registers:
    279   - { id: 0, class: sreg_32_xm0 }
    280   - { id: 1, class: sreg_32_xm0 }
    281   - { id: 2, class: sreg_32_xm0 }
    282   - { id: 3, class: sreg_128 }
    283   - { id: 4, class: sreg_128 }
    284   - { id: 5, class: sreg_128 }
    285 body: |
    286   bb.0:
    287     S_NOP 0, implicit-def %0
    288     S_NOP 0, implicit-def %1
    289     S_NOP 0, implicit-def %2
    290     %3 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2
    291     S_BRANCH %bb.1
    292 
    293   bb.1:
    294     %4 = PHI %3, %bb.0, %5, %bb.1
    295 
    296     ; let's swiffle some lanes around for fun...
    297     %5 = REG_SEQUENCE %4.sub0, %subreg.sub0, %4.sub2, %subreg.sub1, %4.sub1, %subreg.sub2, %4.sub3, %subreg.sub3
    298 
    299     S_CBRANCH_VCCNZ %bb.1, implicit undef $vcc
    300     S_BRANCH %bb.2
    301 
    302   bb.2:
    303     S_NOP 0, implicit %4.sub0
    304     S_NOP 0, implicit %4.sub3
    305 ...
    306 ---
    307 # Check a loop that needs to be traversed multiple times to reach the fixpoint
    308 # for the used lanes. The example reads sub3 lane at the end, however with each
    309 # loop iteration we should get 1 more lane marked as we cycles the sublanes
    310 # along. Sublanes sub0, sub1 and sub3 are rotate in the loop so only sub2
    311 # should be dead.
    312 # CHECK-LABEL: name: loop1
    313 # CHECK: bb.0:
    314 # CHECK: S_NOP 0, implicit-def %0
    315 # CHECK: S_NOP 0, implicit-def %1
    316 # CHECK: S_NOP 0, implicit-def dead %2
    317 # CHECK: S_NOP 0, implicit-def %3
    318 # CHECK: %4:sreg_128 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, undef %2, %subreg.sub2, %3, %subreg.sub3
    319 
    320 # CHECK: bb.1:
    321 # CHECK: %5:sreg_128 = PHI %4, %bb.0, %6, %bb.1
    322 
    323 # CHECK: %6:sreg_128 = REG_SEQUENCE %5.sub1, %subreg.sub0, %5.sub3, %subreg.sub1, undef %5.sub2, %subreg.sub2, %5.sub0, %subreg.sub3
    324 
    325 # CHECK: bb.2:
    326 # CHECK:   S_NOP 0, implicit %6.sub3
    327 name: loop1
    328 tracksRegLiveness: true
    329 registers:
    330   - { id: 0, class: sreg_32_xm0 }
    331   - { id: 1, class: sreg_32_xm0 }
    332   - { id: 2, class: sreg_32_xm0 }
    333   - { id: 3, class: sreg_32_xm0 }
    334   - { id: 4, class: sreg_128 }
    335   - { id: 5, class: sreg_128 }
    336   - { id: 6, class: sreg_128 }
    337 body: |
    338   bb.0:
    339     S_NOP 0, implicit-def %0
    340     S_NOP 0, implicit-def %1
    341     S_NOP 0, implicit-def dead %2
    342     S_NOP 0, implicit-def %3
    343     %4 = REG_SEQUENCE %0, %subreg.sub0, %1, %subreg.sub1, %2, %subreg.sub2, %3, %subreg.sub3
    344     S_BRANCH %bb.1
    345 
    346   bb.1:
    347     %5 = PHI %4, %bb.0, %6, %bb.1
    348 
    349     ; rotate lanes, but skip sub2 lane...
    350     %6 = REG_SEQUENCE %5.sub1, %subreg.sub0, %5.sub3, %subreg.sub1, %5.sub2, %subreg.sub2, %5.sub0, %subreg.sub3
    351 
    352     S_CBRANCH_VCCNZ %bb.1, implicit undef $vcc
    353     S_BRANCH %bb.2
    354 
    355   bb.2:
    356     S_NOP 0, implicit %6.sub3
    357 ...
    358 ---
    359 # Similar to loop1 test, but check for fixpoint of defined lanes.
    360 # Lanes are rotate between sub0, sub2, sub3 so only sub1 should be dead/undef.
    361 # CHECK-LABEL: name: loop2
    362 # CHECK: bb.0:
    363 # CHECK: S_NOP 0, implicit-def %0
    364 # CHECK: %1:sreg_128 = REG_SEQUENCE %0, %subreg.sub0
    365 
    366 # CHECK: bb.1:
    367 # CHECK: %2:sreg_128 = PHI %1, %bb.0, %3, %bb.1
    368 
    369 # CHECK: %3:sreg_128 = REG_SEQUENCE %2.sub3, %subreg.sub0, undef %2.sub1, %subreg.sub1, %2.sub0, %subreg.sub2, %2.sub2, %subreg.sub3
    370 
    371 # CHECK: bb.2:
    372 # CHECK:   S_NOP 0, implicit %2.sub0
    373 # CHECK:   S_NOP 0, implicit undef %2.sub1
    374 # CHECK:   S_NOP 0, implicit %2.sub2
    375 # CHECK:   S_NOP 0, implicit %2.sub3
    376 name: loop2
    377 tracksRegLiveness: true
    378 registers:
    379   - { id: 0, class: sreg_32_xm0 }
    380   - { id: 1, class: sreg_128 }
    381   - { id: 2, class: sreg_128 }
    382   - { id: 3, class: sreg_128 }
    383 body: |
    384   bb.0:
    385     S_NOP 0, implicit-def %0
    386     %1 = REG_SEQUENCE %0, %subreg.sub0
    387     S_BRANCH %bb.1
    388 
    389   bb.1:
    390     %2 = PHI %1, %bb.0, %3, %bb.1
    391 
    392     ; rotate subreg lanes, skipping sub1
    393     %3 = REG_SEQUENCE %2.sub3, %subreg.sub0, %2.sub1, %subreg.sub1, %2.sub0, %subreg.sub2, %2.sub2, %subreg.sub3
    394 
    395     S_CBRANCH_VCCNZ %bb.1, implicit undef $vcc
    396     S_BRANCH %bb.2
    397 
    398   bb.2:
    399     S_NOP 0, implicit %2.sub0
    400     S_NOP 0, implicit undef %2.sub1
    401     S_NOP 0, implicit %2.sub2
    402     S_NOP 0, implicit %2.sub3
    403 ...
    404