Patchwork [PR52417] restore get_addr behavior for passes other than VT

login
register
mail settings
Submitter Alexandre Oliva
Date March 1, 2012, 4:53 p.m.
Message ID <orpqcw6z4u.fsf@livre.localdomain>
Download mbox | patch
Permalink /patch/144073/
State New
Headers show

Comments

Alexandre Oliva - March 1, 2012, 4:53 p.m.
The PR52001 alias.c patch meant to avoid infinite recursion among
permanent equivalences within VTA introduced some relatively expensive
behavior that showed up as (apparently?)-infinite recursion within dse
on AVR for one gcc.c-torture/compile test.

This patch reworks get_addr so that it behaves exactly as before when
permanent equivalences are not in use (i.e., any pass other than var
tracking) and retains the heuristics that avoids infinite recursion only
when permanent equivalences are present, when needed.

Regstrapped on x86_64-linux-gnu and i686-pc-linux-gnu, compile-time
tested for the given AVR testcase, approved (minus the comment before
the newly-added function) by Jakub in bugzilla, checking in.

Patch

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

	PR debug/52001
	PR rtl-optimization/52417
	* cselib.c (cselib_any_perm_equivs): New variable.
	(cselib_reset_table): Check that it's not set when not
	preserving constants.
	(cselib_add_permanent_equiv): Set it.
	(cselib_have_permanent_equivalences): New.
	(cselib_init, cselib_finish): Reset it.
	* cselib.h (cselib_have_permanent_equivalences): Declare.
	* alias.c (get_addr): Restore earlier behavior when there
	aren't permanent equivalences.

Index: gcc/alias.c
===================================================================
--- gcc/alias.c.orig	2012-03-01 04:25:47.348625625 -0300
+++ gcc/alias.c	2012-03-01 07:49:11.000000000 -0300
@@ -1811,20 +1811,34 @@  get_addr (rtx x)
   v = CSELIB_VAL_PTR (x);
   if (v)
     {
-      v = canonical_cselib_val (v);
+      bool have_equivs = cselib_have_permanent_equivalences ();
+      if (have_equivs)
+	v = canonical_cselib_val (v);
       for (l = v->locs; l; l = l->next)
 	if (CONSTANT_P (l->loc))
 	  return l->loc;
       for (l = v->locs; l; l = l->next)
-	if (!REG_P (l->loc) && !MEM_P (l->loc) && GET_CODE (l->loc) != VALUE
-	    && !refs_newer_value_p (l->loc, x))
+	if (!REG_P (l->loc) && !MEM_P (l->loc)
+	    /* Avoid infinite recursion when potentially dealing with
+	       var-tracking artificial equivalences, by skipping the
+	       equivalences themselves, and not choosing expressions
+	       that refer to newer VALUEs.  */
+	    && (!have_equivs
+		|| (GET_CODE (l->loc) != VALUE
+		    && !refs_newer_value_p (l->loc, x))))
 	  return l->loc;
-      for (l = v->locs; l; l = l->next)
-	if (REG_P (l->loc) || (GET_CODE (l->loc) != VALUE
-			       && !refs_newer_value_p (l->loc, x)))
-	  return l->loc;
-      /* Return the canonical value.  */
-      return v->val_rtx;
+      if (have_equivs)
+	{
+	  for (l = v->locs; l; l = l->next)
+	    if (REG_P (l->loc)
+		|| (GET_CODE (l->loc) != VALUE
+		    && !refs_newer_value_p (l->loc, x)))
+	      return l->loc;
+	  /* Return the canonical value.  */
+	  return v->val_rtx;
+	}
+      if (v->locs)
+	return v->locs->loc;
     }
   return x;
 }
Index: gcc/cselib.c
===================================================================
--- gcc/cselib.c.orig	2012-03-01 07:44:32.426668955 -0300
+++ gcc/cselib.c	2012-03-01 13:15:07.000000000 -0300
@@ -52,6 +52,7 @@  struct elt_list {
 
 static bool cselib_record_memory;
 static bool cselib_preserve_constants;
+static bool cselib_any_perm_equivs;
 static int entry_and_rtx_equal_p (const void *, const void *);
 static hashval_t get_value_hash (const void *);
 static struct elt_list *new_elt_list (struct elt_list *, cselib_val *);
@@ -477,7 +478,10 @@  cselib_reset_table (unsigned int num)
   if (cselib_preserve_constants)
     htab_traverse (cselib_hash_table, preserve_constants_and_equivs, NULL);
   else
-    htab_empty (cselib_hash_table);
+    {
+      htab_empty (cselib_hash_table);
+      gcc_checking_assert (!cselib_any_perm_equivs);
+    }
 
   n_useless_values = 0;
   n_useless_debug_values = 0;
@@ -2388,6 +2392,8 @@  cselib_add_permanent_equiv (cselib_val *
 
   if (nelt != elt)
     {
+      cselib_any_perm_equivs = true;
+
       if (!PRESERVED_VALUE_P (nelt->val_rtx))
 	cselib_preserve_value (nelt);
 
@@ -2397,6 +2403,14 @@  cselib_add_permanent_equiv (cselib_val *
   cselib_current_insn = save_cselib_current_insn;
 }
 
+/* Return TRUE if any permanent equivalences have been recorded since
+   the table was last initialized.  */
+bool
+cselib_have_permanent_equivalences (void)
+{
+  return cselib_any_perm_equivs;
+}
+
 /* There is no good way to determine how many elements there can be
    in a PARALLEL.  Since it's fairly cheap, use a really large number.  */
 #define MAX_SETS (FIRST_PSEUDO_REGISTER * 2)
@@ -2651,6 +2665,7 @@  cselib_init (int record_what)
   value_pool = create_alloc_pool ("value", RTX_CODE_SIZE (VALUE), 100);
   cselib_record_memory = record_what & CSELIB_RECORD_MEMORY;
   cselib_preserve_constants = record_what & CSELIB_PRESERVE_CONSTANTS;
+  cselib_any_perm_equivs = false;
 
   /* (mem:BLK (scratch)) is a special mechanism to conflict with everything,
      see canon_true_dependence.  This is only created once.  */
@@ -2684,6 +2699,7 @@  cselib_finish (void)
 {
   cselib_discard_hook = NULL;
   cselib_preserve_constants = false;
+  cselib_any_perm_equivs = false;
   cfa_base_preserved_val = NULL;
   cfa_base_preserved_regno = INVALID_REGNUM;
   free_alloc_pool (elt_list_pool);
Index: gcc/cselib.h
===================================================================
--- gcc/cselib.h.orig	2012-03-01 07:44:32.875663665 -0300
+++ gcc/cselib.h	2012-03-01 07:49:24.608222578 -0300
@@ -98,6 +98,7 @@  extern bool cselib_preserved_value_p (cs
 extern void cselib_preserve_only_values (void);
 extern void cselib_preserve_cfa_base_value (cselib_val *, unsigned int);
 extern void cselib_add_permanent_equiv (cselib_val *, rtx, rtx);
+extern bool cselib_have_permanent_equivalences (void);
 
 extern void dump_cselib_table (FILE *);