Hi Peter,
On Fri, Oct 19, 2018 at 04:16:12PM -0500, Peter Bergner wrote:
> In lra-constraints.c:process_alt_operands(), we notice that pseudo 92 is
> assigned to x1 and that an early clobber operand is also assigned to x1, or
> rather, that it uses x1 explicitly. This is enough to trigger reload(s),
> but the problem is we end up trying to reload the early clobber operand
> which has been forced into x1 via register asm assignment, instead of
> pseudo 92 which conflicts with it.
> Secondly, I don't think it's ever legal to reload an operand
> that has been hard coded by the user to a hard register via a register asm
> definition like in the test case above.
Yup.
> With that in mind, what do people think of the patch below? This fixes the
> AARCH64 test case. However, it ICE's on the following test case:
>
> long foo (long arg)
> {
> register long var asm("x0");
> asm("bla %0 %1" : "+&r"(var) : "r"(arg));
> return var;
> }
(As an "unable to generate reloads for" fatal).
> ...but that is due to a combine bug where combine replaces the use of
> "arg"'s pseudo in the inline asm with the incoming argument reg x0 which
> should be illegal. Ie, it's taking a valid inline asm and creating an
> invalid one since the earlyclobber op and non-matching op have both
> been forced to use the same hard reg. Segher has a combine patch to
> stop that which he is going to submit (commit?) soon.
Yup. It is quite a bit more generic: it prevents combine from combining
a hard-not-fixed-reg-to-pseudo-copy with any instruction, not just with
asm's.
> With my patch,
> we are also now able to catch the following user error, when before we
> could not:
>
> bergner@pike:~/gcc/BUGS/PR87507/AARCH64$ cat ice4.i
> long foo (void)
> {
> register long arg asm("x1");
> register long var asm("x1");
> asm ("bla %0 %1" : "=&r"(arg) : "r"(var));
> return arg;
> }
> bergner@pike:~/gcc/BUGS/PR87507/AARCH64$ .../xgcc -B.../gcc -O2
> -march=armv8.1-a -S ice4.i
> ice4.i: In function âfooâ:
> ice4.i:7:1: error: unable to generate reloads for:
> 7 | }
> | ^
> (insn 5 6 10 2 (set (reg/v:DI 1 x1 [ arg ])
> (asm_operands:DI ("bla %0 %1") ("=&r") 0 [
> (reg/v:DI 1 x1 [ var ])
> ]
> [
> (asm_input:DI ("r") ice4.i:5)
> ]
> [] ice4.i:5)) "ice4.i":5 -1
> (nil))
> during RTL pass: reload
> ice4.i:7:1: internal compiler error: in process_alt_operands, at
> lra-constraints.c:2911
Nice! What did it do before? Oh, it reloaded things into other regs,
generating incorrect code. Ouch!
> I can't test
> this on aarch64 or arm, other than knowing my aarch64 cross doesn't ICE on
> the test case above.
The compile farm has six aarch64 machines ;-)
> --- gcc/lra-constraints.c (revision 264897)
> +++ gcc/lra-constraints.c (working copy)
> @@ -2904,18 +2904,29 @@ process_alt_operands (int only_alternati
> if (first_conflict_j < 0)
> first_conflict_j = j;
> last_conflict_j = j;
> + /* Both the earlyclobber operand and conflicting operand
> + cannot both be hard registers. */
> + if (REGNO (operand_reg[i]) < FIRST_PSEUDO_REGISTER
> + && operand_reg[j] != NULL_RTX
> + && REGNO (operand_reg[j]) < FIRST_PSEUDO_REGISTER)
> + fatal_insn ("unable to generate reloads for:", curr_insn);
You could use HARD_REGISTER_P here, fwiw.
Segher