tree-outof-ssa.c (tree-ssa.h, tree-dfa.h): Include header files.
authorBin Cheng <bin.cheng@arm.com>
Fri, 25 May 2018 10:35:44 +0000 (10:35 +0000)
committerBin Cheng <amker@gcc.gnu.org>
Fri, 25 May 2018 10:35:44 +0000 (10:35 +0000)
* tree-outof-ssa.c (tree-ssa.h, tree-dfa.h): Include header files.
(create_default_def, for_all_parms): Moved from tree-ssa-coalesce.c.
(parm_default_def_partition_arg): Ditto.
(set_parm_default_def_partition): Ditto.
(get_parm_default_def_partitions): Ditto and make it static.
(get_undefined_value_partitions): Ditto and make it static.
(remove_ssa_form): Refactor call to init_var_map here.
* tree-ssa-coalesce.c (build_ssa_conflict_graph): Support live range
computation for loop region.
(coalesce_partitions, compute_optimized_partition_bases): Ditto.
(register_default_def): Delete.
(for_all_parms, create_default_def): Move to tree-outof-ssa.c.
(parm_default_def_partition_arg): Ditto.
(set_parm_default_def_partition): Ditto.
(get_parm_default_def_partitions): Ditto and make it static.
(get_undefined_value_partitions): Ditto and make it static.
(coalesce_with_default, coalesce_with_default): Update comment.
(create_coalesce_list_for_region): New func factored out from
create_outofssa_var_map.
(populate_coalesce_list_for_outofssa): New func factored out from
create_outofssa_var_map and coalesce_ssa_name.
(create_outofssa_var_map): Delete.
(coalesce_ssa_name): Refactor to support live range computation.
* tree-ssa-coalesce.h (coalesce_ssa_name): Change decl.
(get_parm_default_def_partitions): Delete.
(get_undefined_value_partitions): Ditto.
* tree-ssa-live.c (init_var_map, delete_var_map): Support live range
computation for loop region.
(new_tree_live_info, loe_visit_block): Ditto.
(live_worklist, set_var_live_on_entry): Ditto.
(calculate_live_on_exit, verify_live_on_entry): Ditto.
* tree-ssa-live.h (struct _var_map): New fields.
(init_var_map): Change decl.
(region_contains_p): New.

From-SVN: r260747

gcc/ChangeLog
gcc/tree-outof-ssa.c
gcc/tree-ssa-coalesce.c
gcc/tree-ssa-coalesce.h
gcc/tree-ssa-live.c
gcc/tree-ssa-live.h

index 4ce52ef538d8ce42109fc2ccbb57a1541305794b..06e6591aa2199ace2056658c1b91f2a1cebe093c 100644 (file)
@@ -1,3 +1,40 @@
+2018-05-25  Bin Cheng  <bin.cheng@arm.com>
+
+       * tree-outof-ssa.c (tree-ssa.h, tree-dfa.h): Include header files.
+       (create_default_def, for_all_parms): Moved from tree-ssa-coalesce.c.
+       (parm_default_def_partition_arg): Ditto.
+       (set_parm_default_def_partition): Ditto.
+       (get_parm_default_def_partitions): Ditto and make it static.
+       (get_undefined_value_partitions): Ditto and make it static.
+       (remove_ssa_form): Refactor call to init_var_map here.
+       * tree-ssa-coalesce.c (build_ssa_conflict_graph): Support live range
+       computation for loop region.
+       (coalesce_partitions, compute_optimized_partition_bases): Ditto.
+       (register_default_def): Delete.
+       (for_all_parms, create_default_def): Move to tree-outof-ssa.c.
+       (parm_default_def_partition_arg): Ditto.
+       (set_parm_default_def_partition): Ditto.
+       (get_parm_default_def_partitions): Ditto and make it static.
+       (get_undefined_value_partitions): Ditto and make it static.
+       (coalesce_with_default, coalesce_with_default): Update comment.
+       (create_coalesce_list_for_region): New func factored out from
+       create_outofssa_var_map.
+       (populate_coalesce_list_for_outofssa): New func factored out from
+       create_outofssa_var_map and coalesce_ssa_name.
+       (create_outofssa_var_map): Delete.
+       (coalesce_ssa_name): Refactor to support live range computation.
+       * tree-ssa-coalesce.h (coalesce_ssa_name): Change decl.
+       (get_parm_default_def_partitions): Delete.
+       (get_undefined_value_partitions): Ditto.
+       * tree-ssa-live.c (init_var_map, delete_var_map): Support live range
+       computation for loop region.
+       (new_tree_live_info, loe_visit_block): Ditto.
+       (live_worklist, set_var_live_on_entry): Ditto.
+       (calculate_live_on_exit, verify_live_on_entry): Ditto.
+       * tree-ssa-live.h (struct _var_map): New fields.
+       (init_var_map): Change decl.
+       (region_contains_p): New.
+
 2018-05-25  Bin Cheng  <bin.cheng@arm.com>
 
        * tree-ssa-live.h (live_merge_and_clear): Delete.
index 59bdcd6fadd73204a762c367024e598ae74b2952..3f880ef7382ff2678797ce5fb277a7b250118303 100644 (file)
@@ -27,10 +27,12 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimple.h"
 #include "cfghooks.h"
 #include "ssa.h"
+#include "tree-ssa.h"
 #include "memmodel.h"
 #include "emit-rtl.h"
 #include "gimple-pretty-print.h"
 #include "diagnostic-core.h"
+#include "tree-dfa.h"
 #include "stor-layout.h"
 #include "cfgrtl.h"
 #include "cfganal.h"
@@ -888,6 +890,102 @@ rewrite_trees (var_map map)
     }
 }
 
+/* Create a default def for VAR.  */
+
+static void
+create_default_def (tree var, void *arg ATTRIBUTE_UNUSED)
+{
+  if (!is_gimple_reg (var))
+    return;
+
+  tree ssa = get_or_create_ssa_default_def (cfun, var);
+  gcc_assert (ssa);
+}
+
+/* Call CALLBACK for all PARM_DECLs and RESULT_DECLs for which
+   assign_parms may ask for a default partition.  */
+
+static void
+for_all_parms (void (*callback)(tree var, void *arg), void *arg)
+{
+  for (tree var = DECL_ARGUMENTS (current_function_decl); var;
+       var = DECL_CHAIN (var))
+    callback (var, arg);
+  if (!VOID_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
+    callback (DECL_RESULT (current_function_decl), arg);
+  if (cfun->static_chain_decl)
+    callback (cfun->static_chain_decl, arg);
+}
+
+/* We need to pass two arguments to set_parm_default_def_partition,
+   but for_all_parms only supports one.  Use a pair.  */
+
+typedef std::pair<var_map, bitmap> parm_default_def_partition_arg;
+
+/* Set in ARG's PARTS bitmap the bit corresponding to the partition in
+   ARG's MAP containing VAR's default def.  */
+
+static void
+set_parm_default_def_partition (tree var, void *arg_)
+{
+  parm_default_def_partition_arg *arg = (parm_default_def_partition_arg *)arg_;
+  var_map map = arg->first;
+  bitmap parts = arg->second;
+
+  if (!is_gimple_reg (var))
+    return;
+
+  tree ssa = ssa_default_def (cfun, var);
+  gcc_assert (ssa);
+
+  int version = var_to_partition (map, ssa);
+  gcc_assert (version != NO_PARTITION);
+
+  bool changed = bitmap_set_bit (parts, version);
+  gcc_assert (changed);
+}
+
+/* Allocate and return a bitmap that has a bit set for each partition
+   that contains a default def for a parameter.  */
+
+static bitmap
+get_parm_default_def_partitions (var_map map)
+{
+  bitmap parm_default_def_parts = BITMAP_ALLOC (NULL);
+
+  parm_default_def_partition_arg
+    arg = std::make_pair (map, parm_default_def_parts);
+
+  for_all_parms (set_parm_default_def_partition, &arg);
+
+  return parm_default_def_parts;
+}
+
+/* Allocate and return a bitmap that has a bit set for each partition
+   that contains an undefined value.  */
+
+static bitmap
+get_undefined_value_partitions (var_map map)
+{
+  bitmap undefined_value_parts = BITMAP_ALLOC (NULL);
+
+  for (unsigned int i = 1; i < num_ssa_names; i++)
+    {
+      tree var = ssa_name (i);
+      if (var
+         && !virtual_operand_p (var)
+         && !has_zero_uses (var)
+         && ssa_undefined_value_p (var))
+       {
+         const int p = var_to_partition (map, var);
+         if (p != NO_PARTITION)
+           bitmap_set_bit (undefined_value_parts, p);
+       }
+    }
+
+  return undefined_value_parts;
+}
+
 /* Given the out-of-ssa info object SA (with prepared partitions)
    eliminate all phi nodes in all basic blocks.  Afterwards no
    basic block will have phi nodes anymore and there are possibly
@@ -945,7 +1043,9 @@ remove_ssa_form (bool perform_ter, struct ssaexpand *sa)
   bitmap values = NULL;
   var_map map;
 
-  map = coalesce_ssa_name ();
+  for_all_parms (create_default_def, NULL);
+  map = init_var_map (num_ssa_names);
+  coalesce_ssa_name (map);
 
   /* Return to viewing the variable list as just all reference variables after
      coalescing has been performed.  */
index 5cc0acad3954b5b64a1b191ff6a640efa16b0e5f..e4f576fbc19900a2c93e7f30d173715dcc0c1a06 100644 (file)
@@ -879,7 +879,7 @@ build_ssa_conflict_graph (tree_live_info_p liveinfo)
 
   live = new_live_track (map);
 
-  FOR_EACH_BB_FN (bb, cfun)
+  for (unsigned i = 0; liveinfo->map->vec_bbs.iterate (i, &bb); ++i)
     {
       /* Start with live on exit temporaries.  */
       live_track_init (live, live_on_exit (liveinfo, bb));
@@ -944,6 +944,8 @@ build_ssa_conflict_graph (tree_live_info_p liveinfo)
        {
          gphi *phi = gsi.phi ();
          tree result = PHI_RESULT (phi);
+         if (virtual_operand_p (result))
+           continue;
          if (live_track_live_p (live, result))
            live_track_process_def (live, result, graph);
        }
@@ -1012,48 +1014,9 @@ fail_abnormal_edge_coalesce (int x, int y)
   internal_error ("SSA corruption");
 }
 
-/* Call CALLBACK for all PARM_DECLs and RESULT_DECLs for which
-   assign_parms may ask for a default partition.  */
-
-static void
-for_all_parms (void (*callback)(tree var, void *arg), void *arg)
-{
-  for (tree var = DECL_ARGUMENTS (current_function_decl); var;
-       var = DECL_CHAIN (var))
-    callback (var, arg);
-  if (!VOID_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))))
-    callback (DECL_RESULT (current_function_decl), arg);
-  if (cfun->static_chain_decl)
-    callback (cfun->static_chain_decl, arg);
-}
-
-/* Create a default def for VAR.  */
-
-static void
-create_default_def (tree var, void *arg ATTRIBUTE_UNUSED)
-{
-  if (!is_gimple_reg (var))
-    return;
-
-  tree ssa = get_or_create_ssa_default_def (cfun, var);
-  gcc_assert (ssa);
-}
-
-/* Register VAR's default def in MAP.  */
-
-static void
-register_default_def (tree var, void *arg ATTRIBUTE_UNUSED)
-{
-  if (!is_gimple_reg (var))
-    return;
-
-  tree ssa = ssa_default_def (cfun, var);
-  gcc_assert (ssa);
-}
-
 /* If VAR is an SSA_NAME associated with a PARM_DECL or a RESULT_DECL,
    and the DECL's default def is unused (i.e., it was introduced by
-   create_default_def), mark VAR and the default def for
+   create_default_def for out-of-ssa), mark VAR and the default def for
    coalescing.  */
 
 static void
@@ -1070,32 +1033,25 @@ coalesce_with_default (tree var, coalesce_list *cl, bitmap used_in_copy)
 
   add_cost_one_coalesce (cl, SSA_NAME_VERSION (ssa), SSA_NAME_VERSION (var));
   bitmap_set_bit (used_in_copy, SSA_NAME_VERSION (var));
-  /* Default defs will have their used_in_copy bits set at the end of
-     create_outofssa_var_map.  */
+  /* Default defs will have their used_in_copy bits set at the beginning of
+     populate_coalesce_list_for_outofssa.  */
 }
 
-/* This function creates a var_map for the current function as well as creating
-   a coalesce list for use later in the out of ssa process.  */
 
-static var_map
-create_outofssa_var_map (coalesce_list *cl, bitmap used_in_copy)
+/* Given var_map MAP for a region, this function creates and returns a coalesce
+   list as well as recording related ssa names in USED_IN_COPIES for use later
+   in the out-of-ssa or live range computation process.  */
+
+static coalesce_list *
+create_coalesce_list_for_region (var_map map, bitmap used_in_copy)
 {
   gimple_stmt_iterator gsi;
   basic_block bb;
-  tree var;
+  coalesce_list *cl = create_coalesce_list ();
   gimple *stmt;
-  tree first;
-  var_map map;
   int v1, v2, cost;
-  unsigned i;
-
-  for_all_parms (create_default_def, NULL);
-
-  map = init_var_map (num_ssa_names);
-
-  for_all_parms (register_default_def, NULL);
 
-  FOR_EACH_BB_FN (bb, cfun)
+  for (unsigned j = 0; map->vec_bbs.iterate (j, &bb); ++j)
     {
       tree arg;
 
@@ -1110,6 +1066,8 @@ create_outofssa_var_map (coalesce_list *cl, bitmap used_in_copy)
          bool saw_copy = false;
 
          res = gimple_phi_result (phi);
+         if (virtual_operand_p (res))
+           continue;
          ver = SSA_NAME_VERSION (res);
 
          /* Register ssa_names and coalesces between the args and the result
@@ -1249,8 +1207,44 @@ create_outofssa_var_map (coalesce_list *cl, bitmap used_in_copy)
        }
     }
 
-  /* Now process result decls and live on entry variables for entry into
-     the coalesce list.  */
+  return cl;
+}
+
+
+/* Hashtable support for storing SSA names hashed by their SSA_NAME_VAR.  */
+
+struct ssa_name_var_hash : nofree_ptr_hash <tree_node>
+{
+  static inline hashval_t hash (const tree_node *);
+  static inline int equal (const tree_node *, const tree_node *);
+};
+
+inline hashval_t
+ssa_name_var_hash::hash (const_tree n)
+{
+  return DECL_UID (SSA_NAME_VAR (n));
+}
+
+inline int
+ssa_name_var_hash::equal (const tree_node *n1, const tree_node *n2)
+{
+  return SSA_NAME_VAR (n1) == SSA_NAME_VAR (n2);
+}
+
+
+/* This function populates coalesce list CL as well as recording related ssa
+   names in USED_IN_COPIES for use later in the out-of-ssa process.  */
+
+static void
+populate_coalesce_list_for_outofssa (coalesce_list *cl, bitmap used_in_copy)
+{
+  tree var;
+  tree first;
+  int v1, v2, cost;
+  unsigned i;
+
+  /* Process result decls and live on entry variables for entry into the
+     coalesce list.  */
   first = NULL_TREE;
   FOR_EACH_SSA_NAME (i, var, cfun)
     {
@@ -1285,7 +1279,46 @@ create_outofssa_var_map (coalesce_list *cl, bitmap used_in_copy)
        }
     }
 
-  return map;
+  /* If this optimization is disabled, we need to coalesce all the
+     names originating from the same SSA_NAME_VAR so debug info
+     remains undisturbed.  */
+  if (!flag_tree_coalesce_vars)
+    {
+      tree a;
+      hash_table<ssa_name_var_hash> ssa_name_hash (10);
+
+      FOR_EACH_SSA_NAME (i, a, cfun)
+       {
+         if (SSA_NAME_VAR (a)
+             && !DECL_IGNORED_P (SSA_NAME_VAR (a))
+             && (!has_zero_uses (a) || !SSA_NAME_IS_DEFAULT_DEF (a)
+                 || !VAR_P (SSA_NAME_VAR (a))))
+           {
+             tree *slot = ssa_name_hash.find_slot (a, INSERT);
+
+             if (!*slot)
+               *slot = a;
+             else
+               {
+                 /* If the variable is a PARM_DECL or a RESULT_DECL, we
+                    _require_ that all the names originating from it be
+                    coalesced, because there must be a single partition
+                    containing all the names so that it can be assigned
+                    the canonical RTL location of the DECL safely.
+                    If in_lto_p, a function could have been compiled
+                    originally with optimizations and only the link
+                    performed at -O0, so we can't actually require it.  */
+                 const int cost
+                   = (TREE_CODE (SSA_NAME_VAR (a)) == VAR_DECL || in_lto_p)
+                     ? MUST_COALESCE_COST - 1 : MUST_COALESCE_COST;
+                 add_coalesce (cl, SSA_NAME_VERSION (a),
+                               SSA_NAME_VERSION (*slot), cost);
+                 bitmap_set_bit (used_in_copy, SSA_NAME_VERSION (a));
+                 bitmap_set_bit (used_in_copy, SSA_NAME_VERSION (*slot));
+               }
+           }
+       }
+    }
 }
 
 
@@ -1384,13 +1417,15 @@ coalesce_partitions (var_map map, ssa_conflicts *graph, coalesce_list *cl,
                 gsi_next (&gsi))
              {
                gphi *phi = gsi.phi ();
+               tree res = PHI_RESULT (phi);
+               if (virtual_operand_p (res))
+                 continue;
                tree arg = PHI_ARG_DEF (phi, e->dest_idx);
                if (SSA_NAME_IS_DEFAULT_DEF (arg)
                    && (!SSA_NAME_VAR (arg)
                        || TREE_CODE (SSA_NAME_VAR (arg)) != PARM_DECL))
                  continue;
 
-               tree res = PHI_RESULT (phi);
                int v1 = SSA_NAME_VERSION (res);
                int v2 = SSA_NAME_VERSION (arg);
 
@@ -1420,27 +1455,6 @@ coalesce_partitions (var_map map, ssa_conflicts *graph, coalesce_list *cl,
 }
 
 
-/* Hashtable support for storing SSA names hashed by their SSA_NAME_VAR.  */
-
-struct ssa_name_var_hash : nofree_ptr_hash <tree_node>
-{
-  static inline hashval_t hash (const tree_node *);
-  static inline int equal (const tree_node *, const tree_node *);
-};
-
-inline hashval_t
-ssa_name_var_hash::hash (const_tree n)
-{
-  return DECL_UID (SSA_NAME_VAR (n));
-}
-
-inline int
-ssa_name_var_hash::equal (const tree_node *n1, const tree_node *n2)
-{
-  return SSA_NAME_VAR (n1) == SSA_NAME_VAR (n2);
-}
-
-
 /* Output partition map MAP with coalescing plan PART to file F.  */
 
 void
@@ -1629,8 +1643,9 @@ compute_optimized_partition_bases (var_map map, bitmap used_in_copies,
   /* And also with abnormal edges.  */
   basic_block bb;
   edge e;
+  unsigned i;
   edge_iterator ei;
-  FOR_EACH_BB_FN (bb, cfun)
+  for (i = 0; map->vec_bbs.iterate (i, &bb); ++i)
     {
       FOR_EACH_EDGE (e, ei, bb->preds)
        if (e->flags & EDGE_ABNORMAL)
@@ -1640,14 +1655,15 @@ compute_optimized_partition_bases (var_map map, bitmap used_in_copies,
                 gsi_next (&gsi))
              {
                gphi *phi = gsi.phi ();
+               tree res = PHI_RESULT (phi);
+               if (virtual_operand_p (res))
+                 continue;
                tree arg = PHI_ARG_DEF (phi, e->dest_idx);
                if (SSA_NAME_IS_DEFAULT_DEF (arg)
                    && (!SSA_NAME_VAR (arg)
                        || TREE_CODE (SSA_NAME_VAR (arg)) != PARM_DECL))
                  continue;
 
-               tree res = PHI_RESULT (phi);
-
                int p1 = partition_find (tentative, var_to_partition (map, res));
                int p2 = partition_find (tentative, var_to_partition (map, arg));
 
@@ -1675,7 +1691,6 @@ compute_optimized_partition_bases (var_map map, bitmap used_in_copies,
      between all SSA versions that ended up in the same potential
      coalesce partition.  */
   bitmap_iterator bi;
-  unsigned i;
   EXECUTE_IF_SET_IN_BITMAP (used_in_copies, 0, i, bi)
     {
       int pidx = var_to_partition (map, ssa_name (i));
@@ -1784,62 +1799,22 @@ compute_samebase_partition_bases (var_map map)
   free (mapstorage);
 }
 
-/* Reduce the number of copies by coalescing variables in the function.  Return
-   a partition map with the resulting coalesces.  */
+/* Given an initial var_map MAP, coalesce variables and return a partition map
+   with the resulting coalesce.  Note that this function is called in either
+   live range computation context or out-of-ssa context, indicated by MAP.  */
 
-extern var_map
-coalesce_ssa_name (void)
+extern void
+coalesce_ssa_name (var_map map)
 {
   tree_live_info_p liveinfo;
   ssa_conflicts *graph;
   coalesce_list *cl;
   auto_bitmap used_in_copies;
-  var_map map;
-  unsigned int i;
-  tree a;
 
-  cl = create_coalesce_list ();
-  map = create_outofssa_var_map (cl, used_in_copies);
+  cl = create_coalesce_list_for_region (map, used_in_copies);
+  if (map->outofssa_p)
+    populate_coalesce_list_for_outofssa (cl, used_in_copies);
 
-  /* If this optimization is disabled, we need to coalesce all the
-     names originating from the same SSA_NAME_VAR so debug info
-     remains undisturbed.  */
-  if (!flag_tree_coalesce_vars)
-    {
-      hash_table<ssa_name_var_hash> ssa_name_hash (10);
-
-      FOR_EACH_SSA_NAME (i, a, cfun)
-       {
-         if (SSA_NAME_VAR (a)
-             && !DECL_IGNORED_P (SSA_NAME_VAR (a))
-             && (!has_zero_uses (a) || !SSA_NAME_IS_DEFAULT_DEF (a)
-                 || !VAR_P (SSA_NAME_VAR (a))))
-           {
-             tree *slot = ssa_name_hash.find_slot (a, INSERT);
-
-             if (!*slot)
-               *slot = a;
-             else
-               {
-                 /* If the variable is a PARM_DECL or a RESULT_DECL, we
-                    _require_ that all the names originating from it be
-                    coalesced, because there must be a single partition
-                    containing all the names so that it can be assigned
-                    the canonical RTL location of the DECL safely.
-                    If in_lto_p, a function could have been compiled
-                    originally with optimizations and only the link
-                    performed at -O0, so we can't actually require it.  */
-                 const int cost
-                   = (TREE_CODE (SSA_NAME_VAR (a)) == VAR_DECL || in_lto_p)
-                     ? MUST_COALESCE_COST - 1 : MUST_COALESCE_COST;
-                 add_coalesce (cl, SSA_NAME_VERSION (a),
-                               SSA_NAME_VERSION (*slot), cost);
-                 bitmap_set_bit (used_in_copies, SSA_NAME_VERSION (a));
-                 bitmap_set_bit (used_in_copies, SSA_NAME_VERSION (*slot));
-               }
-           }
-       }
-    }
   if (dump_file && (dump_flags & TDF_DETAILS))
     dump_var_map (dump_file, map);
 
@@ -1853,7 +1828,7 @@ coalesce_ssa_name (void)
   if (num_var_partitions (map) < 1)
     {
       delete_coalesce_list (cl);
-      return map;
+      return;
     }
 
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1890,75 +1865,5 @@ coalesce_ssa_name (void)
 
   delete_coalesce_list (cl);
   ssa_conflicts_delete (graph);
-
-  return map;
 }
 
-/* We need to pass two arguments to set_parm_default_def_partition,
-   but for_all_parms only supports one.  Use a pair.  */
-
-typedef std::pair<var_map, bitmap> parm_default_def_partition_arg;
-
-/* Set in ARG's PARTS bitmap the bit corresponding to the partition in
-   ARG's MAP containing VAR's default def.  */
-
-static void
-set_parm_default_def_partition (tree var, void *arg_)
-{
-  parm_default_def_partition_arg *arg = (parm_default_def_partition_arg *)arg_;
-  var_map map = arg->first;
-  bitmap parts = arg->second;
-
-  if (!is_gimple_reg (var))
-    return;
-
-  tree ssa = ssa_default_def (cfun, var);
-  gcc_assert (ssa);
-
-  int version = var_to_partition (map, ssa);
-  gcc_assert (version != NO_PARTITION);
-
-  bool changed = bitmap_set_bit (parts, version);
-  gcc_assert (changed);
-}
-
-/* Allocate and return a bitmap that has a bit set for each partition
-   that contains a default def for a parameter.  */
-
-bitmap
-get_parm_default_def_partitions (var_map map)
-{
-  bitmap parm_default_def_parts = BITMAP_ALLOC (NULL);
-
-  parm_default_def_partition_arg
-    arg = std::make_pair (map, parm_default_def_parts);
-
-  for_all_parms (set_parm_default_def_partition, &arg);
-
-  return parm_default_def_parts;
-}
-
-/* Allocate and return a bitmap that has a bit set for each partition
-   that contains an undefined value.  */
-
-bitmap
-get_undefined_value_partitions (var_map map)
-{
-  bitmap undefined_value_parts = BITMAP_ALLOC (NULL);
-
-  for (unsigned int i = 1; i < num_ssa_names; i++)
-    {
-      tree var = ssa_name (i);
-      if (var
-         && !virtual_operand_p (var)
-         && !has_zero_uses (var)
-         && ssa_undefined_value_p (var))
-       {
-         const int p = var_to_partition (map, var);
-         if (p != NO_PARTITION)
-           bitmap_set_bit (undefined_value_parts, p);
-       }
-    }
-
-  return undefined_value_parts;
-}
index 89d8474df40726c0dd8eac4f0b16809c4b709cd2..f787637164953985f020bb5a148a4dfdabe8dbe8 100644 (file)
@@ -20,9 +20,7 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_TREE_SSA_COALESCE_H
 #define GCC_TREE_SSA_COALESCE_H
 
-extern var_map coalesce_ssa_name (void);
+extern void coalesce_ssa_name (var_map);
 extern bool gimple_can_coalesce_p (tree, tree);
-extern bitmap get_parm_default_def_partitions (var_map);
-extern bitmap get_undefined_value_partitions (var_map);
 
 #endif /* GCC_TREE_SSA_COALESCE_H */
index 62316bac79295eb719f7342ec3770cd945f05749..7447f7a6f0ccd4e2d0cc5e0afd6bf89754db9c16 100644 (file)
@@ -71,10 +71,12 @@ var_map_base_fini (var_map map)
       map->num_basevars = 0;
     }
 }
-/* Create a variable partition map of SIZE, initialize and return it.  */
+/* Create a variable partition map of SIZE for region, initialize and return
+   it.  Region is a loop if LOOP is non-NULL, otherwise is the current
+   function.  */
 
 var_map
-init_var_map (int size)
+init_var_map (int size, struct loop *loop)
 {
   var_map map;
 
@@ -87,6 +89,27 @@ init_var_map (int size)
   map->partition_size = size;
   map->num_basevars = 0;
   map->partition_to_base_index = NULL;
+  map->vec_bbs = vNULL;
+  if (loop)
+    {
+      map->bmp_bbs = BITMAP_ALLOC (NULL);
+      map->outofssa_p = false;
+      basic_block *bbs = get_loop_body_in_dom_order (loop);
+      for (unsigned i = 0; i < loop->num_nodes; ++i)
+       {
+         bitmap_set_bit (map->bmp_bbs, bbs[i]->index);
+         map->vec_bbs.safe_push (bbs[i]);
+       }
+      free (bbs);
+    }
+  else
+    {
+      map->bmp_bbs = NULL;
+      map->outofssa_p = true;
+      basic_block bb;
+      FOR_EACH_BB_FN (bb, cfun)
+       map->vec_bbs.safe_push (bb);
+    }
   return map;
 }
 
@@ -100,6 +123,9 @@ delete_var_map (var_map map)
   partition_delete (map->var_partition);
   free (map->partition_to_view);
   free (map->view_to_partition);
+  if (map->bmp_bbs)
+    BITMAP_FREE (map->bmp_bbs);
+  map->vec_bbs.release ();
   free (map);
 }
 
@@ -901,13 +927,14 @@ new_tree_live_info (var_map map)
 
   bitmap_obstack_initialize (&live->livein_obstack);
   bitmap_obstack_initialize (&live->liveout_obstack);
-  live->livein = XNEWVEC (bitmap_head, last_basic_block_for_fn (cfun));
-  FOR_EACH_BB_FN (bb, cfun)
-    bitmap_initialize (&live->livein[bb->index], &live->livein_obstack);
 
-  live->liveout = XNEWVEC (bitmap_head, last_basic_block_for_fn (cfun));
-  FOR_EACH_BB_FN (bb, cfun)
-    bitmap_initialize (&live->liveout[bb->index], &live->liveout_obstack);
+  live->livein = XCNEWVEC (bitmap_head, last_basic_block_for_fn (cfun));
+  live->liveout = XCNEWVEC (bitmap_head, last_basic_block_for_fn (cfun));
+  for (unsigned i = 0; map->vec_bbs.iterate (i, &bb); ++i)
+    {
+      bitmap_initialize (&live->livein[bb->index], &live->livein_obstack);
+      bitmap_initialize (&live->liveout[bb->index], &live->liveout_obstack);
+    }
 
   live->work_stack = XNEWVEC (int, last_basic_block_for_fn (cfun));
   live->stack_top = live->work_stack;
@@ -960,7 +987,7 @@ loe_visit_block (tree_live_info_p live, basic_block bb, sbitmap visited)
   FOR_EACH_EDGE (e, ei, bb->preds)
     {
       pred_bb = e->src;
-      if (pred_bb == ENTRY_BLOCK_PTR_FOR_FN (cfun))
+      if (!region_contains_p (live->map, pred_bb))
        continue;
       /* Variables live-on-entry from BB that aren't defined in the
         predecessor block.  This should be the live on entry vars to pred.
@@ -993,9 +1020,10 @@ live_worklist (tree_live_info_p live)
 
   bitmap_clear (visited);
 
-  /* Visit all the blocks in reverse order and propagate live on entry values
+  /* Visit region's blocks in reverse order and propagate live on entry values
      into the predecessors blocks.  */
-  FOR_EACH_BB_REVERSE_FN (bb, cfun)
+  for (unsigned i = live->map->vec_bbs.length () - 1;
+       live->map->vec_bbs.iterate (i, &bb); --i)
     loe_visit_block (live, bb, visited);
 
   /* Process any blocks which require further iteration.  */
@@ -1030,7 +1058,7 @@ set_var_live_on_entry (tree ssa_name, tree_live_info_p live)
     {
       def_bb = gimple_bb (stmt);
       /* Mark defs in liveout bitmap temporarily.  */
-      if (def_bb)
+      if (def_bb && region_contains_p (live->map, def_bb))
        bitmap_set_bit (&live->liveout[def_bb->index], p);
     }
   else
@@ -1054,11 +1082,8 @@ set_var_live_on_entry (tree ssa_name, tree_live_info_p live)
             defined in that block, or whether its live on entry.  */
          int index = PHI_ARG_INDEX_FROM_USE (use);
          edge e = gimple_phi_arg_edge (as_a <gphi *> (use_stmt), index);
-         if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun))
-           {
-             if (e->src != def_bb)
-               add_block = e->src;
-           }
+         if (e->src != def_bb && region_contains_p (live->map, e->src))
+           add_block = e->src;
        }
       else if (is_gimple_debug (use_stmt))
        continue;
@@ -1066,7 +1091,7 @@ set_var_live_on_entry (tree ssa_name, tree_live_info_p live)
         {
          /* If its not defined in this block, its live on entry.  */
          basic_block use_bb = gimple_bb (use_stmt);
-         if (use_bb != def_bb)
+         if (use_bb != def_bb && region_contains_p (live->map, use_bb))
            add_block = use_bb;
        }
 
@@ -1095,7 +1120,7 @@ calculate_live_on_exit (tree_live_info_p liveinfo)
   edge_iterator ei;
 
   /* live on entry calculations used liveout vectors for defs, clear them.  */
-  FOR_EACH_BB_FN (bb, cfun)
+  for (unsigned i = 0; liveinfo->map->vec_bbs.iterate (i, &bb); ++i)
     bitmap_clear (&liveinfo->liveout[bb->index]);
 
   /* Set all the live-on-exit bits for uses in PHIs.  */
@@ -1108,6 +1133,8 @@ calculate_live_on_exit (tree_live_info_p liveinfo)
       for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
        {
          gphi *phi = gsi.phi ();
+         if (virtual_operand_p (gimple_phi_result (phi)))
+           continue;
          for (i = 0; i < gimple_phi_num_args (phi); i++)
            {
              tree t = PHI_ARG_DEF (phi, i);
@@ -1120,14 +1147,17 @@ calculate_live_on_exit (tree_live_info_p liveinfo)
              if (p == NO_PARTITION)
                continue;
              e = gimple_phi_arg_edge (phi, i);
-             if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun))
+             if (region_contains_p (liveinfo->map, e->src))
                bitmap_set_bit (&liveinfo->liveout[e->src->index], p);
            }
        }
 
+      if (!region_contains_p (liveinfo->map, bb))
+       continue;
+
       /* Add each successors live on entry to this bock live on exit.  */
       FOR_EACH_EDGE (e, ei, bb->succs)
-       if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
+       if (region_contains_p (liveinfo->map, e->dest))
          bitmap_ior_into (&liveinfo->liveout[bb->index],
                           live_on_entry (liveinfo, e->dest));
     }
@@ -1314,7 +1344,7 @@ verify_live_on_entry (tree_live_info_p live)
   FOR_EACH_EDGE (e, ei, bb->succs)
     {
       int entry_block = e->dest->index;
-      if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun))
+      if (!region_contains_p (live->map, e->dest))
         continue;
       for (i = 0; i < (unsigned)num_var_partitions (map); i++)
        {
@@ -1380,6 +1410,8 @@ verify_live_on_entry (tree_live_info_p live)
                     gsi_next (&gsi))
                  {
                    gphi *phi = gsi.phi ();
+                   if (virtual_operand_p (gimple_phi_result (phi)))
+                     continue;
                    for (z = 0; z < gimple_phi_num_args (phi); z++)
                      if (var == gimple_phi_arg_def (phi, z))
                        {
index 448aaf911ff872b77343751d35d32b8599b97e57..9aa541804bb44855d686226906f299165301de42 100644 (file)
@@ -62,13 +62,25 @@ typedef struct _var_map
 
   /* Map of partitions numbers to base variable table indexes.  */
   int *partition_to_base_index;
+
+  /* Bitmap of basic block.  It describes the region within which the analysis
+     is done.  Using pointer avoids allocating memory in out-of-ssa case.  */
+  bitmap bmp_bbs;
+
+  /* Vector of basic block in the region.  */
+  vec<basic_block> vec_bbs;
+
+  /* True if this map is for out-of-ssa, otherwise for live range
+     computation.  When for out-of-ssa, it also means the var map is computed
+     for whole current function.  */
+  bool outofssa_p;
 } *var_map;
 
 
 /* Value used to represent no partition number.  */
 #define NO_PARTITION           -1
 
-extern var_map init_var_map (int);
+extern var_map init_var_map (int, struct loop* = NULL);
 extern void delete_var_map (var_map);
 extern int var_union (var_map, tree, tree);
 extern void partition_view_normal (var_map);
@@ -82,6 +94,19 @@ extern void debug (_var_map &ref);
 extern void debug (_var_map *ptr);
 
 
+/* Return TRUE if region of the MAP contains basic block BB.  */
+
+inline bool
+region_contains_p (var_map map, basic_block bb)
+{
+  /* It's possible that the function is called with ENTRY_BLOCK/EXIT_BLOCK.  */
+  if (map->outofssa_p)
+    return (bb->index != ENTRY_BLOCK && bb->index != EXIT_BLOCK);
+
+  return bitmap_bit_p (map->bmp_bbs, bb->index);
+}
+
+
 /* Return number of partitions in MAP.  */
 
 static inline unsigned