[PATCH v2 0/5] RISC-V big endian support

Jim Wilson jimw@sifive.com
Tue Mar 23 22:52:46 GMT 2021


On Fri, Mar 19, 2021 at 9:22 AM Kito Cheng via Gcc-patches <
gcc-patches@gcc.gnu.org> wrote:

> On Mon, Mar 15, 2021 at 5:42 AM Marcus Comstedt <marcus@mc.pp.se> wrote:
> > I've now delved a bit deeper into the failure of the testcase
> > gcc.c-torture/compile/pr35318.c on big endian RV32.
>

Looking at this testcase, I think this is triggering undefined behavior for
extended asms.

We have an SImode integer constant 8, a DFmode input/output, a 0
constraint that matches the input to output, and then a % commutative
operator that lets us swap operands, except once we swap operands we are
now trying to force SImode and DFmode values to match via the 0 constraint
which is unreasonable, plus a m constraint that then forces an input to
memory.  It works by accident for little-endian because we reload the +0
word of the double and it is still considered the same operand, and it
fails for big-endian by accident because we reload the +4 word of the
double and now it is considered a different operand.

If I change the "8" to "(double)8" or "8.0" then the testcase works for
both big and little endian, as now we have only DFmode values.

I tried ppc-eabi and ppcle-eabi to see what happens there, and the main
difference is that it chooses the 1 alternative in both cases.  However,
for RISC-V, we choose the 0 alternative with operands swapped.  The reason
for this is that we have a DFmode pseudo that wants an FP reg for a load,
and the same pseudo wants a general reg in the asm, and rv32gc does not
have an instruction to move directly between 64-bit FP regs and 32-bit
general regs, so it gets put in memory as the lowest cost option.  That
then leads to the case that alt 0 with swapped operands has the lowest
cost, except this case is the invalid case that tries to match SImode and
DFmode operands with 0 and m constraints and fails.

To summarize, I think that there are two problems here.
1) The testcase is invalid, and can be fixed by changing the "8" to
"(double)8" or "8.0" to ensure that we have a double constant that matches
the type of the other operands.
2) GCC should be giving an error for an asm like this rather than an ICE.
Note that if I manually swap the operands and remove the % I get
void
foo ()
{
  double x = 4, y;
  __asm__ volatile ("" : "=r" (x), "=r" (y) : "0" (8), "m" (x));
}
which fails with an ICE for big-endian ppc exactly the same as it does for
big-endian RISC-V.  We should be generating an error here rather than an
ICE.

Jim


More information about the Gcc-patches mailing list