<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/69586>69586</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Poor RV64 codegen for a sequence of additions with compile-time constants
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
michalt
</td>
</tr>
</table>
<pre>
We recently ran into an issue with poor scalar RV64 codegen:
https://godbolt.org/z/fGjGn7rr1
Interestingly, the issue is not there when the offsets are not compile-time consntants.
The repro is using SiFive's VCIX instructions, because that's how we noticed the issue, but I don't think the VCIX instructions are actually particularly important here. (Although they might just act as "barriers" to other optimizations/transformations, which might contribute to surfacing the actual program?)
@topperc had an initial look at this:
> I don’t think I’ve seen this specific issue before. At least not to this extreme.
>
>The issue appears to be that the middle end aggressively constant folded the getelementptr instructions in IR into unique operations like this
>
> ```
> %6 = getelementptr inbounds i32, ptr %0, i64 128
> %7 = tail call <vscale x 4 x i32> @llvm.riscv.vle.nxv4i32.i64(<vscale x 4 x i32> poison, ptr nonnull %6, i64 %4)
> %8 = getelementptr inbounds i32, ptr %0, i64 256
> ```
>
> They are no longer in a chain, each is independent and some of them have large constants. It looks like at least some of the constants appear twice.
>
>Each one of these getelementptrs is independently codegened to an add. If the constant is small enough, we’ll use an ADDI. Otherwise we’ll use an ADD and create the constant separately. Any constant that is used twice is selected to a sequence that materializes that constant, and is shared by call uses.
>
> I don’t think scheduling has any real effect here.
>
> At register allocation, we figure out we don’t have enough registers for all the large constants we need since they are used twice. Register allocation can try to rematerialize the constant creation instructions to avoid the spill, but that currently only works if creating the constant can be done in a single instruction with no other inputs. All of these constants, are two instructions, an LI+SLLI so they fail to rematerialize.
>
> One easyish fix would be to create a pseudo instruction that represents LI+SLLI as a single instruction until after register allocation. That would allow register allocation to rematerialize it as a single “instruction". Then we could expand it to LI+SLLI after realloc and use the post-realloc schedule to move the LI and SLLI away from each other to allow the scalar pipe to dual issue with other instructions. I think this is roughly how ARM handles constant materialization.
>
> Another option that would be better for code size, but more work to implement, is to write a new optimization pass that reconstructs a chain ADDs so we can use a series of ADDI 512 to construct each constant relative to the previous one. I thought the StraightLineStrengthReduce pass in LLVM might be able to do this. It’s not enabled by default, and my quick test didn’t show any improvement from using it.
>
> Feel free to file a GitHub issue.
>
> ~Craig
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJycV01z2zwO_jXKBVONTX_EPviQN6m7nsk73Uk73b1SEiShoUiVoOy4h_3tOyDlj3x0DzuTiW2JBMAHDx6Ampkai7jJFn9li4cbPYTW-U1HZatNuClcddz8C8FjiTaYI3htgWxwIJ_MA8KBQgu9cx641EZ7ePqxnEPpKmzQZrO7bPKQTe7aEHqWX2qbqW3jqsKZkDvfZGr7O1Pb-svPL_bW-2lavrMBPXIg25hjpu4htDj6IwbrgjzwCIcWbXzn6poxMGiP8XXpup4MfgrUIZTOsg3aBs6T-fT_eysH670TmwOTbeAbbWmPmbpl-HG_-zeQ5eCHMpCzLGEUWOqBEUKrQ1zVugMcoksqsbqEGRcPAXZQOZupWwmY7HNc8M5yjFqXYdDGHKHXPlA5GO3NEajrnZfQQc6bQ6ZWdya0bmhasXWEjpo2wM-Bg1gAzZApVWjvCT1nSkFw4AQscH2gjn7r8TDb4LXl2vlOn493aKlsR5Ols8FTMQQUEzz4WpcCkZwgxQq9d43XXTbbZmp9jWw2nwTX9-hLaHUVuWIpkDZgnHsGHdHgMznG_7PPI1yfVbaaZOv1CbTd-ckegTGmnBi4x5JqKkdiFFg7gegugEHNIdHEpbX4Ejx2mJ9dnb98PzNL9z1qz7KnSCmOh-2oqgwC2gp003hkpj2aY2RVzEztTDXmvsGABju0oQ_-dY7Jwu4p1c5g6deA4Hr0CXsw9IwJk3fxQbacjH-XR2qxhGz28M5f4QZbMdBMSTrlWaYWE_lOyzlM1eqVjdtoI2gyUGpjIJvd76WIEV5gDi_RjKycT4zZd7knLvf53mBuX_ZzmqmclvNMrf6wrXfEwv0Uh3XWDuJDLZaneDK1mF-YM_sM8mT1fxxMbP4PvC7vvkvJJI0A42yDYhs0lK2mGCrqshU5IFthj7ZCG0DbCth1IjKS5A5avUcw2jd4JgHnsAuR3WMy9YmFVzsvq0euQThQ-REpP0sYzp428htm8ZsQIxuj4AoPozjrqsph99qt7OJOMo1WFCSWPJ6LyxgQbdMW7h4edjl8Fdk4EOMfF0VoSo9aROLaEWOvvQ5ojjnc2ataiVUV5VYildPHoNBgGcbYgfHXgLYcS7DTAT1pQ7-R05OTMQlfAhADrfZYQXFMRB4Y-QNU_yAvXLZYDUbErdUM2h7BozaAdY3lKLwfGLsL4LEhDuhBG-PKWMsJU6ipGTyCG4L8eu010idl4GyBoXbRTMTxDbdih0GsgCnBMpL4AmIOT-9DgVJbCP4oqHq8wvF1rmL-ZPkruZJM7B0lWeOejDm1tJSDwftEPGfNEQ7OPzNQPRob28TFhbYiqZUwOtabNFuD1x7THGFPzYpsP0hR3RlzqYEzIDHzHiEc3LsWrS087jL117fHxx2wS2jVonFvYfgoqV8tAmo-ErdQ0wsc3GCq2A7ciegaesaheuU5gSLDBDJKxi4hCKM-Ou9gAxnQteTsAx7l8F1MJv_y-PDRqveppfDK44l291euM6XEOlrhVRkd4EsfKyk2zKvYx-iiw1hrafhB6B2HT6cXYwFFkDq3Tytku60g2TnoI9TedUlfU4qFYfFckWFpduypj1YqGS-u5ssTKS6pzmF3Hqko6qGXgjLHOJLdPf0NrbaVQb6w8AJTQvijmraXWemU1TMFCgwChxSqqC0w_T7PeZ2TadT5Z4meuj5JdexPsZYOniJ1LB5eDWLQa-YTe2KkckA-tSQRWRYWS6a0TdILjJ6QpS5EqGExjVPeeXcC-Xxsj0YH2mOahRB6j3tyA0t_SSgKcGnW-Ra8lunvkSx-Cx5tE9onrIYSU6Bk4fHxx9_jiFgg6CKlvUpzlnTBs9KlQR2trInaXGGtB3PW7e4IvwYqnyEgB6iouhZJljSKFFPXe7ePcCYKpUmdwkf52yIaqD3GmGoygtYXCv8YisSm_GpMOH_7z70cOv2-qTazaj1b6xvcTJfr29vpdLFc3rSb5aReYrFaqMVqqifLxaRQt1OcTW5X63VZL4ob2qiJmk0n0_V0MlPzZb7Ut7Nqpuv5ejVTi8Uim0-w02TyOEw539zEkDbL9WK1vDG6QMPxGqaUsGS8Rii5lfmN7PlUDA3LMEYc-GIlUDC4-afcwK6vXqmhXJqpq2UmoKTusaje3ZGitt4M3mzeXNcotEORl67L1Fb8jh-feu9-YhkytY3Ryq0inua_AQAA__8T_NsR">