This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]