https://gcc.gnu.org/bugzilla/show_bug.cgi?id=79915
mpf at gcc dot gnu.org changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |ASSIGNED Last reconfirmed| |2017-03-31 CC| |mpf at gcc dot gnu.org Ever confirmed|0 |1 Known to fail| |7.0.1 --- Comment #5 from mpf at gcc dot gnu.org --- This is a bug coming from LRA rematerialisation. The issue is that one or more LEA64 instructions get rematerialized at a point where there are no other spills to resolve. Each LEA64 instruction introduces a new scratch which is a copy of the original scratch but is unallocated. lra_need_for_spills_p says false in this circumstance but is 'wrong'. One option is to simply go round the LRA loop one more time (and ensure that the lra_spill code does not assert because of there being no spills to deal with; it effectively becomes a NOP). There are plenty of alternative solutions which would involve determining whether remat introduced any new scratches and only running the loop again in that situation. We could also optimise to avoid running the lra_spill code as we really need to get to the top of the loop to re-run assignment I believe. It almost seems cleaner to continue round the LRA loop after remat and rely on the single exit point but I assume it was an optimisation to exit immediately after remat if it resolves all remaining spills. Vladimir: Is my description detailed enough for you to understand the issue or should I add dumps as well for a testcase? Is there anything 'safe enough' to do at this point of release? I'm testing my quick fix as below in case it is a suitable solution. diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c index 492fc18..863136d 100644 --- a/gcc/lra-spills.c +++ b/gcc/lra-spills.c @@ -565,7 +565,6 @@ lra_spill (void) /* We do not want to assign memory for former scratches. */ && ! lra_former_scratch_p (i)) pseudo_regnos[n++] = i; - lra_assert (n > 0); pseudo_slots = XNEWVEC (struct pseudo_slot, regs_num); for (i = FIRST_PSEUDO_REGISTER; i < regs_num; i++) { diff --git a/gcc/lra.c b/gcc/lra.c index ed1f062..c906d94 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -2490,8 +2490,6 @@ lra (FILE *f) /* We need full live info -- see the comment above. */ lra_create_live_ranges (lra_reg_spill_p, true); live_p = true; - if (! lra_need_for_spills_p ()) - break; } lra_spill (); /* Assignment of stack slots changes elimination offsets for