<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/82030>82030</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            [AMDGPU] LiveVariables incorrectly marks `$vcc_lo` dead
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            new issue
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          dmpots
      </td>
    </tr>
</table>

<pre>
    I am running into a miscompile when compiling for wave32. The compiler is generating a S_CBRANCH_VCCZ instruction but deleting the def of `$vcc_lo` that controls the branch.

I was able to track down the problem to the LiveVariables pass. It marks the def of `$vcc_lo` dead and then the "Post-RA pseudo instruction expansion pass" converts that copy to a kill (which produces no output in the final codegen).

I am able to reproduce the issue with a simple example below.

## Repro
```
# llc %s -o - -mtriple=amdgcn -mcpu=gfx1010 -mattr="+wavefrontsize32,-wavefrontsize64" -verify-machineinstrs -run-pass=livevars 
---
name: test
tracksRegLiveness: true
body: |
  bb.0:
    liveins: $sgpr1
    %0:sreg_32 = S_AND_B32 $sgpr1, $sgpr1, implicit-def $scc
    $vcc_lo = COPY %0:sreg_32
 S_CBRANCH_VCCNZ %bb.1, implicit $vcc
  bb.1:
    S_ENDPGM 0
...

```

Running this MIR file through llc results in the COPY instruction being marked dead.

`dead $vcc_lo = COPY killed %0`


## Details

This looks to be a problem with how we mark `$VCC` and `$VCC_HI` as reserved registers when compiling for wave32. For wave32 the explicit `$vcc` uses are converted to `$vcc_lo`, but the implicit uses are left as `$vcc`. So we have an explicit def of `$vcc_lo` in a copy instruction, and an implicit use of `$vcc` on the `S_CBRANCH_VCCNZ` instruction.

The live variables pass skips reserved registers when processing an instruction uses (and defs)

```
  // Process all uses.
  for (unsigned MOReg : UseRegs) {
    if (Register::isVirtualRegister(MOReg))
      HandleVirtRegUse(MOReg, MBB, MI);
    else if (!MRI->isReserved(MOReg))
 HandlePhysRegUse(MOReg, MI);
 }
```
https://github.com/llvm/llvm-project/blob/a4ce870859a2d8b5ce8b92732594089e2a81b4fb/llvm/lib/CodeGen/LiveVariables.cpp#L526

This means it thinks the `$vcc_lo` def has no uses and therefore can mark it as dead.


## Possible Fixes

I can think of a few different ways to solve this problem.

### Do not reserve VCC and VCC_HI in wave32

It looks like vcc_hi and vcc were only reserved to avoid possible bugs. I tried un-reserving them and inspecting codegen diffs. I did not see anything too troubling. It was allocating vcc_hi in the shaders now, but I think that should be ok.

```
  // Disallow vcc_hi allocation in wave32. It may be allocated but most likely
  // will result in bugs.
  if (isWave32) {
    Reserved.set(AMDGPU::VCC);
 Reserved.set(AMDGPU::VCC_HI);
 }
```

https://github.com/llvm/llvm-project/blob/2d9f3504491156282a3c785a562fcc0ba3c16161/llvm/lib/Target/AMDGPU/SIRegisterInfo.cpp#L614C1-L619C4

I was wary of this solution because of the unknown risk and the details about why it was reserved in the first place.

### Add VCC_LO and VCC_HI as implicit uses to branch instructions

We currently only add VCC as an implicit use to these branch instructions. We could add the VCC_LO and VCC_HI to the implicit uses as well. Or perhaps have different branch instructions for wave32 (similar to how we do for the `savexec` terminators).

```
let Uses = [VCC] in {
defm S_CBRANCH_VCCZ : SOPP_With_Relaxation <
  "s_cbranch_vccz" , (ins SOPPBrTarget:$simm16),
  "$simm16"
>;
defm S_CBRANCH_VCCNZ : SOPP_With_Relaxation <
  "s_cbranch_vccnz" , (ins SOPPBrTarget:$simm16),
  "$simm16"
>;
} // End Uses = [VCC]
```
https://github.com/llvm/llvm-project/blob/cc673867d97aeb1151da5f7f0dc59d47eb384b45/llvm/lib/Target/AMDGPU/SOPInstructions.td#L1509C1-L1518C22

Making this change caused a lot of test failures for invalid MIR, but seemed pretty mechanical to fix it up.

### Make LiveVariables handle reserved register with unreserved subregister

We could add code to process reserved registers by looking for unreserved subregisters.

```
+/// Process a use of a reserved physical register.
+void LiveVariables::HandleReservedPhysRegUse(unsigned Reg, MachineInstr &MI)
+{
+  assert(MRI->isReserved(Reg) && TRI->isPhysicalRegister(Reg));
+  for (MCSubRegIterator SubRegs(Reg, TRI, /*IncludeSelf=*/false);
+       SubRegs.isValid(); ++SubRegs) {
+ unsigned SubReg = *SubRegs;
+    if (!MRI->isReserved(SubReg))
+ HandlePhysRegUse(SubReg, MI);
+  }
+}
```

And then update live variables to explicitly do more work for reserved registers.
```
 void LiveVariables::runOnInstr(MachineInstr &MI,
 SmallVectorImpl<unsigned> &Defs) {
 assert(!MI.isDebugInstr());
@@ -545,6 +603,8 @@ void LiveVariables::runOnInstr(MachineInstr &MI,
       HandleVirtRegUse(MOReg, MBB, MI);
     else if (!MRI->isReserved(MOReg))
 HandlePhysRegUse(MOReg, MI);
+    else
+ HandleReservedPhysRegUse(MOReg, MI);
   }
```

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy0WF9v4zgO_zTuC5HAlvP3oQ9tMt0NMJ0W6WwXty-FbNOxrrJkSHLS7Kc_ULLTJE2LvdvbwaBJLIqkKP5-JM2tFRuFeB2Nb6Px8oq3rtLmuqgb7exVpov99Qp4DaZVSqgNCOU0cKiFzXXdCImwq1BB-EECpTaw41tM2RB-VtitoAFhYYMKDXckxuHpZXG7vvmx-PXlebH4A4SyzrS5E1pB1jooUKKXdBVCgSXoEqJJHLHRNs9fpI4mMbiKO8i1ckZL6wUzw1VeDaN4GcU34e8KdtwCzySC0-AMz1-h0Dvl5RujM4m1X6kQvostPnMjSNpCw60dwspBzc2r_cqRAnkBXBUkExRHjD1q6wbrG2gstoU-OSC-NVxZ-kY2IsboFFs0zvZnavbgA_0qpISIzXaVyCtyt2hztKA06NY1rQMR7JVCcQm5LnCDKmLzsxDw-hABg50Wv09Y2yLshKuAgxV1IxHwjfvPDKXenSiKWBqxFNakonsyibv_vQBImUPExhYGGgYwqJ0RjcQoXfK62OQKBnXetFG63JRvSZzEMKi5cyZKlxFjEbul5CmNVs6KPzFlEVsMTh5NRhSvwRaNKPeDmueVUOiDa2FgWjXwIU2XUmxxy42F4NlgMAhfFK8xSm_AoXXhic8Ju8YNXb9C2n0DzrQYlgkE9CSaLsIDgCwbxlF60_8EIGNC-Y0RG9lNY5L3xYiNSdoa3LykDKJ0CU8vNz-WL7f0qxdni5PvdBUiF25AKUcLeX6ssUs-r2zx8PivMyOd6AnGfvxBQlk2PNHf6To6WXJysqeXbz-Wj7_cQ3fDw-FpRpzdv_-77sjCVcLC_WoNJRGFq4xuN5XPD4O2lc722etPcMIASPsJd1h4dJ0b9Yi7EAbCCxYhGqdOnWTwEh0X0h6v_CRnpdaEdA0ZAj-wg4dHpXewQ-9Th__nxYLAT7g_PHj5deWfWToimi0WYHAjrENjv6LKu8N3HxB862-nZxrS2lq0wA32bIEFuXpGRnS5RKAe3f0lH3ZKLB15d6x3CE-ajlbxLQJX78Y_YTuhgAeKOroyMkuR4OrE6sl-2qw7fpzEZ8kZNB_0DU_vBj3EYHtCzmBfRfN5pBujc7TWlxt1kl4-HBGbkcMFljZi8y-SmvB2F7E7eAwKgUvpVQz7dbrJiM1a5YtpAfcPa9wAscFvFte4IQMQTW_fYSUI1LN15zAhLr0R9lkY13J5eMxmXhO513sI_t-vXBUSSXyNm98svksu4P721n-saE96ZBOlxc5wxJL79WoQpd-EXXfhu2gtGHqs9vaCoVML0XR5MXyVcw0xYwjiRriqzYa5riN2J-W2_xg0Rv8bcxexu0zqLGJ3fJTjbBrPxnPOilk2znGWzdk0ZeP5KJ7NkfFZko3K7EiPoB8LXeAvVATvTsr5MG-aiKXfx2zyAfY1cmVBEGiE6kr9xxpfQsV96Q1oCuXeYKkJkVwFahAeXh8p65h9HrW1gsrxnXhDe1qpSZH3gpDDocQdFKIs0aBysON7z05Wyy0Geu046kKZ9jynQWnXIwSeFwGkgagIyIFzTlxwHQtK8YpA56-E37TNc9ihQdBK7t9BR23KVosCmv5UWbuhvgmcEVhAqwZBtmvmaq9MKNtg7hu8rmnxx_T7ClF4ry0SHe0pGhtwmpo33WZEnb4r822dlDoPHWXnaVdRbMULIgKldz0hrrq4-g7LVrqVBdG8fv2qoB2wvxSWjO0OEeksa_Uexq5Z3PvqEdax8LZrbZ0PqNyf6d1RgxfKISnysetFAlaF_T1c0jmH9MAdWnQRm93cL395_C1QCZWmY2x-LUpF668g-e_hmRXzMh3Ho9E8ScYTNmM8zaezMR9PWJnnccbTPJkkk-Qczz-52ZDXd53X7O5p1TPkSpW6B_YkGS2SwfdJMl-MPg4AO272BCkPGqtl2_UZOe-qFGVNq14VjQZG2Nce4FCEXgF4plsHu2pPGN8dV_hDD26sg0byHD-B400RsPf94RiG3J4Vauo__CBzXLROeOJ3hLw1xAlyH_DIg2pSdl6Cw3Bj8ZLSIZAqjwXSQMf46GA3HZ11ExZ2KOUQHgw0aCre2NBBvNPVBXtHTQ_lthW1kNyQha6_KrQX6RjY8i2-oW8cHJpaKO60sefzzVmaSnRUd63vCqPxLYFhvKRbOsCnwLI-n0CpXD89PD6-_C5c9bJGyd8CvqN08Q5aZl_ycK6XbZ7_SbNIaN1nQlm__9Z0GUsQGVlR18nE19RjLUcrPfum3w4I_Ojej__NP_UPORhNlz2BfVPFhWj_XzuBPJ9M09lkWsynHLMkGScFH5fTMi7y8bwYTTFLZ6NsNP4LzPHwuDrOflcQcyTjeE7UkYyT2YKdVMN7_nqYZPKKqw2V-tZiARykdp440DoouZCtwZDfQm25FAWNPn3xsYg1FtAYdG4PNZIukXNJmV-KN6KUtvmENe756_mricq3ZR873zCqtOqwYNusXzvnjwPoqQCTH12_fKmfzva-KeinlssG7JeTIbsN137SSPcjAn832lR76yPTqx0eFPg24yQQoYSFJrWvcSfN6qEl73vW8L7AJwFEbBJ62IOHPT9E7BaAW4uGyuWlVjk0yqQiYhP42Us8dt4ftfDvLXV6rL2bGe4XT222xs3KoSFyg_DT9hsXpDsA-C5iNyuVy7bAJ5Slf2NCWCq5pLOe6ff_OmVDYZ8pI33nT3Lgr-P2YOuos6DNh6gFgQBtdtOLn9n5cqQIe45nCtp1YazoBc_nCm_kvSOhS_qqO7np38K1TcHdh7HR6cN4K_dUbGrq3nfavPoL-Zj6w8tt4WepaFr1oHx20d1eSLaeY59qLuUz5k6bVd3IKF30QY_SbyS8DHPpUct3yEcK9Woo7BKzdtMbO8-xURyNYhiMiRYXE7rwSZxGbDGDbulvH-FvjKL_8CzaJSYZOc-5iyzx2UgLn7bCV8V1WszTOb_C62Qaz5IknqbpVXWd53GSJknOZvPRJGNZOcdpPmasHM9HCZ9Pr8Q1i9koZskkmScsSYezIkvKybScTmfxBBO6G6y5kEOqZUNtNlf-Je31jMVpfCV5htL61_WMKdyFN7hUpMfLK3PtCygNEdEolsI6-67FCSf9e_6uGo6XZ0VFqFwbgzkhI7zyvvSe-6o18vq_ruTeSxuxO3-K_wQAAP__DOh_OQ">