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