This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [testcase] CSE bug
On Mon, Jul 23, 2001 at 07:49:34PM -0300, Alexandre Oliva wrote:
> On Jul 23, 2001, Richard Henderson <rth@redhat.com> wrote:
>
> > On Mon, Jul 23, 2001 at 04:35:59PM +0200, Jakub Jelinek wrote:
>
> >> But remove_invalid_subreg_refs(60,0,SImode) invalidates only
> >> (subreg:SI (reg:DI 60) 0),
> >> (which in fact was not needed if invalidate_skipped_block recorded somewhere
> >> that only part of the register needs to be invalidated and which one) and
> >> from this point on, (subreg:SI (reg:DI 60) 4) is handled like if nobody
> >> would ever touch it.
> >> Any ideas what's the right way to fix this?
>
> > Alex, didn't you have a patch that touched on this sort
> > of thing? Did it ever get reviewed?
>
> Yeah, the description sounds somewhat similar, but there a number of
> function names that don't ring any bells right now. The problem
> originally showed up on mn10300-elf, with a C++ test case, IIRC.
>
> I got some feedback, but never an official approval or rejection.
> Here's the patch file, created on Nov 18, 2000:
You need to fix it up for SUBREG_BYTE slightly - current GCC will not allow
you to create a VOIDmode SUBREG. As canon_hash only adds SUBREG_BYTE(x) / UNITS_PER_WORD
to hash, it is enough to step in UNITS_PER_WORD steps.
With this modified patch my testcase works fine (though I haven't done full
bootstrap).
--- gcc/cse.c.jj Sun Jul 22 21:33:49 2001
+++ gcc/cse.c Wed Jul 25 13:42:04 2001
@@ -1480,6 +1480,17 @@ lookup_for_remove (x, hash, mode)
&& REGNO (p->exp) == regno)
return p;
}
+ else if (GET_CODE (x) == SUBREG && GET_CODE (SUBREG_REG (x)) == REG)
+ {
+ unsigned int regno = REGNO (SUBREG_REG (x));
+
+ /* Don't check the machine mode when comparing SUBREGs. */
+ for (p = table[hash]; p; p = p->next_same_hash)
+ if (GET_CODE (p->exp) == SUBREG
+ && GET_CODE (SUBREG_REG (p->exp)) == REG
+ && REGNO (SUBREG_REG (p->exp)) == regno)
+ return p;
+ }
else
{
for (p = table[hash]; p; p = p->next_same_hash)
@@ -1874,9 +1885,21 @@ invalidate (x, full_mode)
/* Because a register can be referenced in more than one mode,
we might have to remove more than one table entry. */
struct table_elt *elt;
+ int i;
while ((elt = lookup_for_remove (x, hash, GET_MODE (x))))
remove_from_table (elt, hash);
+
+ /* Since multi-word PSEUDOS may also be referenced through
+ SUBREGs, we attempt to remove such subregs too. */
+ for (i = 0; i * UNITS_PER_WORD < GET_MODE_SIZE (GET_MODE (x)); i++)
+ {
+ rtx subreg = gen_rtx_SUBREG (word_mode, x, i * UNITS_PER_WORD);
+ unsigned hash = HASH (subreg, VOIDmode);
+
+ while ((elt = lookup_for_remove (subreg, hash, VOIDmode)))
+ remove_from_table (elt, hash);
+ }
}
else
{
Jakub