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]
Other format: [Raw text]

Fix PR rtl-optimization/31944


This is an infinite loop compiling the Linux kernel for the 64-bit PA at -O2, 
a regression from 3.4.x present on all the branches.  The loop occurs during
CSE1 when the hash table is being flushed, because there is a dangling pseudo 
in the table that was not removed when its "quantity number" changed.

More precisely, the pseudo had been inserted twice, for SImode and DImode, and 
only one occurrence was removed because, contrary to what the 'invalidate' 
function does, the 'merge_equiv_classes' function overlooks this case.

Bootstrapped/regtested on i586-suse-linux, applied on all the branches.


2008-01-14  Eric Botcazou  <ebotcazou@adacore.com>

	PR rtl-optimization/31944
	* cse.c (remove_pseudo_from_table): New function.
	(merge_equiv_classes): Use above function to remove pseudo-registers.
	(invalidate): Likewise.


2008-01-14  Eric Botcazou  <ebotcazou@adacore.com>

	* gcc.c-torture/compile/20080114-1.c: New test.


-- 
Eric Botcazou
Index: cse.c
===================================================================
--- cse.c	(revision 131425)
+++ cse.c	(working copy)
@@ -554,7 +554,8 @@ static void delete_reg_equiv (unsigned i
 static int mention_regs (rtx);
 static int insert_regs (rtx, struct table_elt *, int);
 static void remove_from_table (struct table_elt *, unsigned);
-static struct table_elt *lookup	(rtx, unsigned, enum machine_mode);
+static void remove_pseudo_from_table (rtx, unsigned);
+static struct table_elt *lookup (rtx, unsigned, enum machine_mode);
 static struct table_elt *lookup_for_remove (rtx, unsigned, enum machine_mode);
 static rtx lookup_as_function (rtx, enum rtx_code);
 static struct table_elt *insert (rtx, struct table_elt *, unsigned,
@@ -1288,6 +1289,19 @@ remove_from_table (struct table_elt *elt
   free_element_chain = elt;
 }
 
+/* Same as above, but X is a pseudo-register.  */
+
+static void
+remove_pseudo_from_table (rtx x, unsigned int hash)
+{
+  struct table_elt *elt;
+
+  /* Because a pseudo-register can be referenced in more than one
+     mode, we might have to remove more than one table entry.  */
+  while ((elt = lookup_for_remove (x, hash, VOIDmode)))
+    remove_from_table (elt, hash);
+}
+
 /* Look up X in the hash table and return its table element,
    or 0 if X is not in the table.
 
@@ -1605,7 +1619,10 @@ merge_equiv_classes (struct table_elt *c
 	      delete_reg_equiv (REGNO (exp));
 	    }
 
-	  remove_from_table (elt, hash);
+	  if (REG_P (exp) && REGNO (exp) >= FIRST_PSEUDO_REGISTER)
+	    remove_pseudo_from_table (exp, hash);
+	  else
+	    remove_from_table (elt, hash);
 
 	  if (insert_regs (exp, class1, 0) || need_rehash)
 	    {
@@ -1701,14 +1718,7 @@ invalidate (rtx x, enum machine_mode ful
 	SUBREG_TICKED (regno) = -1;
 
 	if (regno >= FIRST_PSEUDO_REGISTER)
-	  {
-	    /* 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;
-
-	    while ((elt = lookup_for_remove (x, hash, GET_MODE (x))))
-	      remove_from_table (elt, hash);
-	  }
+	  remove_pseudo_from_table (x, hash);
 	else
 	  {
 	    HOST_WIDE_INT in_table
/* PR rtl-optimization/31944 */
/* Origin: Aurelien Jarno <aurelien@aurel32.net> */

int type;

void stuck(int res)
{
  if (type == 1) {
    if (res == 0) asm volatile("nop");
  }
  else if (type == 0) {
    if (res == 0) asm volatile("nop" : : "i" (0));
  }
}

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