OSDN Git Service

PR/14362
authorzlomek <zlomek@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 11 Mar 2004 08:05:14 +0000 (08:05 +0000)
committerzlomek <zlomek@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 11 Mar 2004 08:05:14 +0000 (08:05 +0000)
* var-tracking.c (struct variable_def): Added field refcount.
(variable_htab_free): Decrease the refcount and delete variable
only if there are no more references.
(unshare_variable): New function.
(vars_copy_1): Increase refcount instead of copying the variable.
(variable_union): Share the variables where possible, unshare
the variables if needed.
(variable_different_p): Return false if var1 and var2 are
the same structure.
(variable_was_changed): Init the refcount of new variable.
(set_frame_base_location): Unshare variable if needed.
(set_variable_part): Init the refcount of new variable.
Unshare the variables if needed.
(delete_variable_part): Unshare the variables if needed.
(emit_notes_for_differences_1): Init the refcount of new variable.
(vt_add_function_parameters): Do not add function parameters to
IN set of ENTRY_BLOCK_PTR because it is unused anyway.
(vt_initialize): Do not add frame_base_decl to IN set of
ENTRY_BLOCK_PTR because it is unused anyway.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@79307 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/var-tracking.c

index c1df556..6707f58 100644 (file)
@@ -1,5 +1,28 @@
 2004-03-11  Josef Zlomek  <zlomekj@suse.cz>
 
+       PR/14362
+       * var-tracking.c (struct variable_def): Added field refcount.
+       (variable_htab_free): Decrease the refcount and delete variable
+       only if there are no more references.
+       (unshare_variable): New function.
+       (vars_copy_1): Increase refcount instead of copying the variable.
+       (variable_union): Share the variables where possible, unshare
+       the variables if needed.
+       (variable_different_p): Return false if var1 and var2 are
+       the same structure.
+       (variable_was_changed): Init the refcount of new variable.
+       (set_frame_base_location): Unshare variable if needed.
+       (set_variable_part): Init the refcount of new variable.
+       Unshare the variables if needed.
+       (delete_variable_part): Unshare the variables if needed. 
+       (emit_notes_for_differences_1): Init the refcount of new variable.
+       (vt_add_function_parameters): Do not add function parameters to
+       IN set of ENTRY_BLOCK_PTR because it is unused anyway.
+       (vt_initialize): Do not add frame_base_decl to IN set of
+       ENTRY_BLOCK_PTR because it is unused anyway.
+
+2004-03-11  Josef Zlomek  <zlomekj@suse.cz>
+
        * var-tracking.c (vars_copy_1): Cleanup and speedup chain operations.
        (vars_copy): Likewise.
        (variable_union): Likewise.
index 5b586bc..5da2376 100644 (file)
@@ -233,6 +233,9 @@ typedef struct variable_def
   /* The declaration of the variable.  */
   tree decl;
 
+  /* Reference count.  */
+  int refcount;
+
   /* Number of variable parts.  */
   int n_var_parts;
 
@@ -285,6 +288,7 @@ static void attrs_list_copy (attrs *, attrs);
 static void attrs_list_union (attrs *, attrs);
 
 static void vars_clear (htab_t);
+static variable unshare_variable (dataflow_set *set, variable var);
 static int vars_copy_1 (void **, void *);
 static void vars_copy (htab_t, htab_t);
 static void var_reg_delete_and_set (dataflow_set *, rtx);
@@ -629,6 +633,15 @@ variable_htab_free (void *elem)
   variable var = (variable) elem;
   location_chain node, next;
 
+#ifdef ENABLE_CHECKING
+  if (var->refcount <= 0)
+    abort ();
+#endif
+
+  var->refcount--;
+  if (var->refcount > 0)
+    return;
+
   for (i = 0; i < var->n_var_parts; i++)
     {
       for (node = var->var_part[i].loc_chain; node; node = next)
@@ -732,32 +745,29 @@ vars_clear (htab_t vars)
   htab_empty (vars);
 }
 
-/* Copy one variable from *SLOT to hash table DATA.  */
+/* Return a copy of a variable VAR and insert it to dataflow set SET.  */
 
-static int
-vars_copy_1 (void **slot, void *data)
+static variable
+unshare_variable (dataflow_set *set, variable var)
 {
-  htab_t dst = (htab_t) data;
-  variable src, *dstp, var;
+  void **slot;
+  variable new_var;
   int i;
 
-  src = *(variable *) slot;
-  dstp = (variable *) htab_find_slot_with_hash (dst, src->decl,
-                                               VARIABLE_HASH_VAL (src->decl),
-                                               INSERT);
-  var = pool_alloc (var_pool);
-  var->decl = src->decl;
-  var->n_var_parts = src->n_var_parts;
-  *dstp = (void *) var;
+  new_var = pool_alloc (var_pool);
+  new_var->decl = var->decl;
+  new_var->refcount = 1;
+  var->refcount--;
+  new_var->n_var_parts = var->n_var_parts;
 
   for (i = 0; i < var->n_var_parts; i++)
     {
       location_chain node;
       location_chain *nextp;
 
-      var->var_part[i].offset = src->var_part[i].offset;
-      nextp = &var->var_part[i].loc_chain;
-      for (node = src->var_part[i].loc_chain; node; node = node->next)
+      new_var->var_part[i].offset = var->var_part[i].offset;
+      nextp = &new_var->var_part[i].loc_chain;
+      for (node = var->var_part[i].loc_chain; node; node = node->next)
        {
          location_chain new_lc;
 
@@ -771,12 +781,36 @@ vars_copy_1 (void **slot, void *data)
 
       /* We are at the basic block boundary when copying variable description
         so set the CUR_LOC to be the first element of the chain.  */
-      if (var->var_part[i].loc_chain)
-       var->var_part[i].cur_loc = var->var_part[i].loc_chain->loc;
+      if (new_var->var_part[i].loc_chain)
+       new_var->var_part[i].cur_loc = new_var->var_part[i].loc_chain->loc;
       else
-       var->var_part[i].cur_loc = NULL;
+       new_var->var_part[i].cur_loc = NULL;
     }
 
+  slot = htab_find_slot_with_hash (set->vars, new_var->decl,
+                                  VARIABLE_HASH_VAL (new_var->decl),
+                                  INSERT);
+  *slot = new_var;
+  return new_var;
+}
+
+/* Add a variable from *SLOT to hash table DATA and increase its reference
+   count.  */
+
+static int
+vars_copy_1 (void **slot, void *data)
+{
+  htab_t dst = (htab_t) data;
+  variable src, *dstp;
+
+  src = *(variable *) slot;
+  src->refcount++;
+
+  dstp = (variable *) htab_find_slot_with_hash (dst, src->decl,
+                                               VARIABLE_HASH_VAL (src->decl),
+                                               INSERT);
+  *dstp = src;
+
   /* Continue traversing the hash table.  */
   return 1;
 }
@@ -972,9 +1006,37 @@ variable_union (void **slot, void *data)
                                                INSERT);
   if (!*dstp)
     {
-      *dstp = dst = pool_alloc (var_pool);
-      dst->decl = src->decl;
-      dst->n_var_parts = 0;
+      src->refcount++;
+
+      /* If CUR_LOC of some variable part is not the first element of
+        the location chain we are going to change it so we have to make
+        a copy of the variable.  */
+      for (k = 0; k < src->n_var_parts; k++)
+       {
+         if (src->var_part[k].loc_chain)
+           {
+#ifdef ENABLE_CHECKING
+             if (src->var_part[k].cur_loc == NULL)
+               abort ();
+#endif
+             if (src->var_part[k].cur_loc != src->var_part[k].loc_chain->loc)
+               break;
+           }
+#ifdef ENABLE_CHECKING
+         else
+           {
+             if (src->var_part[k].cur_loc != NULL)
+               abort ();
+           }
+#endif
+       }
+      if (k < src->n_var_parts)
+       unshare_variable (set, src);
+      else
+       *dstp = src;
+
+      /* Continue traversing the hash table.  */
+      return 1;
     }
   else
     dst = *dstp;
@@ -998,10 +1060,8 @@ variable_union (void **slot, void *data)
       else
        j++;
     }
-  if (i < src->n_var_parts)
-    k += src->n_var_parts - i;
-  if (j < dst->n_var_parts)
-    k += dst->n_var_parts - j;
+  k += src->n_var_parts - i;
+  k += dst->n_var_parts - j;
 #ifdef ENABLE_CHECKING
   /* We track only variables whose size is <= MAX_VAR_PARTS bytes
      thus there are at most MAX_VAR_PARTS different offsets.  */
@@ -1009,13 +1069,16 @@ variable_union (void **slot, void *data)
     abort ();
 #endif
 
+  if (dst->refcount > 1 && dst->n_var_parts != k)
+    dst = unshare_variable (set, dst);
+
   i = src->n_var_parts - 1;
   j = dst->n_var_parts - 1;
   dst->n_var_parts = k;
 
   for (k--; k >= 0; k--)
     {
-      location_chain node;
+      location_chain node, node2;
 
       if (i >= 0 && j >= 0
          && src->var_part[i].offset == dst->var_part[j].offset)
@@ -1026,7 +1089,26 @@ variable_union (void **slot, void *data)
          int dst_l, src_l;
          int ii, jj, n;
          struct variable_union_info *vui;
-         
+
+         /* If DST is shared compare the location chains.
+            If they are different we will modify the chain in DST with
+            high probability so make a copy of DST.  */
+         if (dst->refcount > 1)
+           {
+             for (node = src->var_part[i].loc_chain,
+                  node2 = dst->var_part[j].loc_chain; node && node2;
+                  node = node->next, node2 = node2->next)
+               {
+                 if (!((GET_CODE (node2->loc) == REG
+                        && GET_CODE (node->loc) == REG
+                        && REGNO (node2->loc) == REGNO (node->loc))
+                       || rtx_equal_p (node2->loc, node->loc)))
+                   break;
+               }
+             if (node || node2)
+               dst = unshare_variable (set, dst);
+           }
+
          src_l = 0;
          for (node = src->var_part[i].loc_chain; node; node = node->next)
            src_l++;
@@ -1187,6 +1269,9 @@ variable_different_p (variable var1, variable var2)
 {
   int i;
 
+  if (var1 == var2)
+    return false;
+
   if (var1->n_var_parts != var2->n_var_parts)
     return true;
 
@@ -1791,6 +1876,7 @@ variable_was_changed (variable var, htab_t htab)
 
          empty_var = pool_alloc (var_pool);
          empty_var->decl = var->decl;
+         empty_var->refcount = 1;
          empty_var->n_var_parts = 0;
          *slot = empty_var;
 
@@ -1843,7 +1929,12 @@ set_frame_base_location (dataflow_set *set, rtx loc)
     abort ();
 #endif
 
+  /* If frame_base_decl is shared unshare it first.  */
+  if (var->refcount > 1)
+    var = unshare_variable (set, var);
+
   var->var_part[0].loc_chain->loc = loc;
+  var->var_part[0].cur_loc = loc;
   variable_was_changed (var, set->vars);
 }
 
@@ -1867,6 +1958,7 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
       /* Create new variable information.  */
       var = pool_alloc (var_pool);
       var->decl = decl;
+      var->refcount = 1;
       var->n_var_parts = 1;
       var->var_part[0].offset = offset;
       var->var_part[0].loc_chain = NULL;
@@ -1891,9 +1983,33 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
        }
       pos = low;
 
-      if (pos == var->n_var_parts || var->var_part[pos].offset != offset)
+      if (pos < var->n_var_parts && var->var_part[pos].offset == offset)
        {
-         /* We have not find the location part, new one will be created.  */
+         node = var->var_part[pos].loc_chain;
+
+         if (node
+             && ((GET_CODE (node->loc) == REG && GET_CODE (loc) == REG
+                  && REGNO (node->loc) == REGNO (loc))
+                 || rtx_equal_p (node->loc, loc)))
+           {
+             /* LOC is in the beginning of the chain so we have nothing
+                to do.  */
+             return;
+           }
+         else
+           {
+             /* We have to make a copy of a shared variable.  */
+             if (var->refcount > 1)
+               var = unshare_variable (set, var);
+           }
+       }
+      else
+       {
+         /* We have not found the location part, new one will be created.  */
+
+         /* We have to make a copy of the shared variable.  */
+         if (var->refcount > 1)
+           var = unshare_variable (set, var);
 
 #ifdef ENABLE_CHECKING
          /* We track only variables whose size is <= MAX_VAR_PARTS bytes
@@ -1914,7 +2030,7 @@ set_variable_part (dataflow_set *set, rtx loc, tree decl, HOST_WIDE_INT offset)
        }
     }
 
-  /* Delete the location from list.  */
+  /* Delete the location from the list.  */
   nextp = &var->var_part[pos].loc_chain;
   for (node = var->var_part[pos].loc_chain; node; node = next)
     {
@@ -1981,6 +2097,23 @@ delete_variable_part (dataflow_set *set, rtx loc, tree decl,
          location_chain *nextp;
          bool changed;
 
+         if (var->refcount > 1)
+           {
+             /* If the variable contains the location part we have to
+                make a copy of the variable.  */
+             for (node = var->var_part[pos].loc_chain; node;
+                  node = node->next)
+               {
+                 if ((GET_CODE (node->loc) == REG && GET_CODE (loc) == REG
+                      && REGNO (node->loc) == REGNO (loc))
+                     || rtx_equal_p (node->loc, loc))
+                   {
+                     var = unshare_variable (set, var);
+                     break;
+                   }
+               }
+           }
+
          /* Delete the location part.  */
          nextp = &var->var_part[pos].loc_chain;
          for (node = *nextp; node; node = next)
@@ -2149,6 +2282,7 @@ emit_notes_for_differences_1 (void **slot, void *data)
 
       empty_var = pool_alloc (var_pool);
       empty_var->decl = old_var->decl;
+      empty_var->refcount = 1;
       empty_var->n_var_parts = 0;
       variable_was_changed (empty_var, NULL);
     }
@@ -2357,7 +2491,7 @@ vt_add_function_parameters (void)
       rtx incoming = DECL_INCOMING_RTL (parm);
       tree decl;
       HOST_WIDE_INT offset;
-      dataflow_set *in, *out;
+      dataflow_set *out;
 
       if (TREE_CODE (parm) != PARM_DECL)
        continue;
@@ -2386,7 +2520,6 @@ vt_add_function_parameters (void)
       incoming = eliminate_regs (incoming, 0, NULL_RTX);
       if (!frame_pointer_needed && GET_CODE (incoming) == MEM)
        incoming = adjust_stack_reference (incoming, -stack_adjust);
-      in = &VTI (ENTRY_BLOCK_PTR)->in;
       out = &VTI (ENTRY_BLOCK_PTR)->out;
 
       if (GET_CODE (incoming) == REG)
@@ -2395,16 +2528,12 @@ vt_add_function_parameters (void)
          if (REGNO (incoming) >= FIRST_PSEUDO_REGISTER)
            abort ();
 #endif
-         attrs_list_insert (&in->regs[REGNO (incoming)],
-                            parm, offset, incoming);
          attrs_list_insert (&out->regs[REGNO (incoming)],
                             parm, offset, incoming);
-         set_variable_part (in, incoming, parm, offset);
          set_variable_part (out, incoming, parm, offset);
        }
       else if (GET_CODE (incoming) == MEM)
        {
-         set_variable_part (in, incoming, parm, offset);
          set_variable_part (out, incoming, parm, offset);
        }
     }
@@ -2564,7 +2693,6 @@ vt_initialize (void)
 
       /* Set its initial "location".  */
       base = gen_rtx_MEM (Pmode, stack_pointer_rtx);
-      set_variable_part (&VTI (ENTRY_BLOCK_PTR)->in, base, frame_base_decl, 0);
       set_variable_part (&VTI (ENTRY_BLOCK_PTR)->out, base, frame_base_decl, 0);
     }
   else