OSDN Git Service

PR fortran/26025
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-live.c
index cbd36f1..a5fe403 100644 (file)
@@ -38,6 +38,7 @@ Boston, MA 02110-1301, USA.  */
 #include "tree-dump.h"
 #include "tree-ssa-live.h"
 #include "toplev.h"
+#include "vecprim.h"
 
 static void live_worklist (tree_live_info_p, int *, int);
 static tree_live_info_p new_tree_live_info (var_map);
@@ -286,6 +287,7 @@ change_partition_var (var_map map, tree var, int part)
     map->partition_to_var[map->compact_to_partition[part]] = var;
 }
 
+static inline void mark_all_vars_used (tree *);
 
 /* Helper function for mark_all_vars_used, called via walk_tree.  */
 
@@ -295,6 +297,20 @@ mark_all_vars_used_1 (tree *tp, int *walk_subtrees,
 {
   tree t = *tp;
 
+  if (TREE_CODE (t) == SSA_NAME)
+    t = SSA_NAME_VAR (t);
+
+  /* Ignore TREE_ORIGINAL for TARGET_MEM_REFS, as well as other
+     fields that do not contain vars.  */
+  if (TREE_CODE (t) == TARGET_MEM_REF)
+    {
+      mark_all_vars_used (&TMR_SYMBOL (t));
+      mark_all_vars_used (&TMR_BASE (t));
+      mark_all_vars_used (&TMR_INDEX (t));
+      *walk_subtrees = 0;
+      return NULL;
+    }
+
   /* Only need to mark VAR_DECLS; parameters and return results are not
      eliminated as unused.  */
   if (TREE_CODE (t) == VAR_DECL)
@@ -315,6 +331,72 @@ mark_all_vars_used (tree *expr_p)
   walk_tree (expr_p, mark_all_vars_used_1, NULL, NULL);
 }
 
+
+/* Remove local variables that are not referenced in the IL.  */
+
+void
+remove_unused_locals (void)
+{
+  basic_block bb;
+  tree t, *cell;
+
+  /* Assume all locals are unused.  */
+  for (t = cfun->unexpanded_var_list; t; t = TREE_CHAIN (t))
+    {
+      tree var = TREE_VALUE (t);
+      if (TREE_CODE (var) != FUNCTION_DECL
+         && var_ann (var))
+       var_ann (var)->used = false;
+    }
+
+  /* Walk the CFG marking all referenced symbols.  */
+  FOR_EACH_BB (bb)
+    {
+      block_stmt_iterator bsi;
+      tree phi, def;
+
+      /* Walk the statements.  */
+      for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+       mark_all_vars_used (bsi_stmt_ptr (bsi));
+
+      for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
+        {
+          use_operand_p arg_p;
+          ssa_op_iter i;
+
+         /* No point processing globals.  */
+         if (is_global_var (SSA_NAME_VAR (PHI_RESULT (phi))))
+           continue;
+
+          def = PHI_RESULT (phi);
+          mark_all_vars_used (&def);
+
+          FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_ALL_USES)
+            {
+             tree arg = USE_FROM_PTR (arg_p);
+             mark_all_vars_used (&arg);
+            }
+        }
+    }
+
+  /* Remove unmarked vars and clear used flag.  */
+  for (cell = &cfun->unexpanded_var_list; *cell; )
+    {
+      tree var = TREE_VALUE (*cell);
+      var_ann_t ann;
+
+      if (TREE_CODE (var) != FUNCTION_DECL
+         && (!(ann = var_ann (var))
+             || !ann->used))
+       {
+         *cell = TREE_CHAIN (*cell);
+         continue;
+       }
+
+      cell = &TREE_CHAIN (*cell);
+    }
+}
+
 /* This function looks through the program and uses FLAGS to determine what 
    SSA versioned variables are given entries in a new partition table.  This
    new partition map is returned.  */
@@ -329,18 +411,15 @@ create_ssa_var_map (int flags)
   var_map map;
   ssa_op_iter iter;
 #ifdef ENABLE_CHECKING
-  sbitmap used_in_real_ops;
-  sbitmap used_in_virtual_ops;
+  bitmap used_in_real_ops;
+  bitmap used_in_virtual_ops;
 #endif
 
   map = init_var_map (num_ssa_names + 1);
 
 #ifdef ENABLE_CHECKING
-  used_in_real_ops = sbitmap_alloc (num_referenced_vars);
-  sbitmap_zero (used_in_real_ops);
-
-  used_in_virtual_ops = sbitmap_alloc (num_referenced_vars);
-  sbitmap_zero (used_in_virtual_ops);
+  used_in_real_ops = BITMAP_ALLOC (NULL);
+  used_in_virtual_ops = BITMAP_ALLOC (NULL);
 #endif
 
   if (flags & SSA_VAR_MAP_REF_COUNT)
@@ -353,6 +432,7 @@ create_ssa_var_map (int flags)
   FOR_EACH_BB (bb)
     {
       tree phi, arg;
+
       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
        {
          int i;
@@ -377,7 +457,7 @@ create_ssa_var_map (int flags)
              register_ssa_partition (map, use, true);
 
 #ifdef ENABLE_CHECKING
-             SET_BIT (used_in_real_ops, var_ann (SSA_NAME_VAR (use))->uid);
+             bitmap_set_bit (used_in_real_ops, DECL_UID (SSA_NAME_VAR (use)));
 #endif
            }
 
@@ -386,7 +466,7 @@ create_ssa_var_map (int flags)
              register_ssa_partition (map, dest, false);
 
 #ifdef ENABLE_CHECKING
-             SET_BIT (used_in_real_ops, var_ann (SSA_NAME_VAR (dest))->uid);
+             bitmap_set_bit (used_in_real_ops, DECL_UID (SSA_NAME_VAR (dest)));
 #endif
            }
 
@@ -395,7 +475,8 @@ create_ssa_var_map (int flags)
          FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, 
                                     SSA_OP_VIRTUAL_USES | SSA_OP_VMUSTDEF)
            {
-             SET_BIT (used_in_virtual_ops, var_ann (SSA_NAME_VAR (use))->uid);
+             bitmap_set_bit (used_in_virtual_ops, 
+                             DECL_UID (SSA_NAME_VAR (use)));
            }
 
 #endif /* ENABLE_CHECKING */
@@ -407,21 +488,21 @@ create_ssa_var_map (int flags)
 #if defined ENABLE_CHECKING
   {
     unsigned i;
-    sbitmap both = sbitmap_alloc (num_referenced_vars);
-    sbitmap_a_and_b (both, used_in_real_ops, used_in_virtual_ops);
-    if (sbitmap_first_set_bit (both) >= 0)
+    bitmap both = BITMAP_ALLOC (NULL);
+    bitmap_and (both, used_in_real_ops, used_in_virtual_ops);
+    if (!bitmap_empty_p (both))
       {
-       sbitmap_iterator sbi;
+       bitmap_iterator bi;
 
-       EXECUTE_IF_SET_IN_SBITMAP (both, 0, i, sbi)
+       EXECUTE_IF_SET_IN_BITMAP (both, 0, i, bi)
          fprintf (stderr, "Variable %s used in real and virtual operands\n",
                   get_name (referenced_var (i)));
        internal_error ("SSA corruption");
       }
 
-    sbitmap_free (used_in_real_ops);
-    sbitmap_free (used_in_virtual_ops);
-    sbitmap_free (both);
+    BITMAP_FREE (used_in_real_ops);
+    BITMAP_FREE (used_in_virtual_ops);
+    BITMAP_FREE (both);
   }
 #endif
 
@@ -629,7 +710,7 @@ calculate_live_on_entry (var_map map)
        }
     }
 
-  stack = xmalloc (sizeof (int) * last_basic_block);
+  stack = XNEWVEC (int, last_basic_block);
   EXECUTE_IF_SET_IN_BITMAP (live->global, 0, i, bi)
     {
       live_worklist (live, stack, i);
@@ -801,7 +882,7 @@ tpa_init (var_map map)
 
   x = MAX (40, (num_partitions / 20));
   tpa->trees = VEC_alloc (tree, heap, x);
-  VARRAY_INT_INIT (tpa->first_partition, x, "first_partition");
+  tpa->first_partition = VEC_alloc (int, heap, x);
 
   return tpa;
 
@@ -818,7 +899,8 @@ tpa_remove_partition (tpa_p tpa, int tree_index, int partition_index)
   i = tpa_first_partition (tpa, tree_index);
   if (i == partition_index)
     {
-      VARRAY_INT (tpa->first_partition, tree_index) = tpa->next_partition[i];
+      VEC_replace (int, tpa->first_partition, tree_index,
+                  tpa->next_partition[i]);
     }
   else
     {
@@ -843,6 +925,7 @@ tpa_delete (tpa_p tpa)
     return;
 
   VEC_free (tree, heap, tpa->trees);
+  VEC_free (int, heap, tpa->first_partition);
   free (tpa->partition_to_tree_map);
   free (tpa->next_partition);
   free (tpa);
@@ -877,20 +960,20 @@ tpa_compact (tpa_p tpa)
       if (tpa_next_partition (tpa, first) == NO_PARTITION)
         {
          swap_t = VEC_index (tree, tpa->trees, last);
-         swap_i = VARRAY_INT (tpa->first_partition, last);
+         swap_i = VEC_index (int, tpa->first_partition, last);
 
          /* Update the last entry. Since it is known to only have one
             partition, there is nothing else to update.  */
          VEC_replace (tree, tpa->trees, last,
                       VEC_index (tree, tpa->trees, x));
-         VARRAY_INT (tpa->first_partition, last) 
-           = VARRAY_INT (tpa->first_partition, x);
+         VEC_replace (int, tpa->first_partition, last,
+                      VEC_index (int, tpa->first_partition, x));
          tpa->partition_to_tree_map[tpa_first_partition (tpa, last)] = last;
 
          /* Since this list is known to have more than one partition, update
             the list owner entries.  */
          VEC_replace (tree, tpa->trees, x, swap_t);
-         VARRAY_INT (tpa->first_partition, x) = swap_i;
+         VEC_replace (int, tpa->first_partition, x, swap_i);
          for (y = tpa_first_partition (tpa, x); 
               y != NO_PARTITION; 
               y = tpa_next_partition (tpa, y))
@@ -960,16 +1043,16 @@ root_var_init (var_map map)
       ann = var_ann (t);
       if (ann->root_var_processed)
         {
-         rv->next_partition[p] = VARRAY_INT (rv->first_partition, 
-                                             VAR_ANN_ROOT_INDEX (ann));
-         VARRAY_INT (rv->first_partition, VAR_ANN_ROOT_INDEX (ann)) = p;
+         rv->next_partition[p] = VEC_index (int, rv->first_partition, 
+                                            VAR_ANN_ROOT_INDEX (ann));
+         VEC_replace (int, rv->first_partition, VAR_ANN_ROOT_INDEX (ann), p);
        }
       else
         {
          ann->root_var_processed = 1;
          VAR_ANN_ROOT_INDEX (ann) = rv->num_trees++;
          VEC_safe_push (tree, heap, rv->trees, t);
-         VARRAY_PUSH_INT (rv->first_partition, p);
+         VEC_safe_push (int, heap, rv->first_partition, p);
        }
       rv->partition_to_tree_map[p] = VAR_ANN_ROOT_INDEX (ann);
     }
@@ -998,13 +1081,13 @@ type_var_init (var_map map)
   tree t;
   sbitmap seen;
 
-  seen = sbitmap_alloc (num_partitions);
-  sbitmap_zero (seen);
-
   tv = tpa_init (map);
   if (!tv)
     return NULL;
 
+  seen = sbitmap_alloc (num_partitions);
+  sbitmap_zero (seen);
+
   for (x = num_partitions - 1; x >= 0; x--)
     {
       t = partition_to_var (map, x);
@@ -1039,12 +1122,12 @@ type_var_init (var_map map)
         {
          tv->num_trees++;
          VEC_safe_push (tree, heap, tv->trees, t);
-         VARRAY_PUSH_INT (tv->first_partition, p);
+         VEC_safe_push (int, heap, tv->first_partition, p);
        }
       else
         {
-         tv->next_partition[p] = VARRAY_INT (tv->first_partition, y);
-         VARRAY_INT (tv->first_partition, y) = p;
+         tv->next_partition[p] = VEC_index (int, tv->first_partition, y);
+         VEC_replace (int, tv->first_partition, y, p);
        }
       tv->partition_to_tree_map[p] = y;
     }
@@ -1135,11 +1218,30 @@ find_partition_pair (coalesce_list_p cl, int p1, int p2, bool create)
   return node;
 }
 
+/* Return cost of execution of copy instruction with FREQUENCY
+   possibly on CRITICAL edge and in HOT basic block.  */
+int
+coalesce_cost (int frequency, bool hot, bool critical)
+{
+  /* Base costs on BB frequencies bounded by 1.  */
+  int cost = frequency;
+
+  if (!cost)
+    cost = 1;
+  if (optimize_size || hot)
+    cost = 1;
+  /* Inserting copy on critical edge costs more
+     than inserting it elsewhere.  */
+  if (critical)
+    cost *= 2;
+  return cost;
+}
 
 /* Add a potential coalesce between P1 and P2 in CL with a cost of VALUE.  */
 
 void 
-add_coalesce (coalesce_list_p cl, int p1, int p2, int value)
+add_coalesce (coalesce_list_p cl, int p1, int p2,
+             int value)
 {
   partition_pair_p node;
 
@@ -1195,7 +1297,7 @@ sort_coalesce_list (coalesce_list_p cl)
   /* Only call qsort if there are more than 2 items.  */
   if (num > 2)
     {
-      list = xmalloc (sizeof (partition_pair_p) * num);
+      list = XNEWVEC (partition_pair_p, num);
       count = 0;
       for (p = chain; p != NULL; p = p->next)
        list[count++] = p;
@@ -1286,9 +1388,6 @@ add_conflicts_if_valid (tpa_p tpa, conflict_graph graph,
     }
 }
 
-DEF_VEC_I(int);
-DEF_VEC_ALLOC_I(int,heap);
-
 /* Return a conflict graph for the information contained in LIVE_INFO.  Only
    conflicts between items in the same TPA list are added.  If optional 
    coalesce list CL is passed in, any copies encountered are added.  */
@@ -1316,8 +1415,8 @@ build_tree_conflict_graph (tree_live_info_p liveinfo, tpa_p tpa,
 
   live = BITMAP_ALLOC (NULL);
 
-  partition_link = xcalloc (num_var_partitions (map) + 1, sizeof (int));
-  tpa_nodes = xcalloc (tpa_num_trees (tpa), sizeof (int));
+  partition_link = XCNEWVEC (int, num_var_partitions (map) + 1);
+  tpa_nodes = XCNEWVEC (int, tpa_num_trees (tpa));
   tpa_to_clear = VEC_alloc (int, heap, 50);
 
   FOR_EACH_BB (bb)
@@ -1373,7 +1472,9 @@ build_tree_conflict_graph (tree_live_info_p liveinfo, tpa_p tpa,
                  if (bit)
                    bitmap_set_bit (live, p2);
                  if (cl)
-                   add_coalesce (cl, p1, p2, 1);
+                   add_coalesce (cl, p1, p2,
+                                 coalesce_cost (bb->frequency,
+                                                maybe_hot_bb_p (bb), false));
                  set_if_valid (map, live, rhs);
                }
            }