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.

Reply via email to