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