Somehow I can't help but think I'm missing something here...

Given:

  (set (reg X) (mem Y))

  (...)

  (set (mem Y) (reg Z))

  (...)

  (use  (reg X))



update_equiv_regs can set an equivalence between (reg X) and (mem Y) which is clearly wrong as (mem Y) is set to (reg Z).

99.99% of the time this doesn't cause us any problems. However, imagine if (reg X) is not assigned a hard register. Reload then gleefully replaces uses of (reg X) with its equivalent memory location. Given the RTL above that's clearly bad.

It looks like this code is supposed to wipe the problematic equivalence:

          /* We only handle the case of a pseudo register being set
             once, or always to the same value.  */
          /* ??? The mn10200 port breaks if we add equivalences for
values that need an ADDRESS_REGS register and set them equivalent to a MEM of a pseudo. The actual problem is in the over-conservative
             handling of INPADDR_ADDRESS / INPUT_ADDRESS / INPUT triples in
             calculate_needs, but we traditionally work around this problem
here by rejecting equivalences when the destination is in a register
             that's likely spilled.  This is fragile, of course, since the
preferred class of a pseudo depends on all instructions that set
             or use it.  */

          if (!REG_P (dest)
              || (regno = REGNO (dest)) < FIRST_PSEUDO_REGISTER
              || reg_equiv[regno].init_insns == const0_rtx
              || (CLASS_LIKELY_SPILLED_P (reg_preferred_class (regno))
&& MEM_P (src) && ! reg_equiv[regno].is_arg_equivalence))
            {
/* This might be setting a SUBREG of a pseudo, a pseudo that is
                 also set somewhere else to a constant.  */
              note_stores (set, no_equiv, NULL);
              continue;
            }

However, if we look at no_equiv we see the following:

/* Mark REG as having no known equivalence.
   Some instructions might have been processed before and furnished
   with REG_EQUIV notes for this register; these notes will have to be
   removed.
   STORE is the piece of RTL that does the non-constant / conflicting
   assignment - a SET, CLOBBER or REG_INC note.  It is currently not used,
but needs to be there because this function is called from note_stores. */
static void
no_equiv (rtx reg, const_rtx store ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
{
  int regno;
  rtx list;

  if (!REG_P (reg))
    return;

[ ... ]

Thus no_equiv doesn't do anything when passed a MEM.

I haven't tried triggering this problem with the mainline sources...

What am I missing?

jeff

Reply via email to