On Thu, 24 Jun 2021, Jakub Jelinek wrote:

> Hi!
> 
> The recent addition of gcc_assert (regno < endregno); triggers during
> glibc build on m68k.
> The problem is that RA decisions shouldn't depend on expressions in
> DEBUG_INSNs and those expressions can contain paradoxical subregs of certain
> pseudos.  If RA then decides to allocate the pseudo to a register
> with very small hard register REGNO, we can trigger the new assert,
> as (int) subreg_regno_offset may be negative on big endian and the small
> REGNO + the negative offset can wrap around.

Hm, I wonder if we should reset the debug_insn if the RA made a decision
that produces such non-sensical result for a debug_insn use?

> The following patch in that case records the range from the REGNO 0 to
> endregno, before the addition of the assert as both regno and endregno are
> unsigned it wouldn't record anything at all silently.
> 
> Bootstrapped/regtested on x86_64-linux and i686-linux and tested with a
> cross compiler to m68k-liux on the testcase, ok for trunk?

OK.

Thanks,
Richard.

> 2021-06-24  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR middle-end/101170
>       * df-scan.c (df_ref_record): For paradoxical big-endian SUBREGs
>       where regno + subreg_regno_offset wraps around use 0 as starting
>       regno.
> 
>       * gcc.dg/pr101170.c: New test.
> 
> --- gcc/df-scan.c.jj  2021-06-22 10:04:46.371208994 +0200
> +++ gcc/df-scan.c     2021-06-23 12:46:51.654678805 +0200
> @@ -2576,9 +2576,21 @@ df_ref_record (enum df_ref_class cl,
>  
>        if (GET_CODE (reg) == SUBREG)
>       {
> -       regno += subreg_regno_offset (regno, GET_MODE (SUBREG_REG (reg)),
> -                                     SUBREG_BYTE (reg), GET_MODE (reg));
> -       endregno = regno + subreg_nregs (reg);
> +       int off = subreg_regno_offset (regno, GET_MODE (SUBREG_REG (reg)),
> +                                      SUBREG_BYTE (reg), GET_MODE (reg));
> +       unsigned int nregno = regno + off;
> +       endregno = nregno + subreg_nregs (reg);
> +       if (off < 0 && regno < (unsigned) -off)
> +         /* Deal with paradoxical SUBREGs on big endian where
> +            in debug insns the hard reg number might be smaller
> +            than -off, such as (subreg:DI (reg:SI 0 [+4 ]) 0));
> +            RA decisions shouldn't be affected by debug insns
> +            and so RA can decide to put pseudo into a hard reg
> +            with small REGNO, even when it is referenced in
> +            a paradoxical SUBREG in a debug insn.  */
> +         regno = 0;
> +       else
> +         regno = nregno;
>       }
>        else
>       endregno = END_REGNO (reg);
> --- gcc/testsuite/gcc.dg/pr101170.c.jj        2021-06-23 12:27:08.866593960 
> +0200
> +++ gcc/testsuite/gcc.dg/pr101170.c   2021-06-23 12:26:55.823769555 +0200
> @@ -0,0 +1,37 @@
> +/* PR middle-end/101170 */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -g" } */
> +
> +#include <stdarg.h>
> +
> +struct S { int a; int b[4]; } s;
> +va_list ap;
> +int i;
> +long long l;
> +
> +struct S
> +foo (int x)
> +{
> +  struct S a = {};
> +  do
> +    if (x)
> +      return a;
> +  while (1);
> +}
> +
> +__attribute__((noipa)) void
> +bar (void)
> +{
> +  for (; i; i++)
> +    l |= va_arg (ap, long long) << s.b[i];
> +  if (l)
> +    foo (l);
> +}
> +
> +void
> +baz (int v, ...)
> +{
> +  va_start (ap, v);
> +  bar ();
> +  va_end (ap);
> +}
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Felix Imendörffer; HRB 36809 (AG Nuernberg)

Reply via email to