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

    <tr>
        <th>Summary</th>
        <td>
            [RISCV] Regsiter copies in a loop should be eliminated
        </td>
    </tr>

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

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

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

<pre>
    The following happens in gcc benchmark:

For this code in gcc benchmark:

```
typedef struct simple_bitmap_def
{
  unsigned char *popcount;
  unsigned int n_bits;
  unsigned int size;
  unsigned long elms[1];
} *sbitmap;
typedef const struct simple_bitmap_def *const_sbitmap;

typedef unsigned long *sbitmap_ptr;
typedef const unsigned long *const_sbitmap_ptr;
static unsigned long sbitmap_elt_popcount (unsigned long);

void
sbitmap_a_or_b (sbitmap dst, const_sbitmap a, const_sbitmap b)
{
  unsigned int i, n = dst->size;
  sbitmap_ptr dstp = dst->elms;
  const_sbitmap_ptr ap = a->elms;
  const_sbitmap_ptr bp = b->elms;
  unsigned char has_popcount = dst->popcount != ((void *) 0);

  for (i = 0; i < n; i++)
 {
      const unsigned long tmp = *ap++ | *bp++;
      *dstp++ = tmp;
    }
}
```

We get copies in the loop body:

```
  ld  a4, 0(a3)
  ld  a5, 0(a2) 
  addi  a1, a3, 8
  addi  a2, a2, 8
  or  a4, a4, a5
  addi  a3, a0, 8
  sd  a4, 0(a0)
  mv  a0, a3
  mv  a3, a1
  bne a1, a6, .LBB0_2

```

Copies are introduced by PHI Elimination. The code before PHI Elimination:

```
bb.2.for.body:
; predecessors: %bb.1, %bb.2
  successors: %bb.3(0x04000000), %bb.2(0x7c000000); %bb.3(3.12%), %bb.2(96.88%)

  %5:gpr = PHI %3:gpr, %bb.1, %10:gpr, %bb.2
  %6:gpr = PHI %1:gpr, %bb.1, %9:gpr, %bb.2
  %7:gpr = PHI %2:gpr, %bb.1, %8:gpr, %bb.2
  %8:gpr = ADDI %7:gpr, 8
  %16:gpr = LD killed %7:gpr, 0 :: (load (s64) from %ir.ap.014, !tbaa !15)
  %9:gpr = nuw ADDI %6:gpr, 8
  %17:gpr = LD killed %6:gpr, 0 :: (load (s64) from %ir.bp.015, !tbaa !15)
  %18:gpr = OR killed %17:gpr, killed %16:gpr
 %10:gpr = nuw ADDI %5:gpr, 8
  SD killed %18:gpr, killed %5:gpr, 0 :: (store (s64) into %ir.dstp.016, !tbaa !15)
  BNE %8:gpr, %4:gpr, %bb.2
 PseudoBR %bb.3
```

Note that `SD killed %18:gpr, killed %5:gpr, 0 :: (store (s64) into %ir.dstp.016, !tbaa !15)` is using the value of induction variable `%5` which is updated in `%10:gpr = nuw ADDI %5:gpr, 8`. 

However, it is legal to move the store before the add. Similar situations is with other copies.
Possible solutions:

(1) Have some scheduling pass before PHI elimination. Right after non-global `ISel` we have a scheduling, where target can choose a  custom scheduler via `ST.getDAGScheduler`. None of the existing targets use this and, as I understand, this code will be replaced by something else soon? Also, these schedulers are bottom-up, while this situation is best handled in top-down I think. 
Another possibility is to add a top-down scheduler somewhere before PHI Elimination?

(2) Do this reordering in some other existing non-scheduler pass? Maybe as a first step of PHI elimination? We'll have to reproduce some of the scheduler's logic though which doesn't seem right.

(3) Something else?

What do you think?

CC:
@topperc @preames @asb @wangpc-pp 
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJy8WF9z4jgS_zTKS1dctowxPPAAYXKTqr25qcnWzWNKthpbN7LlkmTY3Ke_atmAgZDde1kqZYz6369_3WrZEc6pqkVcsWzDsu2D6H1t7Kqpeqmah8LI99XvNcLOaG0Oqq2gFl2HrQPVQlWWUGBb1o2wv1i6ZvGWxeP12VjwtXJQGol_pszm8fgXfvr3DiXuwHnblx6cajqNb4XyjejeJO5Go3wz3AD0bUhCQlkLC4yvO9OVpm89S291VOuhJW_untSp_-JHMm3aClA3jmWbhGXbkw7LtxTVDRBPy8c8StM6fzcbsgwab9f2l14uYZzDvXXe3gl5Y3IR58LQeeFVeWVxVETt346UAuOLCy3Gl1eI90bJ0evoQLwZ-1aQ6bgC0nnGn-ACEIjbpYLc3603VUuRUQss3ZLTR5Z-uarfJF3S6KaqoZpn1Rt-QAzq4i8pF4Ny8YHyZYvWwk0IPcOZkJzQMuMLxhfEJ1WP8SXEt3QD7Ax1_UIFVzFLN0C3T9CGW8Y34W_kESZE0uejVvHNkAnja9EN9sDyJ_pdjL8nudGH8TVxe9RNt-TjQofl29Nu-XDbD9efCBV6KE2nMEwZXyNoYzqgYfT54ADQEkDMqCNixhciPWc9iLKTiBObR5mQUgGIhKRk9ASLKxEPIn4hMvYYbLxmV0bBk4gvjNwlwniCsNnDqC3Si7XBT3JcK1o8Yp3TNfpts4nf-CfEDNengVNhaSB7a2RfooTiHb5_fYEvWjWqFV6ZNgIa-WFwF7gzFq8VPq9CUUQ82hkbXRYs3UBnUWKJzhnrWLoGxrOiiEImwy0_sdSXN3op44v4j3gWhw_xNrEjUV6eRelmYpVGCWc8uzFZzqPFYhRcbCjGs4yl66qzoZUpfcazdFg6-zgiT-JrCZ94mt96Su55Wn7mKL91xO85WnzmaDFxtN5uXybOL3qVkE7R_7aFX0prlFcGMVCZQ6EW2ggZBv18RjtsZ01D2spGooviZDYgSnwhBH0n2WQDnAkI4dr-cII3vwMvvwdv_v_CKwhe9ifwkil1__oxiZdM-JisHmGMo_fcKzcZZh9k-DrNKFl8FCH7OE_nad-eE1WtN2OiNKejOJl_lurm25fbLprd66nvDntpNj9OW-7-DPpmPIKvhQc2j__-9OYxKAe9oydZOlj2QvcIZgeqlX1Jsw32wipRaCSAAcA8hkOtyjpYdlL48OAxiv9aOedxBFMWvpoD7jEIlSe_GiuhwRtozB4DsiHDcf7SgpAyglfVKC0sOOX7MIodWR-Ur8H4Gu14bkZDmO_GOUWpOKP7oH09ufkiIfq-ij0pNQiurFH2mvjphHPTAwCnJ8QPVdUexM6jhda0j5U2hdBEyssr6sAZQk1uxcQnJXyokTISNhzzooWyNsaRHpS986Y56qOFvRKhT36PKvTb9T9ej5LA6DfThtoRO_iHcj5UNTimGuPwAiJaGY5KBy_QtxKt8-PS-f3koLSGAsFip8V4KBIdvlbhkd8RO3TuPcNaOzMYo8Mz1OFYLYz3pnnsuyFRpUcMp3JRtQp0HmrRSj00kjfdozSHFl5Iuf11bJV1O5S0C1VUWvl3MveGWgHE2e7MF2Ee-L13cD9flT88Bm3NANOisRIt5azaoR8GCCd2qdTncNQhxMk_xXuBxLCAnbLhXQc7qsxV25DuT2Q813roDW-I8uFJZIw3lPMUg_HcgTaVKsHXpq_qcS9Kg65lPPfgEBuw1I7RVW709AevF2W8IuAnDSJp4N30A_dX8qen84aZxd50HdoS2CzuLIoGHd0KV9DXQbRVVz52HTzIVSqX6VI84CrJk1mczvk8f6hXi91O8izdJfP5MisKjPksl5iXHHdZscvzB7XiMZ_FM57FyySJ82i-lIukXCRpwnmR73I2i7ERSkda75vI2OpBOdfjahnHafqgRYHahTd5zls8QBAyzunF3q7I5rHoK8dmsVbOu7MXr7wO_wL48fL69G-WbeEHVk7500ChfhDDY7irTa8l7ZZjZVE-9Favau-7MGD4M-PPlfJ1X0SlaRh_pkDj12NnzX-w9Iw_B3iO8ecA_38BAAD___c4028">