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 28name: test0 29isSSA: true 30registers: 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 } 37body: | 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 86name: test1 87isSSA: true 88registers: 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 } 100body: | 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 165name: test2 166isSSA: true 167registers: 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 } 185body: | 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 223name: test3 224isSSA: true 225tracksRegLiveness: true 226registers: 227 - { id: 0, class: sreg_64 } 228 - { id: 1, class: sreg_64 } 229body: | 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 244name: test4 245isSSA: true 246tracksRegLiveness: true 247registers: 248 - { id: 0, class: sreg_64 } 249 - { id: 1, class: sreg_64 } 250body: | 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 265name: test5 266isSSA: true 267tracksRegLiveness: true 268registers: 269 - { id: 0, class: sreg_32 } 270 - { id: 1, class: sreg_64 } 271body: | 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 292name: loop0 293isSSA: true 294tracksRegLiveness: true 295registers: 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 } 302body: | 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 346name: loop1 347isSSA: true 348tracksRegLiveness: true 349registers: 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 } 357body: | 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 398name: loop2 399isSSA: true 400tracksRegLiveness: true 401registers: 402 - { id: 0, class: sreg_32 } 403 - { id: 1, class: sreg_128 } 404 - { id: 2, class: sreg_128 } 405 - { id: 3, class: sreg_128 } 406body: | 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