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)