]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR debug/52001 (Huge compile-time regression with var-tracking)
authorAlexandre Oliva <aoliva@redhat.com>
Thu, 1 Mar 2012 16:58:11 +0000 (16:58 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Thu, 1 Mar 2012 16:58:11 +0000 (16:58 +0000)
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.

From-SVN: r184750

gcc/ChangeLog
gcc/alias.c
gcc/cselib.c
gcc/cselib.h

index c18b26129f01726092753bd83ca21b9421a34beb..805e359e819857bcfa9340854bec6afda574037b 100644 (file)
@@ -1,3 +1,17 @@
+2012-03-01  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.
+
 2012-03-01  Steven Bosscher  <steven@gcc.gnu.org>
 
        * config/mn10300/mn10300-modes.def: Fix copyright notice.
index 4bda40d8836dae52a1e2ecfdf61290c67360aab4..e9d701f96362e55852d929e012fc5670f5a698ba 100644 (file)
@@ -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 4985357c83a40d14456e774395ed2f3211be8d46..56f2b7f9ffe3a2c0edc2e1dcfd15450b424181b0 100644 (file)
@@ -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 *elt, rtx x, rtx insn)
 
   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 *elt, rtx x, rtx insn)
   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 5b5fe23ae4039b4d28dde5d51735da5038e70650..96575f985e085d0d6c0b66f1810a1814c839d2af 100644 (file)
@@ -98,6 +98,7 @@ extern bool cselib_preserved_value_p (cselib_val *);
 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 *);