* 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
+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.
#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"
}
}
+/* 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
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. */
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));
{
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);
}
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
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;
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
}
}
- /* 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)
{
}
}
- 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));
+ }
+ }
+ }
+ }
}
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);
}
-/* 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
/* 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)
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));
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));
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);
if (num_var_partitions (map) < 1)
{
delete_coalesce_list (cl);
- return map;
+ return;
}
if (dump_file && (dump_flags & TDF_DETAILS))
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;
-}
#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 */
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;
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;
}
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);
}
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;
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.
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. */
{
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
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;
{
/* 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;
}
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. */
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);
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));
}
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++)
{
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))
{
/* 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);
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