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 <mar...@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