https://gcc.gnu.org/bugzilla/show_bug.cgi?id=123092
Jeffrey A. Law <law at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |rdapp at gcc dot gnu.org,
| |vmakarov at gcc dot gnu.org
--- Comment #11 from Jeffrey A. Law <law at gcc dot gnu.org> ---
So as I hinted at on Tuesday, the LRA code is making changes to the relevant
insn without checking for the validity of those changes.
However, it's happening through a path I'm not familiar with. In particular
here:
if (curr_insn_transform (false))
changed_p = true;
/* Check non-transformed insns too for equiv change as USE
or CLOBBER don't need reloads but can contain pseudos
being changed on their equivalences. */
else if (bitmap_bit_p (equiv_insn_bitmap, INSN_UID (curr_insn))
&& loc_equivalence_change_p (&PATTERN (curr_insn)))
{
lra_update_insn_regno_info (curr_insn);
changed_p = true;
}
THe incoming form as we call curr_insn_transform is:
(insn 8 12 13 2 (prefetch (plus:DI (reg/f:DI 139 [ d.b ])
(const_int 64 [0x40]))
(const_int 0 [0])
(const_int 3 [0x3])) "j.c":7:3 500 {prefetch}
(expr_list:REG_DEAD (reg/f:DI 139 [ d.b ])
(nil)))
Obviously we have a pseudo in there. Note we don't have any naked
USE/CLOBBERs.
curr_insn_transform returns false (at least one alternative fits), but no
changes are made by curr_insn_transform. Then loc_equivalence_change_p does
its thing resulting in:
(insn 8 12 13 2 (prefetch (plus:DI (mem/f/c:DI (lo_sum:DI (reg/f:DI 137)
(symbol_ref:DI ("d") [flags 0x86] <var_decl 0x7ffff73c5be0
d>)) [1 d.b+0 S8 A64])
(const_int 64 [0x40]))
(const_int 0 [0])
(const_int 3 [0x3])) "j.c":7:3 500 {prefetch}
(expr_list:REG_DEAD (reg/f:DI 139 [ d.b ])
(nil)))
At which point the form hangs around forever and results in the failure we're
seeing. We do _not_ get back into curr_insn_transform for this insn to try and
reload it.
If I hack up loc_equivalence_change_p to do nothing for this insn then we
replace the pseudo with its MEM equivalence. We then reload the operand of the
prefetch into a new register (via a subsequent call to curr_insn_transform) and
the right things just happen.
Vlad -- how is this supposed to work? It seems wrong to be slamming in the
equivalence without either validating the result to verify its valid or sending
it back through curr_insn_transform to reload the invalid stuff.
Interesting enough Robin has a similar issue in play where we slam in a
constant equivalence for a register resulting in an invalid insn. I suspect,
but haven't yet confirmed that its the same basic path we're seeing here.