public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* Latent bug in update_equiv_regs?
@ 2009-08-20  0:01 Jeff Law
  2009-08-20  0:24 ` Ian Lance Taylor
  0 siblings, 1 reply; 8+ messages in thread
From: Jeff Law @ 2009-08-20  0:01 UTC (permalink / raw)
  To: GCC

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

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2009-08-20 14:03 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-08-20  0:01 Latent bug in update_equiv_regs? Jeff Law
2009-08-20  0:24 ` Ian Lance Taylor
2009-08-20  1:20   ` Jeff Law
2009-08-20  4:48     ` Ian Lance Taylor
2009-08-20 14:03       ` Jeff Law
2009-08-20  9:48     ` Richard Guenther
2009-08-20 14:27       ` Jeff Law
2009-08-20 15:11         ` Richard Guenther

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).