Commit e3bfa377 by Bin Cheng Committed by Bin Cheng

tree-outof-ssa.c (tree-ssa.h, tree-dfa.h): Include header files.

	* 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
parent 34f7080e
2018-05-25 Bin Cheng <bin.cheng@arm.com> 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. * tree-ssa-live.h (live_merge_and_clear): Delete.
2018-05-25 Richard Biener <rguenther@suse.de> 2018-05-25 Richard Biener <rguenther@suse.de>
......
...@@ -27,10 +27,12 @@ along with GCC; see the file COPYING3. If not see ...@@ -27,10 +27,12 @@ along with GCC; see the file COPYING3. If not see
#include "gimple.h" #include "gimple.h"
#include "cfghooks.h" #include "cfghooks.h"
#include "ssa.h" #include "ssa.h"
#include "tree-ssa.h"
#include "memmodel.h" #include "memmodel.h"
#include "emit-rtl.h" #include "emit-rtl.h"
#include "gimple-pretty-print.h" #include "gimple-pretty-print.h"
#include "diagnostic-core.h" #include "diagnostic-core.h"
#include "tree-dfa.h"
#include "stor-layout.h" #include "stor-layout.h"
#include "cfgrtl.h" #include "cfgrtl.h"
#include "cfganal.h" #include "cfganal.h"
...@@ -888,6 +890,102 @@ rewrite_trees (var_map map) ...@@ -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) /* Given the out-of-ssa info object SA (with prepared partitions)
eliminate all phi nodes in all basic blocks. Afterwards no eliminate all phi nodes in all basic blocks. Afterwards no
basic block will have phi nodes anymore and there are possibly basic block will have phi nodes anymore and there are possibly
...@@ -945,7 +1043,9 @@ remove_ssa_form (bool perform_ter, struct ssaexpand *sa) ...@@ -945,7 +1043,9 @@ remove_ssa_form (bool perform_ter, struct ssaexpand *sa)
bitmap values = NULL; bitmap values = NULL;
var_map map; 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 /* Return to viewing the variable list as just all reference variables after
coalescing has been performed. */ coalescing has been performed. */
......
...@@ -20,9 +20,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -20,9 +20,7 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_TREE_SSA_COALESCE_H #ifndef GCC_TREE_SSA_COALESCE_H
#define 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 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 */ #endif /* GCC_TREE_SSA_COALESCE_H */
...@@ -71,10 +71,12 @@ var_map_base_fini (var_map map) ...@@ -71,10 +71,12 @@ var_map_base_fini (var_map map)
map->num_basevars = 0; 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 var_map
init_var_map (int size) init_var_map (int size, struct loop *loop)
{ {
var_map map; var_map map;
...@@ -87,6 +89,27 @@ init_var_map (int size) ...@@ -87,6 +89,27 @@ init_var_map (int size)
map->partition_size = size; map->partition_size = size;
map->num_basevars = 0; map->num_basevars = 0;
map->partition_to_base_index = NULL; 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; return map;
} }
...@@ -100,6 +123,9 @@ delete_var_map (var_map map) ...@@ -100,6 +123,9 @@ delete_var_map (var_map map)
partition_delete (map->var_partition); partition_delete (map->var_partition);
free (map->partition_to_view); free (map->partition_to_view);
free (map->view_to_partition); free (map->view_to_partition);
if (map->bmp_bbs)
BITMAP_FREE (map->bmp_bbs);
map->vec_bbs.release ();
free (map); free (map);
} }
...@@ -901,13 +927,14 @@ new_tree_live_info (var_map map) ...@@ -901,13 +927,14 @@ new_tree_live_info (var_map map)
bitmap_obstack_initialize (&live->livein_obstack); bitmap_obstack_initialize (&live->livein_obstack);
bitmap_obstack_initialize (&live->liveout_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)); live->livein = XCNEWVEC (bitmap_head, last_basic_block_for_fn (cfun));
FOR_EACH_BB_FN (bb, cfun) live->liveout = XCNEWVEC (bitmap_head, last_basic_block_for_fn (cfun));
bitmap_initialize (&live->liveout[bb->index], &live->liveout_obstack); 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->work_stack = XNEWVEC (int, last_basic_block_for_fn (cfun));
live->stack_top = live->work_stack; live->stack_top = live->work_stack;
...@@ -960,7 +987,7 @@ loe_visit_block (tree_live_info_p live, basic_block bb, sbitmap visited) ...@@ -960,7 +987,7 @@ loe_visit_block (tree_live_info_p live, basic_block bb, sbitmap visited)
FOR_EACH_EDGE (e, ei, bb->preds) FOR_EACH_EDGE (e, ei, bb->preds)
{ {
pred_bb = e->src; pred_bb = e->src;
if (pred_bb == ENTRY_BLOCK_PTR_FOR_FN (cfun)) if (!region_contains_p (live->map, pred_bb))
continue; continue;
/* Variables live-on-entry from BB that aren't defined in the /* Variables live-on-entry from BB that aren't defined in the
predecessor block. This should be the live on entry vars to pred. predecessor block. This should be the live on entry vars to pred.
...@@ -993,9 +1020,10 @@ live_worklist (tree_live_info_p live) ...@@ -993,9 +1020,10 @@ live_worklist (tree_live_info_p live)
bitmap_clear (visited); 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. */ 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); loe_visit_block (live, bb, visited);
/* Process any blocks which require further iteration. */ /* Process any blocks which require further iteration. */
...@@ -1030,7 +1058,7 @@ set_var_live_on_entry (tree ssa_name, tree_live_info_p live) ...@@ -1030,7 +1058,7 @@ set_var_live_on_entry (tree ssa_name, tree_live_info_p live)
{ {
def_bb = gimple_bb (stmt); def_bb = gimple_bb (stmt);
/* Mark defs in liveout bitmap temporarily. */ /* 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); bitmap_set_bit (&live->liveout[def_bb->index], p);
} }
else else
...@@ -1054,11 +1082,8 @@ set_var_live_on_entry (tree ssa_name, tree_live_info_p live) ...@@ -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. */ defined in that block, or whether its live on entry. */
int index = PHI_ARG_INDEX_FROM_USE (use); int index = PHI_ARG_INDEX_FROM_USE (use);
edge e = gimple_phi_arg_edge (as_a <gphi *> (use_stmt), index); 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 && region_contains_p (live->map, e->src))
{ add_block = e->src;
if (e->src != def_bb)
add_block = e->src;
}
} }
else if (is_gimple_debug (use_stmt)) else if (is_gimple_debug (use_stmt))
continue; continue;
...@@ -1066,7 +1091,7 @@ set_var_live_on_entry (tree ssa_name, tree_live_info_p live) ...@@ -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. */ /* If its not defined in this block, its live on entry. */
basic_block use_bb = gimple_bb (use_stmt); 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; add_block = use_bb;
} }
...@@ -1095,7 +1120,7 @@ calculate_live_on_exit (tree_live_info_p liveinfo) ...@@ -1095,7 +1120,7 @@ calculate_live_on_exit (tree_live_info_p liveinfo)
edge_iterator ei; edge_iterator ei;
/* live on entry calculations used liveout vectors for defs, clear them. */ /* 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]); bitmap_clear (&liveinfo->liveout[bb->index]);
/* Set all the live-on-exit bits for uses in PHIs. */ /* Set all the live-on-exit bits for uses in PHIs. */
...@@ -1108,6 +1133,8 @@ calculate_live_on_exit (tree_live_info_p liveinfo) ...@@ -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)) for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{ {
gphi *phi = gsi.phi (); gphi *phi = gsi.phi ();
if (virtual_operand_p (gimple_phi_result (phi)))
continue;
for (i = 0; i < gimple_phi_num_args (phi); i++) for (i = 0; i < gimple_phi_num_args (phi); i++)
{ {
tree t = PHI_ARG_DEF (phi, i); tree t = PHI_ARG_DEF (phi, i);
...@@ -1120,14 +1147,17 @@ calculate_live_on_exit (tree_live_info_p liveinfo) ...@@ -1120,14 +1147,17 @@ calculate_live_on_exit (tree_live_info_p liveinfo)
if (p == NO_PARTITION) if (p == NO_PARTITION)
continue; continue;
e = gimple_phi_arg_edge (phi, i); 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); 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. */ /* Add each successors live on entry to this bock live on exit. */
FOR_EACH_EDGE (e, ei, bb->succs) 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], bitmap_ior_into (&liveinfo->liveout[bb->index],
live_on_entry (liveinfo, e->dest)); live_on_entry (liveinfo, e->dest));
} }
...@@ -1314,7 +1344,7 @@ verify_live_on_entry (tree_live_info_p live) ...@@ -1314,7 +1344,7 @@ verify_live_on_entry (tree_live_info_p live)
FOR_EACH_EDGE (e, ei, bb->succs) FOR_EACH_EDGE (e, ei, bb->succs)
{ {
int entry_block = e->dest->index; int entry_block = e->dest->index;
if (e->dest == EXIT_BLOCK_PTR_FOR_FN (cfun)) if (!region_contains_p (live->map, e->dest))
continue; continue;
for (i = 0; i < (unsigned)num_var_partitions (map); i++) for (i = 0; i < (unsigned)num_var_partitions (map); i++)
{ {
...@@ -1380,6 +1410,8 @@ verify_live_on_entry (tree_live_info_p live) ...@@ -1380,6 +1410,8 @@ verify_live_on_entry (tree_live_info_p live)
gsi_next (&gsi)) gsi_next (&gsi))
{ {
gphi *phi = gsi.phi (); gphi *phi = gsi.phi ();
if (virtual_operand_p (gimple_phi_result (phi)))
continue;
for (z = 0; z < gimple_phi_num_args (phi); z++) for (z = 0; z < gimple_phi_num_args (phi); z++)
if (var == gimple_phi_arg_def (phi, z)) if (var == gimple_phi_arg_def (phi, z))
{ {
......
...@@ -62,13 +62,25 @@ typedef struct _var_map ...@@ -62,13 +62,25 @@ typedef struct _var_map
/* Map of partitions numbers to base variable table indexes. */ /* Map of partitions numbers to base variable table indexes. */
int *partition_to_base_index; 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; } *var_map;
/* Value used to represent no partition number. */ /* Value used to represent no partition number. */
#define NO_PARTITION -1 #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 void delete_var_map (var_map);
extern int var_union (var_map, tree, tree); extern int var_union (var_map, tree, tree);
extern void partition_view_normal (var_map); extern void partition_view_normal (var_map);
...@@ -82,6 +94,19 @@ extern void debug (_var_map &ref); ...@@ -82,6 +94,19 @@ extern void debug (_var_map &ref);
extern void debug (_var_map *ptr); 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. */ /* Return number of partitions in MAP. */
static inline unsigned static inline unsigned
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment