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

    <tr>
        <th>Summary</th>
        <td>
            Assertion "Invalid SubReg for physical register" failed - Broken subreg SubRegIdxLists?
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            tablegen,
            regalloc
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
            arsenm,
            perlfu,
            uweigand,
            JonPsson
      </td>
    </tr>

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

<pre>
    llc -mtriple=s390x-linux-gnu -mcpu=z15 -O3 -o out.s -start-before=simple-register-coalescing ./tc_VR128_HH32.mir
[testcase.tar.gz](https://github.com/llvm/llvm-project/files/10961530/testcase.tar.gz)

This test case starts out with separate fp32 / fp64 and vr128 bit regs:

```
%10:fp32bit = nofpexcept WFDSB killed %9:fp32bit, killed %8:fp32bit, implicit $fpc
undef %11.subreg_h32:fp64bit = COPY %10:fp32bit
%13:fp64bit = COPY killed %11:fp64bit
%13:fp64bit = nofpexcept MDEBR %13:fp64bit(tied-def 0), killed %10:fp32bit, implicit $fpc
undef %16.subreg_h64:vr128bit = COPY killed %13:fp64bit
%20:vr128bit = VPDI %16:vr128bit, killed %18:vr128bit, 0
```

The RegCoalescer produces a register def with the hh32 subreg:

```
288B      undef %16.subreg_hh32:vf128bit = nofpexcept WFDSB %9:fp32bit, %8:fp32bit, implicit $fpc
400B      %20:vr128bit = VPDI %16:vf128bit, %18:vr128bit, 0
```

On SystemZ, a VR128 reg has a "high" subreg FP64, which in turn has a "high" subreg FP32. So the FP32 subreg of VR128 has the HH32 subreg index.

This assertion fails:

`VirtRegMap.cpp:603: void {anonymous}::VirtRegRewriter::rewrite(): Assertion `PhysReg.isValid() && "Invalid SubReg for physical register"' failed.`

PhysReg = TRI->getSubReg(PhysReg, SubReg);

was called, where PhysReg is SystemZ::V1 (%16 above), and Subreg is SystemZ::subreg_hh32, as expected.

I suspect that the SubRegIdxLists is broken:

SubRegIndices for V1 is 0, meaning that *SRI is set to the first SubRegIndices list in MCRegisterInfo::getSubReg():

```
extern const uint16_t SystemZSubRegIdxLists[] = {
  /* 0 */ 2, 1, 0,
  /* 3 */ 5, 1, 0,
  /* 6 */ 6, 1, 2, 3, 0,
  /* 11 */ 6, 5, 1, 2, 4, 3, 0,
};
```

The subreg-indices here are 2, 1, which are h64 and h32, per the generated table:

```
enum : uint16_t {
 NoSubRegister,
  subreg_h32,   // 1
  subreg_h64,   // 2
 subreg_hh32,  // 3
  subreg_hl32,  // 4
  subreg_l32,   // 5
 subreg_l64,   // 6
  NUM_TARGET_SUBREGS
};
```

The subregs retrieved with MCSubRegIterator is F1D and F1S, which are the correct registers.

However, the h32 subreg index should actually be hh32 (3 above). This is the subreg index that the coalescer came up with (I suppose through composeSubRegIndices(), but it is not found in this list, so NoRegister is returned, and then the assert triggers.

Since the right subreg index is produced by the coalescer, it seems this should then also work with getSubReg(). I guess either something is missing in the SystemZ .td file, or there is a bug somewhere?

(This is a rare case which I ran into only recently during other experiments).

</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyUV1tv2zgW_jXMy4ENibQV-8EPdlxPs9i0gd3JYvcloKQjiVuZFEgql_n1g0NJjq2mmbYokojn_p0bKZ1TpUZcsfmGcS6tQ31knDN-wzhv0NZFe_psn1GVUueng38Zfe-c0XQw317J1lfGrobTq9Tkr6u6zmBy9FY1NTKxdWIZvUxqpduXSalbmByzpmVi-1c8h8lXARMDpvVTBxPnpfWTFAtjg6A6NjVOLJbKebSTzMgaXaZ0CVPGdz57fNjHfPH4-bPg06OyLNqyaM3mG4_OZ9Lh1Es7Lf9i8y3ji8r7xjGxZnzH-K5UvmrTaWaOjO_q-mn4NWms-T9mnvFdoWp0jO_iaJnEcxGRyZFivuxthp_fKuWAWIB4IETjKDZ4Vr4Ch4200iMUjeDA-A6KJpmB1Dk82ZgvIFUeLJbByTO1LIn6_90nn8cRE2vSQhJMbEGbosGXDBsP_9ltDxv4ruoac2B8vnxjZfzmjLC4JBDWKiN9fFY0WWer1TkWxBzHU9emFsvHSvAgmMwG4zdf7_8LI6_eXBXvcb95Ecdv9J8LncV3t_202cOIifGFV5hPyNuIsnIR6YVj_xxqcgo1mTGxDrn5mffiHe95NJZ6uN_edqrPKCMfFyNS9H7y-0JD2GN50_UDWmisydsMHUgYugUonFB3vkKoKsGhC-vj6uKLxQbCv_cA6ZL_VJzF9kPp_Vhzv1hssyjqTf8CiMUbUr-L3lcNh1fn8fg_4pQQhgjhBpUkBBnnlSorxgfEYHefzIj3uVJZBUqDb63-gFvwKRxMAJ4-BoIpelskSUQaXANR6Rxfpj-ME-kcWq-MhkKq-p3R8KCs32N5J5tp1jRMrJOIihKejMqBXW-kNvr1aFrHrrckLda9xB6frfJou0PbfTG-oPYRa1ifDLMkuq9e3R7LqXIPslZ5xwWMJ4wnhMCtfqJzOLTpHksojIWmenUqk_WpIMMKuQ5hYD4d5aQ3EBL9bX87YeJTib5Tx_iiJ1MOhrMlE5tzDc_SQSapnbpMoUUYtCp3yniHQAwhhHmcgEzNE_Yjg0bxoU_HSOS8A4jTAb40mHkK5cyLW3Cto3PwlfQhyZ3Dt_nLv5XzjhSn1nxHPUplz6ZzRX1MCD7ExByRuSNKTWsvKGV8fdjfEs2hB9_VWaGs83CppFbOU7Xe3ez7HNzqwnTxnKPbZfyDoYAvHq2GzGjnoVXax8mjH_C5jI8uFfNtyCO77hNEDb1jfA0R-U6LL2AYd43Kb0ZcYuCaf8SVDFzJiStoFT_hj-MLgfml1Owd0dAwm38Yw11dTFQPeSg7afEswm5o0FnVb_u-hhq0IXUlaqR7QQ5epnRj-jAVuj0C9ecpDW8wfzFdLvp2OyFwtrn5DfSI7CAe07shd6Lznj4q_YEsxuL1JX02otcj8_NL9fXIejKIf_nz7vHbev_Hp2-Phz83-09_HH47PQ4seqvwCfNuJd7d9FXrCXljqZl28TZkZxcfLtNGOcqMtdTVwzBzF13_2TzjU4C8W7ajqQ6uMm2dg8x8K-v6FdJ-ITO-EKcBNIUw8FW3Gi7kT7MkO238TB4R2qYLh_EFDZ6mMY7ctaYtK8jMkb4vRkLf7PwG0taD8mRNGw-FaXUeFhu5QHODeJyBL2aoJ2K1SIuvm7AEla9QB7-6LQXeqrIcg3NQOutAtKqs_GVkyg13lxzS18sYw0XBg0M8us6xHsdgVtbOwLOx3zsIRvNsCrdQtugcoPIVWnDmiL6iGaocHJVz4c_O-36QwdTnQJd-MmxCb1okdglpWwYNYa0wsbtoUL4YEifBUsGE239XP7dgpQalvQGj61ewmKH29SvkrSUPTHCOVolVR9Teke-d3qt8JfKlWMorXMXJ9eJaLPlsdlWtRLaIheSCX88XnF8XM5kU-bKI51hkScrjK7XiEReRiAWP-DWfTWPJl0uZ5vNkKfI4XbBZhEep6im9eKbGllfKuRZXSSyW0VUtU6xd_zwMI6lEfXoAWixlXZusfwDaVXg1pW3p2CyiynFvWr3yNa7ObhK_fFPorwkwgU1YlkPVjJaN2F21tl799tMuhEtvuxDx3wEAAP__YcKBNg">