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]

clobber doesn't invalidate subregs in cse


This problem has first shown up on mn10300-elf, with -O.  As you'll
note, the value of pf.u.pnf is supposed to end up being copied onto
itself.  It turns out that, on mn10300-elf, the DI pseudo that holds
the value of `pf' is clobbered before pf is assigned a new value, but,
because invalidate_from_clobbers() hadn't removed (subreg:SI (reg:DI
<pf>) 1) from the table of available expressions, cse ends up
assigning it onto itself.  The assignment is later by flow, and so is
the first assignment, since it is clobbered afterwards, so pf ends up
uninitialized.

This patch arranges for invalidate_from_clobbers to invalidate all
subregs of a register when a register is invalidated.

This is sub-optimal because, when a subreg is invalidated,
invalidate() kills the whole register, whereas it would be sufficient
to kill just the affected words.  Before I spend any further time
implementing this optimization, does this approach seem reasonable?
Mind you, the patch didn't introduce any regressions on mn10300-elf.
I couldn't reproduce the original problem on x86.

Index: gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* cse.c (invalidate) [REG]: Invalidate all SUBREGs of the REG.
	(lookup_for_remove): Handle SUBREGs.

Index: gcc/cse.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cse.c,v
retrieving revision 1.164
diff -u -p -r1.164 cse.c
--- gcc/cse.c 2000/11/07 22:49:51 1.164
+++ gcc/cse.c 2000/11/18 22:27:04
@@ -1481,6 +1481,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)
@@ -1880,9 +1891,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 (VOIDmode, x, i);
+		unsigned hash = HASH (subreg, VOIDmode);
+
+		while ((elt = lookup_for_remove (subreg, hash, VOIDmode)))
+		  remove_from_table (elt, hash);
+	      }
 	  }
 	else
 	  {
Index: gcc/testsuite/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	* gcc.c-torture/execute/20001118-1.c: New test.

Index: gcc/testsuite/gcc.c-torture/execute/20001118-1.c
===================================================================
RCS file: 20001118-1.c
diff -N 20001118-1.c
--- /dev/null	Tue May  5 13:32:27 1998
+++ gcc/testsuite/gcc.c-torture/execute/20001118-1.c Sat Nov 18 14:27:06 2000
@@ -0,0 +1,32 @@
+/* Copyright 2000 Free Software Foundation
+   Origin: Jason Merrill <jason@redhat.com>.  */
+
+union foo {
+  void (*pfn)();
+  short delta2;
+};
+
+struct pmf {
+  short delta;
+  short index;
+  union foo u;
+};
+
+void f () { }
+
+int main ()
+{
+  struct pmf pf = { 0, -1, { &f } };
+
+  struct pmf pg = (pf.index > 0
+		   ? (struct pmf){ pf.delta, pf.index,{ delta2: pf.u.delta2 }}
+		   : (struct pmf){ pf.delta, pf.index,{ pfn: pf.u.pfn }});
+
+  pf = (pg.index > 0
+	? (struct pmf){ pg.delta, pg.index,{ delta2: pg.u.delta2 }}
+	: (struct pmf){ pg.delta, pg.index,{ pfn: pg.u.pfn }});
+
+  if (pf.u.pfn != &f)
+    abort ();
+  exit (0);
+}

-- 
Alexandre Oliva   Enjoy Guarana', see http://www.ic.unicamp.br/~oliva/
Red Hat GCC Developer                  aoliva@{cygnus.com, redhat.com}
CS PhD student at IC-Unicamp        oliva@{lsd.ic.unicamp.br, gnu.org}
Free Software Evangelist    *Please* write to mailing lists, not to me

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