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

Reply via email to