| # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6 | |
| # RUN: llc -mtriple=amdgpu9.08 -run-pass=si-fold-operands -o - %s | FileCheck %s | |
| # When SIFoldOperands folds a COPY source into a use inside a BUNDLE, it | |
| # must also update the BUNDLE header's matching implicit operand. | |
| # Without it, for example after folding %5.sub1 into the bundle | |
| # | |
| # %8:vgpr_32 = COPY killed %5.sub1:vreg_128 | |
| # BUNDLE implicit killed %8:vgpr_32, ... { | |
| # DS_GWS_INIT %5.sub1:vreg_128, ... | |
| # } | |
| # | |
| # the header still uses %8, so the COPY can't be deleted. Its `killed %5.sub1` | |
| # is now stale and MachineVerifier reports "Using a killed virtual register". | |
| # Updating the header's implicit operand from %8 to %5.sub1 lets the dead-COPY | |
| # cleanup remove the COPY and its stale kill flag. | |
| --- | |
| name: fold_into_bundled_use | |
| tracksRegLiveness: true | |
| body: | | |
| bb.0: | |
| liveins: $vgpr0, $vgpr1, $vgpr2, $vgpr3 | |
| ; CHECK-LABEL: name: fold_into_bundled_use | |
| ; CHECK: liveins: $vgpr0, $vgpr1, $vgpr2, $vgpr3 | |
| ; CHECK-NEXT: {{ $}} | |
| ; CHECK-NEXT: [[COPY:%[0-9]+]]:vgpr_32 = COPY $vgpr0 | |
| ; CHECK-NEXT: [[COPY1:%[0-9]+]]:vgpr_32 = COPY $vgpr1 | |
| ; CHECK-NEXT: [[COPY2:%[0-9]+]]:vgpr_32 = COPY $vgpr2 | |
| ; CHECK-NEXT: [[COPY3:%[0-9]+]]:vgpr_32 = COPY $vgpr3 | |
| ; CHECK-NEXT: [[REG_SEQUENCE:%[0-9]+]]:vreg_128 = REG_SEQUENCE [[COPY]], %subreg.sub0, [[COPY1]], %subreg.sub1, [[COPY2]], %subreg.sub2, [[COPY3]], %subreg.sub3 | |
| ; CHECK-NEXT: $m0 = S_MOV_B32 0 | |
| ; CHECK-NEXT: BUNDLE implicit [[REG_SEQUENCE]].sub0, implicit $m0, implicit $exec :: (store (s32) into custom "GWSResource") { | |
| ; CHECK-NEXT: DS_GWS_INIT [[REG_SEQUENCE]].sub0, 0, implicit $m0, implicit $exec :: (store (s32) into custom "GWSResource") | |
| ; CHECK-NEXT: S_WAITCNT .Vmcnt_0_Expcnt_0_Lgkmcnt_0 | |
| ; CHECK-NEXT: } | |
| ; CHECK-NEXT: BUNDLE implicit [[REG_SEQUENCE]].sub1, implicit $m0, implicit $exec :: (store (s32) into custom "GWSResource") { | |
| ; CHECK-NEXT: DS_GWS_INIT [[REG_SEQUENCE]].sub1, 0, implicit $m0, implicit $exec :: (store (s32) into custom "GWSResource") | |
| ; CHECK-NEXT: S_WAITCNT .Vmcnt_0_Expcnt_0_Lgkmcnt_0 | |
| ; CHECK-NEXT: } | |
| ; CHECK-NEXT: S_ENDPGM 0 | |
| %0:vgpr_32 = COPY $vgpr0 | |
| %1:vgpr_32 = COPY $vgpr1 | |
| %2:vgpr_32 = COPY $vgpr2 | |
| %3:vgpr_32 = COPY $vgpr3 | |
| %4:vreg_128 = REG_SEQUENCE %0:vgpr_32, %subreg.sub0, %1:vgpr_32, %subreg.sub1, %2:vgpr_32, %subreg.sub2, %3:vgpr_32, %subreg.sub3 | |
| %5:vgpr_32 = COPY %4.sub0:vreg_128 | |
| %6:vgpr_32 = COPY %4.sub1:vreg_128 | |
| $m0 = S_MOV_B32 0 | |
| BUNDLE implicit %5:vgpr_32, implicit $m0, implicit $exec :: (store (s32) into custom "GWSResource") { | |
| DS_GWS_INIT %5:vgpr_32, 0, implicit $m0, implicit $exec :: (store (s32) into custom "GWSResource") | |
| S_WAITCNT 0 | |
| } | |
| BUNDLE implicit %6:vgpr_32, implicit $m0, implicit $exec :: (store (s32) into custom "GWSResource") { | |
| DS_GWS_INIT %6:vgpr_32, 0, implicit $m0, implicit $exec :: (store (s32) into custom "GWSResource") | |
| S_WAITCNT 0 | |
| } | |
| S_ENDPGM 0 | |
| ... |