compare-elim.c (find_comparison_dom_walker): New class

* compare-elim.c (find_comparison_dom_walker): New class
	(find_comparisons_in_bb): Rename to
	find_comparison_dom_walker::before_dom_children
	(find_comparisons): Adjust
	* domwalk.c (walk_dominator_tree): Rename to dom_walker::walk, and
	adjust.
	(init_walk_dominator_tree, fini_walk_dominator_tree): Remove
	* domwalk.h (dom_walk_data): Convert it To a class dom_walker.
	(init_walk_dominator_tree): Remove declaration.
	(fini_walk_dominator_tree): Remove declaration.
	* fwprop.c (single_def_use_dom_walker): New class
	(single_def_use_enter_block): Convert to
	single_def_use_dom_walker::before_dom_children.
	(single_def_use_leave_block): Convert to
	single_def_use_dom_walker::after_dom_children.
	(build_single_def_use_links): Adjust.
	* gimple-ssa-strength-reduction.c (find_candidates_dom_walker): New
	class.
	(find_candidates_in_block): Convert to
	find_candidates_dom_walker::before_dom_children.
	(execute_strength_reduction): Adjust.
	* graphite-sese-to-poly.c (struct bsc, build_sese_conditions): Remove.
	(sese_dom_walker): New class.
	(sese_dom_walker::sese_dom_walker): New constructor.
	(sese_dom_walker::~sese_dom_walker): New destructor.
	(build_sese_conditions_before): Convert to
	sese_dom_walker::before_dom_children.
	(build_sese_conditions_after): Convert to
	sese_dom_walker::after_dom_children.
	(build_poly_scop): Adjust
	* tree-into-ssa.c (rewrite_dom_walker): New class
	(rewrite_enter_block): Convert to
	rewrite_dom_walker::before_dom_children.
	(rewrite_leave_block): Convert to
	rewrite_dom_walker::after_dom_children.
	(rewrite_update_dom_walker): New class.
	(rewrite_update_enter_block): Convert to
	rewrite_update_dom_walker::before_dom_children.
	(rewrite_update_leave_block): Convert to
	rewrite_update_dom_walker::after_dom_children.
	(rewrite_blocks, rewrite_into_ssa): Adjust.
	(mark_def_dom_walker): New class.
	(mark_def_dom_walker::mark_def_dom_walker): New constructor.
	(mark_def_dom_walker::~mark_def_dom_walker): New destructor.
	(mark_def_sites_blocks): Convert to
	mark_def_dom_walker::before_dom_children.
	(mark_def_site_blocks): Remove.
	* tree-ssa-dom.c (dom_opt_dom_walker): New class.
	(tree_ssa_dominator_optimize): Adjust.
	(dom_thread_across_edge): Convert to method
	dom_opt_dom_walker::thread_across_edge.
	(dom_opt_enter_block): Convert to member function
	dom_opt_dom_walker::before_dom_children.
	(dom_opt_leave_block): Convert to member function
	dom_opt_dom_walker::after_dom_children.
	* tree-ssa-dse.c (dse_dom_walker): New class.
	(dse_enter_block): Convert to member function
	dse_dom_walker::before_dom_children.
	(tree_ssa_dse): Adjust.
	* tree-ssa-loop-im.c (invariantness_dom_walker): New class.
	(determine_invariantness_stmt): Convert to method
	invariantness_dom_walker::before_dom_children.
	(determine_invariantness): Remove
	(move_computations_dom_walker): New class.
	(move_computations_stmt): Convert to method
	move_computations_dom_walker::before_dom_children.
	(move_computations, tree_ssa_lim): Adjust.
	* tree-ssa-phiopt.c (nontrapping_dom_walker): new class
	(nt_init_block): Make method
	notrappping_dom_walker::before_dom_children.
	(nt_fini_block): Make
	method nontrapping_dom_walker::after_dom_children.
	(get_non_trapping): Adjust.
	* tree-ssa-pre.c (eliminate_dom_walker): New class.
	(eliminate_bb): Make method eliminate_dom_walker::before_dom_children.
	(eliminate_leave_block): Make method.
	eliminate_dom_walker::after_dom_children.
	(eliminate): Adjust
	* tree-ssa-strlen.c (strlen_dom_walker): New class.
	(strlen_enter_block): Make method
	strlen_dom_walker::before_dom_children.
	(strlen_leave_block): Make
	method strlen_dom_walker::after_dom_children.
	(tree_ssa_strlen): Adjust.
	* tree-ssa-uncprop.c (uncprop_dom_walker): New class.
	(tree_ssa_uncprop): Adjust.
	(uncprop_leave_block): Make method
	uncprop_dom_walker::after_dom_children.
	(uncprop_leave_block): Make method
	uncprop_dom_walker::before_dom_children.

From-SVN: r202679
This commit is contained in:
Trevor Saunders 2013-09-18 02:39:50 +00:00 committed by Jeff Law
parent 3b3cc26bcc
commit 4d9192b50c
15 changed files with 428 additions and 521 deletions

View File

@ -1,3 +1,96 @@
2013-09-17 Trevor Saunders <tsaunders@mozilla.com>
* compare-elim.c (find_comparison_dom_walker): New class
(find_comparisons_in_bb): Rename to
find_comparison_dom_walker::before_dom_children
(find_comparisons): Adjust
* domwalk.c (walk_dominator_tree): Rename to dom_walker::walk, and
adjust.
(init_walk_dominator_tree, fini_walk_dominator_tree): Remove
* domwalk.h (dom_walk_data): Convert it To a class dom_walker.
(init_walk_dominator_tree): Remove declaration.
(fini_walk_dominator_tree): Remove declaration.
* fwprop.c (single_def_use_dom_walker): New class
(single_def_use_enter_block): Convert to
single_def_use_dom_walker::before_dom_children.
(single_def_use_leave_block): Convert to
single_def_use_dom_walker::after_dom_children.
(build_single_def_use_links): Adjust.
* gimple-ssa-strength-reduction.c (find_candidates_dom_walker): New
class.
(find_candidates_in_block): Convert to
find_candidates_dom_walker::before_dom_children.
(execute_strength_reduction): Adjust.
* graphite-sese-to-poly.c (struct bsc, build_sese_conditions): Remove.
(sese_dom_walker): New class.
(sese_dom_walker::sese_dom_walker): New constructor.
(sese_dom_walker::~sese_dom_walker): New destructor.
(build_sese_conditions_before): Convert to
sese_dom_walker::before_dom_children.
(build_sese_conditions_after): Convert to
sese_dom_walker::after_dom_children.
(build_poly_scop): Adjust
* tree-into-ssa.c (rewrite_dom_walker): New class
(rewrite_enter_block): Convert to
rewrite_dom_walker::before_dom_children.
(rewrite_leave_block): Convert to
rewrite_dom_walker::after_dom_children.
(rewrite_update_dom_walker): New class.
(rewrite_update_enter_block): Convert to
rewrite_update_dom_walker::before_dom_children.
(rewrite_update_leave_block): Convert to
rewrite_update_dom_walker::after_dom_children.
(rewrite_blocks, rewrite_into_ssa): Adjust.
(mark_def_dom_walker): New class.
(mark_def_dom_walker::mark_def_dom_walker): New constructor.
(mark_def_dom_walker::~mark_def_dom_walker): New destructor.
(mark_def_sites_blocks): Convert to
mark_def_dom_walker::before_dom_children.
(mark_def_site_blocks): Remove.
* tree-ssa-dom.c (dom_opt_dom_walker): New class.
(tree_ssa_dominator_optimize): Adjust.
(dom_thread_across_edge): Convert to method
dom_opt_dom_walker::thread_across_edge.
(dom_opt_enter_block): Convert to member function
dom_opt_dom_walker::before_dom_children.
(dom_opt_leave_block): Convert to member function
dom_opt_dom_walker::after_dom_children.
* tree-ssa-dse.c (dse_dom_walker): New class.
(dse_enter_block): Convert to member function
dse_dom_walker::before_dom_children.
(tree_ssa_dse): Adjust.
* tree-ssa-loop-im.c (invariantness_dom_walker): New class.
(determine_invariantness_stmt): Convert to method
invariantness_dom_walker::before_dom_children.
(determine_invariantness): Remove
(move_computations_dom_walker): New class.
(move_computations_stmt): Convert to method
move_computations_dom_walker::before_dom_children.
(move_computations, tree_ssa_lim): Adjust.
* tree-ssa-phiopt.c (nontrapping_dom_walker): new class
(nt_init_block): Make method
notrappping_dom_walker::before_dom_children.
(nt_fini_block): Make
method nontrapping_dom_walker::after_dom_children.
(get_non_trapping): Adjust.
* tree-ssa-pre.c (eliminate_dom_walker): New class.
(eliminate_bb): Make method eliminate_dom_walker::before_dom_children.
(eliminate_leave_block): Make method.
eliminate_dom_walker::after_dom_children.
(eliminate): Adjust
* tree-ssa-strlen.c (strlen_dom_walker): New class.
(strlen_enter_block): Make method
strlen_dom_walker::before_dom_children.
(strlen_leave_block): Make
method strlen_dom_walker::after_dom_children.
(tree_ssa_strlen): Adjust.
* tree-ssa-uncprop.c (uncprop_dom_walker): New class.
(tree_ssa_uncprop): Adjust.
(uncprop_leave_block): Make method
uncprop_dom_walker::after_dom_children.
(uncprop_leave_block): Make method
uncprop_dom_walker::before_dom_children.
2013-09-18 Bin Cheng <bin.cheng@arm.com>
* config/arm/arm.c (thumb1_reorg): Search for flag setting insn

View File

@ -243,13 +243,21 @@ find_flags_uses_in_insn (struct comparison *cmp, rtx insn)
cmp->missing_uses = true;
}
class find_comparison_dom_walker : public dom_walker
{
public:
find_comparison_dom_walker (cdi_direction direction)
: dom_walker(direction) {}
virtual void before_dom_children (basic_block);
};
/* Identify comparison instructions within BB. If the flags from the last
compare in the BB is live at the end of the block, install the compare
in BB->AUX. Called via walk_dominators_tree. */
in BB->AUX. Called via dom_walker.walk (). */
static void
find_comparisons_in_bb (struct dom_walk_data *data ATTRIBUTE_UNUSED,
basic_block bb)
void
find_comparison_dom_walker::before_dom_children (basic_block bb)
{
struct comparison *last_cmp;
rtx insn, next, last_clobber;
@ -403,17 +411,10 @@ find_comparisons_in_bb (struct dom_walk_data *data ATTRIBUTE_UNUSED,
static void
find_comparisons (void)
{
struct dom_walk_data data;
memset (&data, 0, sizeof(data));
data.dom_direction = CDI_DOMINATORS;
data.before_dom_children = find_comparisons_in_bb;
calculate_dominance_info (CDI_DOMINATORS);
init_walk_dominator_tree (&data);
walk_dominator_tree (&data, ENTRY_BLOCK_PTR);
fini_walk_dominator_tree (&data);
find_comparison_dom_walker (CDI_DOMINATORS)
.walk (cfun->cfg->x_entry_block_ptr);
clear_aux_for_blocks ();
free_dominance_info (CDI_DOMINATORS);

View File

@ -144,23 +144,17 @@ cmp_bb_postorder (const void *a, const void *b)
}
/* Recursively walk the dominator tree.
WALK_DATA contains a set of callbacks to perform pass-specific
actions during the dominator walk as well as a stack of block local
data maintained during the dominator walk.
BB is the basic block we are currently visiting. */
void
walk_dominator_tree (struct dom_walk_data *walk_data, basic_block bb)
dom_walker::walk (basic_block bb)
{
void *bd = NULL;
basic_block dest;
basic_block *worklist = XNEWVEC (basic_block, n_basic_blocks * 2);
int sp = 0;
int *postorder, postorder_num;
if (walk_data->dom_direction == CDI_DOMINATORS)
if (dom_direction_ == CDI_DOMINATORS)
{
postorder = XNEWVEC (int, n_basic_blocks);
postorder_num = inverted_post_order_compute (postorder);
@ -177,37 +171,9 @@ walk_dominator_tree (struct dom_walk_data *walk_data, basic_block bb)
|| bb == ENTRY_BLOCK_PTR
|| bb == EXIT_BLOCK_PTR)
{
/* Callback to initialize the local data structure. */
if (walk_data->initialize_block_local_data)
{
bool recycled;
/* First get some local data, reusing any local data
pointer we may have saved. */
if (walk_data->free_block_data.length () > 0)
{
bd = walk_data->free_block_data.pop ();
recycled = 1;
}
else
{
bd = xcalloc (1, walk_data->block_local_data_size);
recycled = 0;
}
/* Push the local data into the local data stack. */
walk_data->block_data_stack.safe_push (bd);
/* Call the initializer. */
walk_data->initialize_block_local_data (walk_data, bb,
recycled);
}
/* Callback for operations to execute before we have walked the
dominator children, but before we walk statements. */
if (walk_data->before_dom_children)
(*walk_data->before_dom_children) (walk_data, bb);
/* Callback for subclasses to do custom things before we have walked
the dominator children, but before we walk statements. */
before_dom_children (bb);
/* Mark the current BB to be popped out of the recursion stack
once children are processed. */
@ -215,10 +181,10 @@ walk_dominator_tree (struct dom_walk_data *walk_data, basic_block bb)
worklist[sp++] = NULL;
int saved_sp = sp;
for (dest = first_dom_son (walk_data->dom_direction, bb);
dest; dest = next_dom_son (walk_data->dom_direction, dest))
for (dest = first_dom_son (dom_direction_, bb);
dest; dest = next_dom_son (dom_direction_, dest))
worklist[sp++] = dest;
if (walk_data->dom_direction == CDI_DOMINATORS)
if (dom_direction_ == CDI_DOMINATORS)
switch (sp - saved_sp)
{
case 0:
@ -235,48 +201,19 @@ walk_dominator_tree (struct dom_walk_data *walk_data, basic_block bb)
--sp;
bb = worklist[--sp];
/* Callback for operations to execute after we have walked the
dominator children, but before we walk statements. */
if (walk_data->after_dom_children)
(*walk_data->after_dom_children) (walk_data, bb);
if (walk_data->initialize_block_local_data)
{
/* And finally pop the record off the block local data stack. */
bd = walk_data->block_data_stack.pop ();
/* And save the block data so that we can re-use it. */
walk_data->free_block_data.safe_push (bd);
}
/* Callback allowing subclasses to do custom things after we have
walked dominator children, but before we walk statements. */
after_dom_children (bb);
}
if (sp)
bb = worklist[--sp];
else
break;
}
if (walk_data->dom_direction == CDI_DOMINATORS)
if (dom_direction_ == CDI_DOMINATORS)
{
free (bb_postorder);
bb_postorder = NULL;
}
free (worklist);
}
void
init_walk_dominator_tree (struct dom_walk_data *walk_data)
{
walk_data->free_block_data.create (0);
walk_data->block_data_stack.create (0);
}
void
fini_walk_dominator_tree (struct dom_walk_data *walk_data)
{
if (walk_data->initialize_block_local_data)
{
while (walk_data->free_block_data.length () > 0)
free (walk_data->free_block_data.pop ());
}
walk_data->free_block_data.release ();
walk_data->block_data_stack.release ();
}

View File

@ -18,57 +18,35 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
typedef void *void_p;
#ifndef GCC_DOM_WALK_H
#define GCC_DOM_WALK_H
/* This is the main data structure for the dominator walker. It provides
the callback hooks as well as a convenient place to hang block local
data and pass-global data. */
struct dom_walk_data
/**
* This is the main class for the dominator walker. It is expected that
* consumers will have a custom class inheriting from it, which will over ride
* at least one of before_dom_children and after_dom_children to implement the
* custom behavior.
*/
class dom_walker
{
public:
dom_walker (cdi_direction direction) : dom_direction_ (direction) {}
/* Walk the dominator tree. */
void walk (basic_block);
/* Function to call before the recursive walk of the dominator children. */
virtual void before_dom_children (basic_block) {}
/* Function to call after the recursive walk of the dominator children. */
virtual void after_dom_children (basic_block) {}
private:
/* This is the direction of the dominator tree we want to walk. i.e.,
if it is set to CDI_DOMINATORS, then we walk the dominator tree,
if it is set to CDI_POST_DOMINATORS, then we walk the post
dominator tree. */
ENUM_BITFIELD (cdi_direction) dom_direction : 2;
/* Function to initialize block local data.
Note that the dominator walker infrastructure may provide a new
fresh, and zero'd block local data structure, or it may re-use an
existing block local data structure.
If the block local structure has items such as virtual arrays, then
that allows your optimizer to re-use those arrays rather than
creating new ones. */
void (*initialize_block_local_data) (struct dom_walk_data *,
basic_block, bool);
/* Function to call before the recursive walk of the dominator children. */
void (*before_dom_children) (struct dom_walk_data *, basic_block);
/* Function to call after the recursive walk of the dominator children. */
void (*after_dom_children) (struct dom_walk_data *, basic_block);
/* Global data for a walk through the dominator tree. */
void *global_data;
/* Stack of any data we need to keep on a per-block basis.
If you have no local data, then BLOCK_DATA_STACK will be NULL. */
vec<void_p> block_data_stack;
/* Size of the block local data. If this is zero, then it is assumed
you have no local data and thus no BLOCK_DATA_STACK as well. */
size_t block_local_data_size;
/* From here below are private data. Please do not use this
information/data outside domwalk.c. */
/* Stack of available block local structures. */
vec<void_p> free_block_data;
const ENUM_BITFIELD (cdi_direction) dom_direction_ : 2;
};
void walk_dominator_tree (struct dom_walk_data *, basic_block);
void init_walk_dominator_tree (struct dom_walk_data *);
void fini_walk_dominator_tree (struct dom_walk_data *);
#endif

View File

@ -205,10 +205,17 @@ process_uses (df_ref *use_rec, int top_flag)
}
}
class single_def_use_dom_walker : public dom_walker
{
public:
single_def_use_dom_walker (cdi_direction direction)
: dom_walker (direction) {}
virtual void before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
};
static void
single_def_use_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
basic_block bb)
void
single_def_use_dom_walker::before_dom_children (basic_block bb)
{
int bb_index = bb->index;
struct df_md_bb_info *md_bb_info = df_md_get_bb_info (bb_index);
@ -245,9 +252,8 @@ single_def_use_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
/* Pop the definitions created in this basic block when leaving its
dominated parts. */
static void
single_def_use_leave_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
basic_block bb ATTRIBUTE_UNUSED)
void
single_def_use_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
{
df_ref saved_def;
while ((saved_def = reg_defs_stack.pop ()) != NULL)
@ -269,8 +275,6 @@ single_def_use_leave_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
static void
build_single_def_use_links (void)
{
struct dom_walk_data walk_data;
/* We use the multiple definitions problem to compute our restricted
use-def chains. */
df_set_flags (DF_EQ_NOTES);
@ -291,14 +295,8 @@ build_single_def_use_links (void)
/* Walk the dominator tree looking for single reaching definitions
dominating the uses. This is similar to how SSA form is built. */
walk_data.dom_direction = CDI_DOMINATORS;
walk_data.initialize_block_local_data = NULL;
walk_data.before_dom_children = single_def_use_enter_block;
walk_data.after_dom_children = single_def_use_leave_block;
init_walk_dominator_tree (&walk_data);
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
fini_walk_dominator_tree (&walk_data);
single_def_use_dom_walker (CDI_DOMINATORS)
.walk (cfun->cfg->x_entry_block_ptr);
BITMAP_FREE (local_lr);
BITMAP_FREE (local_md);

View File

@ -1571,11 +1571,18 @@ slsr_process_copy (gimple gs, tree rhs1, bool speed)
add_cand_for_stmt (gs, c);
}
class find_candidates_dom_walker : public dom_walker
{
public:
find_candidates_dom_walker (cdi_direction direction)
: dom_walker (direction) {}
virtual void before_dom_children (basic_block);
};
/* Find strength-reduction candidates in block BB. */
static void
find_candidates_in_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
basic_block bb)
void
find_candidates_dom_walker::before_dom_children (basic_block bb)
{
bool speed = optimize_bb_for_speed_p (bb);
gimple_stmt_iterator gsi;
@ -3488,8 +3495,6 @@ analyze_candidates_and_replace (void)
static unsigned
execute_strength_reduction (void)
{
struct dom_walk_data walk_data;
/* Create the obstack where candidates will reside. */
gcc_obstack_init (&cand_obstack);
@ -3509,18 +3514,10 @@ execute_strength_reduction (void)
back edges, and this gives us dominator information as well. */
loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
/* Set up callbacks for the generic dominator tree walker. */
walk_data.dom_direction = CDI_DOMINATORS;
walk_data.initialize_block_local_data = NULL;
walk_data.before_dom_children = find_candidates_in_block;
walk_data.after_dom_children = NULL;
walk_data.global_data = NULL;
walk_data.block_local_data_size = 0;
init_walk_dominator_tree (&walk_data);
/* Walk the CFG in predominator order looking for strength reduction
candidates. */
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
find_candidates_dom_walker (CDI_DOMINATORS)
.walk (cfun->cfg->x_entry_block_ptr);
if (dump_file && (dump_flags & TDF_DETAILS))
{
@ -3531,8 +3528,6 @@ execute_strength_reduction (void)
/* Analyze costs and make appropriate replacements. */
analyze_candidates_and_replace ();
/* Free resources. */
fini_walk_dominator_tree (&walk_data);
loop_optimizer_finalize ();
base_cand_map.dispose ();
obstack_free (&chain_obstack, NULL);

View File

@ -1191,14 +1191,6 @@ add_conditions_to_constraints (scop_p scop)
add_conditions_to_domain (pbb);
}
/* Structure used to pass data to dom_walk. */
struct bsc
{
vec<gimple> *conditions, *cases;
sese region;
};
/* Returns a COND_EXPR statement when BB has a single predecessor, the
edge between BB and its predecessor is not a loop exit edge, and
the last statement of the single predecessor is a COND_EXPR. */
@ -1224,20 +1216,43 @@ single_pred_cond_non_loop_exit (basic_block bb)
return NULL;
}
class sese_dom_walker : public dom_walker
{
public:
sese_dom_walker (cdi_direction, sese);
~sese_dom_walker ();
virtual void before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
private:
vec<gimple> conditions_, cases_;
sese region_;
};
sese_dom_walker::sese_dom_walker (cdi_direction direction, sese region)
: dom_walker (direction), region_ (region)
{
conditions_.create (3);
cases_.create (3);
}
sese_dom_walker::~sese_dom_walker ()
{
conditions_.release ();
cases_.release ();
}
/* Call-back for dom_walk executed before visiting the dominated
blocks. */
static void
build_sese_conditions_before (struct dom_walk_data *dw_data,
basic_block bb)
void
sese_dom_walker::before_dom_children (basic_block bb)
{
struct bsc *data = (struct bsc *) dw_data->global_data;
vec<gimple> *conditions = data->conditions;
vec<gimple> *cases = data->cases;
gimple_bb_p gbb;
gimple stmt;
if (!bb_in_sese_p (bb, data->region))
if (!bb_in_sese_p (bb, region_))
return;
stmt = single_pred_cond_non_loop_exit (bb);
@ -1246,75 +1261,39 @@ build_sese_conditions_before (struct dom_walk_data *dw_data,
{
edge e = single_pred_edge (bb);
conditions->safe_push (stmt);
conditions_.safe_push (stmt);
if (e->flags & EDGE_TRUE_VALUE)
cases->safe_push (stmt);
cases_.safe_push (stmt);
else
cases->safe_push (NULL);
cases_.safe_push (NULL);
}
gbb = gbb_from_bb (bb);
if (gbb)
{
GBB_CONDITIONS (gbb) = conditions->copy ();
GBB_CONDITION_CASES (gbb) = cases->copy ();
GBB_CONDITIONS (gbb) = conditions_.copy ();
GBB_CONDITION_CASES (gbb) = cases_.copy ();
}
}
/* Call-back for dom_walk executed after visiting the dominated
blocks. */
static void
build_sese_conditions_after (struct dom_walk_data *dw_data,
basic_block bb)
void
sese_dom_walker::after_dom_children (basic_block bb)
{
struct bsc *data = (struct bsc *) dw_data->global_data;
vec<gimple> *conditions = data->conditions;
vec<gimple> *cases = data->cases;
if (!bb_in_sese_p (bb, data->region))
if (!bb_in_sese_p (bb, region_))
return;
if (single_pred_cond_non_loop_exit (bb))
{
conditions->pop ();
cases->pop ();
conditions_.pop ();
cases_.pop ();
}
}
/* Record all conditions in REGION. */
static void
build_sese_conditions (sese region)
{
struct dom_walk_data walk_data;
vec<gimple> conditions;
conditions.create (3);
vec<gimple> cases;
cases.create (3);
struct bsc data;
data.conditions = &conditions;
data.cases = &cases;
data.region = region;
walk_data.dom_direction = CDI_DOMINATORS;
walk_data.initialize_block_local_data = NULL;
walk_data.before_dom_children = build_sese_conditions_before;
walk_data.after_dom_children = build_sese_conditions_after;
walk_data.global_data = &data;
walk_data.block_local_data_size = 0;
init_walk_dominator_tree (&walk_data);
walk_dominator_tree (&walk_data, SESE_ENTRY_BB (region));
fini_walk_dominator_tree (&walk_data);
conditions.release ();
cases.release ();
}
/* Add constraints on the possible values of parameter P from the type
of P. */
@ -3179,7 +3158,8 @@ build_poly_scop (scop_p scop)
rewrite_commutative_reductions_out_of_ssa (scop);
build_sese_loop_nests (region);
build_sese_conditions (region);
/* Record all conditions in REGION. */
sese_dom_walker (CDI_DOMINATORS, region).walk (cfun->cfg->x_entry_block_ptr);
find_scop_parameters (scop);
max_dim = PARAM_VALUE (PARAM_GRAPHITE_MAX_NB_SCOP_PARAMS);

View File

@ -1399,14 +1399,22 @@ rewrite_add_phi_arguments (basic_block bb)
}
}
class rewrite_dom_walker : public dom_walker
{
public:
rewrite_dom_walker (cdi_direction direction) : dom_walker (direction) {}
virtual void before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
};
/* SSA Rewriting Step 1. Initialization, create a block local stack
of reaching definitions for new SSA names produced in this block
(BLOCK_DEFS). Register new definitions for every PHI node in the
block. */
static void
rewrite_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
basic_block bb)
void
rewrite_dom_walker::before_dom_children (basic_block bb)
{
gimple_stmt_iterator gsi;
@ -1444,9 +1452,8 @@ rewrite_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
/* Called after visiting all the statements in basic block BB and all
of its dominator children. Restore CURRDEFS to its original value. */
static void
rewrite_leave_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
basic_block bb ATTRIBUTE_UNUSED)
void
rewrite_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
{
/* Restore CURRDEFS to its original state. */
while (block_defs_stack.length () > 0)
@ -2065,15 +2072,22 @@ rewrite_update_phi_arguments (basic_block bb)
}
}
class rewrite_update_dom_walker : public dom_walker
{
public:
rewrite_update_dom_walker (cdi_direction direction) : dom_walker (direction) {}
virtual void before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
};
/* Initialization of block data structures for the incremental SSA
update pass. Create a block local stack of reaching definitions
for new SSA names produced in this block (BLOCK_DEFS). Register
new definitions for every PHI node in the block. */
static void
rewrite_update_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
basic_block bb)
void
rewrite_update_dom_walker::before_dom_children (basic_block bb)
{
bool is_abnormal_phi;
gimple_stmt_iterator gsi;
@ -2146,9 +2160,8 @@ rewrite_update_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
unwinding must be done in the opposite order to what is done in
register_new_update_set. */
static void
rewrite_update_leave_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
basic_block bb ATTRIBUTE_UNUSED)
void
rewrite_update_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
{
while (block_defs_stack.length () > 0)
{
@ -2183,40 +2196,19 @@ rewrite_update_leave_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
static void
rewrite_blocks (basic_block entry, enum rewrite_mode what)
{
struct dom_walk_data walk_data;
/* Rewrite all the basic blocks in the program. */
timevar_push (TV_TREE_SSA_REWRITE_BLOCKS);
/* Setup callbacks for the generic dominator tree walker. */
memset (&walk_data, 0, sizeof (walk_data));
walk_data.dom_direction = CDI_DOMINATORS;
if (what == REWRITE_ALL)
{
walk_data.before_dom_children = rewrite_enter_block;
walk_data.after_dom_children = rewrite_leave_block;
}
else if (what == REWRITE_UPDATE)
{
walk_data.before_dom_children = rewrite_update_enter_block;
walk_data.after_dom_children = rewrite_update_leave_block;
}
else
gcc_unreachable ();
block_defs_stack.create (10);
/* Initialize the dominator walker. */
init_walk_dominator_tree (&walk_data);
/* Recursively walk the dominator tree rewriting each statement in
each basic block. */
walk_dominator_tree (&walk_data, entry);
/* Finalize the dominator walker. */
fini_walk_dominator_tree (&walk_data);
if (what == REWRITE_ALL)
rewrite_dom_walker (CDI_DOMINATORS).walk (entry);
else if (what == REWRITE_UPDATE)
rewrite_update_dom_walker (CDI_DOMINATORS).walk (entry);
else
gcc_unreachable ();
/* Debugging dumps. */
if (dump_file && (dump_flags & TDF_STATS))
@ -2231,69 +2223,44 @@ rewrite_blocks (basic_block entry, enum rewrite_mode what)
timevar_pop (TV_TREE_SSA_REWRITE_BLOCKS);
}
class mark_def_dom_walker : public dom_walker
{
public:
mark_def_dom_walker (cdi_direction direction);
~mark_def_dom_walker ();
virtual void before_dom_children (basic_block);
private:
/* Notice that this bitmap is indexed using variable UIDs, so it must be
large enough to accommodate all the variables referenced in the
function, not just the ones we are renaming. */
bitmap kills_;
};
mark_def_dom_walker::mark_def_dom_walker (cdi_direction direction)
: dom_walker (direction), kills_ (BITMAP_ALLOC (NULL))
{
}
mark_def_dom_walker::~mark_def_dom_walker ()
{
BITMAP_FREE (kills_);
}
/* Block processing routine for mark_def_sites. Clear the KILLS bitmap
at the start of each block, and call mark_def_sites for each statement. */
static void
mark_def_sites_block (struct dom_walk_data *walk_data, basic_block bb)
void
mark_def_dom_walker::before_dom_children (basic_block bb)
{
struct mark_def_sites_global_data *gd;
bitmap kills;
gimple_stmt_iterator gsi;
gd = (struct mark_def_sites_global_data *) walk_data->global_data;
kills = gd->kills;
bitmap_clear (kills);
bitmap_clear (kills_);
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
mark_def_sites (bb, gsi_stmt (gsi), kills);
mark_def_sites (bb, gsi_stmt (gsi), kills_);
}
/* Mark the definition site blocks for each variable, so that we know
where the variable is actually live.
The INTERESTING_BLOCKS global will be filled in with all the blocks
that should be processed by the renamer. It is assumed that the
caller has already initialized and zeroed it. */
static void
mark_def_site_blocks (void)
{
struct dom_walk_data walk_data;
struct mark_def_sites_global_data mark_def_sites_global_data;
/* Setup callbacks for the generic dominator tree walker to find and
mark definition sites. */
walk_data.dom_direction = CDI_DOMINATORS;
walk_data.initialize_block_local_data = NULL;
walk_data.before_dom_children = mark_def_sites_block;
walk_data.after_dom_children = NULL;
/* Notice that this bitmap is indexed using variable UIDs, so it must be
large enough to accommodate all the variables referenced in the
function, not just the ones we are renaming. */
mark_def_sites_global_data.kills = BITMAP_ALLOC (NULL);
walk_data.global_data = &mark_def_sites_global_data;
/* We do not have any local data. */
walk_data.block_local_data_size = 0;
/* Initialize the dominator walker. */
init_walk_dominator_tree (&walk_data);
/* Recursively walk the dominator tree. */
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
/* Finalize the dominator walker. */
fini_walk_dominator_tree (&walk_data);
/* We no longer need this bitmap, clear and free it. */
BITMAP_FREE (mark_def_sites_global_data.kills);
}
/* Initialize internal data needed during renaming. */
static void
@ -2331,8 +2298,7 @@ fini_ssa_renamer (void)
insert PHI nodes and rename the function in dominator tree
order.
2- Find and mark all the blocks that define variables
(mark_def_site_blocks).
2- Find and mark all the blocks that define variables.
3- Insert PHI nodes at dominance frontiers (insert_phi_nodes).
@ -2370,7 +2336,7 @@ rewrite_into_ssa (void)
compute_dominance_frontiers (dfs);
/* 2- Find and mark definition sites. */
mark_def_site_blocks ();
mark_def_dom_walker (CDI_DOMINATORS).walk (cfun->cfg->x_entry_block_ptr);
/* 3- Insert PHI nodes at dominance frontiers of definition blocks. */
insert_phi_nodes (dfs);

View File

@ -244,9 +244,6 @@ static void record_equivalences_from_phis (basic_block);
static void record_equivalences_from_incoming_edge (basic_block);
static void eliminate_redundant_computations (gimple_stmt_iterator *);
static void record_equivalences_from_stmt (gimple, int);
static void dom_thread_across_edge (struct dom_walk_data *, edge);
static void dom_opt_leave_block (struct dom_walk_data *, basic_block);
static void dom_opt_enter_block (struct dom_walk_data *, basic_block);
static void remove_local_expressions_from_table (void);
static void restore_vars_to_original_value (void);
static edge single_incoming_edge_ignoring_loop_edges (basic_block);
@ -773,6 +770,21 @@ free_all_edge_infos (void)
}
}
class dom_opt_dom_walker : public dom_walker
{
public:
dom_opt_dom_walker (cdi_direction direction)
: dom_walker (direction), dummy_cond_ (NULL) {}
virtual void before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
private:
void thread_across_edge (edge);
gimple dummy_cond_;
};
/* Jump threading, redundancy elimination and const/copy propagation.
This pass may expose new symbols that need to be renamed into SSA. For
@ -782,8 +794,6 @@ free_all_edge_infos (void)
static unsigned int
tree_ssa_dominator_optimize (void)
{
struct dom_walk_data walk_data;
memset (&opt_stats, 0, sizeof (opt_stats));
/* Create our hash tables. */
@ -792,20 +802,6 @@ tree_ssa_dominator_optimize (void)
const_and_copies_stack.create (20);
need_eh_cleanup = BITMAP_ALLOC (NULL);
/* Setup callbacks for the generic dominator tree walker. */
walk_data.dom_direction = CDI_DOMINATORS;
walk_data.initialize_block_local_data = NULL;
walk_data.before_dom_children = dom_opt_enter_block;
walk_data.after_dom_children = dom_opt_leave_block;
/* Right now we only attach a dummy COND_EXPR to the global data pointer.
When we attach more stuff we'll need to fill this out with a real
structure. */
walk_data.global_data = NULL;
walk_data.block_local_data_size = 0;
/* Now initialize the dominator walker. */
init_walk_dominator_tree (&walk_data);
calculate_dominance_info (CDI_DOMINATORS);
cfg_altered = false;
@ -824,7 +820,7 @@ tree_ssa_dominator_optimize (void)
mark_dfs_back_edges ();
/* Recursively walk the dominator tree optimizing statements. */
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
dom_opt_dom_walker (CDI_DOMINATORS).walk (cfun->cfg->x_entry_block_ptr);
{
gimple_stmt_iterator gsi;
@ -897,9 +893,6 @@ tree_ssa_dominator_optimize (void)
/* Delete our main hashtable. */
avail_exprs.dispose ();
/* And finalize the dominator walker. */
fini_walk_dominator_tree (&walk_data);
/* Free asserted bitmaps and stacks. */
BITMAP_FREE (need_eh_cleanup);
@ -1081,21 +1074,18 @@ simplify_stmt_for_jump_threading (gimple stmt,
it handles lazily building the dummy condition and the bookkeeping
when jump threading is successful. */
static void
dom_thread_across_edge (struct dom_walk_data *walk_data, edge e)
void
dom_opt_dom_walker::thread_across_edge (edge e)
{
if (! walk_data->global_data)
{
gimple dummy_cond =
if (! dummy_cond_)
dummy_cond_ =
gimple_build_cond (NE_EXPR,
integer_zero_node, integer_zero_node,
NULL, NULL);
walk_data->global_data = dummy_cond;
}
thread_across_edge ((gimple) walk_data->global_data, e, false,
&const_and_copies_stack,
simplify_stmt_for_jump_threading);
::thread_across_edge (dummy_cond_, e, false,
&const_and_copies_stack,
simplify_stmt_for_jump_threading);
}
/* PHI nodes can create equivalences too.
@ -1864,9 +1854,8 @@ record_edge_info (basic_block bb)
}
}
static void
dom_opt_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
basic_block bb)
void
dom_opt_dom_walker::before_dom_children (basic_block bb)
{
gimple_stmt_iterator gsi;
@ -1903,8 +1892,8 @@ dom_opt_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
any finalization actions in preparation for leaving this node in
the dominator tree. */
static void
dom_opt_leave_block (struct dom_walk_data *walk_data, basic_block bb)
void
dom_opt_dom_walker::after_dom_children (basic_block bb)
{
gimple last;
@ -1919,7 +1908,7 @@ dom_opt_leave_block (struct dom_walk_data *walk_data, basic_block bb)
/* Push a marker on the stack, which thread_across_edge expects
and will remove. */
const_and_copies_stack.safe_push (NULL_TREE);
dom_thread_across_edge (walk_data, single_succ_edge (bb));
thread_across_edge (single_succ_edge (bb));
}
else if ((last = last_stmt (bb))
&& gimple_code (last) == GIMPLE_COND
@ -1964,7 +1953,7 @@ dom_opt_leave_block (struct dom_walk_data *walk_data, basic_block bb)
record_cond (eq);
}
dom_thread_across_edge (walk_data, true_edge);
thread_across_edge (true_edge);
/* And restore the various tables to their state before
we threaded this edge. */
@ -1999,7 +1988,7 @@ dom_opt_leave_block (struct dom_walk_data *walk_data, basic_block bb)
}
/* Now thread the edge. */
dom_thread_across_edge (walk_data, false_edge);
thread_across_edge (false_edge);
/* No need to remove local expressions from our tables
or restore vars to their original value as that will

View File

@ -68,7 +68,6 @@ static bitmap need_eh_cleanup;
static bool gate_dse (void);
static unsigned int tree_ssa_dse (void);
static void dse_enter_block (struct dom_walk_data *, basic_block);
/* A helper of dse_optimize_stmt.
@ -292,9 +291,16 @@ dse_optimize_stmt (gimple_stmt_iterator *gsi)
}
}
static void
dse_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
basic_block bb)
class dse_dom_walker : public dom_walker
{
public:
dse_dom_walker (cdi_direction direction) : dom_walker (direction) {}
virtual void before_dom_children (basic_block);
};
void
dse_dom_walker::before_dom_children (basic_block bb)
{
gimple_stmt_iterator gsi;
@ -313,8 +319,6 @@ dse_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
static unsigned int
tree_ssa_dse (void)
{
struct dom_walk_data walk_data;
need_eh_cleanup = BITMAP_ALLOC (NULL);
renumber_gimple_stmt_uids ();
@ -328,22 +332,7 @@ tree_ssa_dse (void)
/* Dead store elimination is fundamentally a walk of the post-dominator
tree and a backwards walk of statements within each block. */
walk_data.dom_direction = CDI_POST_DOMINATORS;
walk_data.initialize_block_local_data = NULL;
walk_data.before_dom_children = dse_enter_block;
walk_data.after_dom_children = NULL;
walk_data.block_local_data_size = 0;
walk_data.global_data = NULL;
/* Initialize the dominator walker. */
init_walk_dominator_tree (&walk_data);
/* Recursively walk the dominator tree. */
walk_dominator_tree (&walk_data, EXIT_BLOCK_PTR);
/* Finalize the dominator walker. */
fini_walk_dominator_tree (&walk_data);
dse_dom_walker (CDI_POST_DOMINATORS).walk (cfun->cfg->x_exit_block_ptr);
/* Removal of stores may make some EH edges dead. Purge such edges from
the CFG as needed. */

View File

@ -1040,14 +1040,25 @@ rewrite_bittest (gimple_stmt_iterator *bsi)
return stmt;
}
/* For each statement determines the outermost loop in that it is invariant,
- statements on whose motion it depends and the cost of the computation.
- This information is stored to the LIM_DATA structure associated with
- each statement. */
class invariantness_dom_walker : public dom_walker
{
public:
invariantness_dom_walker (cdi_direction direction)
: dom_walker (direction) {}
virtual void before_dom_children (basic_block);
};
/* Determine the outermost loops in that statements in basic block BB are
invariant, and record them to the LIM_DATA associated with the statements.
Callback for walk_dominator_tree. */
Callback for dom_walker. */
static void
determine_invariantness_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
basic_block bb)
void
invariantness_dom_walker::before_dom_children (basic_block bb)
{
enum move_pos pos;
gimple_stmt_iterator bsi;
@ -1177,32 +1188,23 @@ determine_invariantness_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
}
}
/* For each statement determines the outermost loop in that it is invariant,
statements on whose motion it depends and the cost of the computation.
This information is stored to the LIM_DATA structure associated with
each statement. */
static void
determine_invariantness (void)
class move_computations_dom_walker : public dom_walker
{
struct dom_walk_data walk_data;
public:
move_computations_dom_walker (cdi_direction direction)
: dom_walker (direction), todo_ (0) {}
memset (&walk_data, 0, sizeof (struct dom_walk_data));
walk_data.dom_direction = CDI_DOMINATORS;
walk_data.before_dom_children = determine_invariantness_stmt;
virtual void before_dom_children (basic_block);
init_walk_dominator_tree (&walk_data);
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
fini_walk_dominator_tree (&walk_data);
}
unsigned int todo_;
};
/* Hoist the statements in basic block BB out of the loops prescribed by
data stored in LIM_DATA structures associated with each statement. Callback
for walk_dominator_tree. */
static void
move_computations_stmt (struct dom_walk_data *dw_data,
basic_block bb)
void
move_computations_dom_walker::before_dom_children (basic_block bb)
{
struct loop *level;
gimple_stmt_iterator bsi;
@ -1266,7 +1268,7 @@ move_computations_stmt (struct dom_walk_data *dw_data,
gimple_phi_result (stmt),
t, arg0, arg1);
SSA_NAME_DEF_STMT (gimple_phi_result (stmt)) = new_stmt;
*((unsigned int *)(dw_data->global_data)) |= TODO_cleanup_cfg;
todo_ |= TODO_cleanup_cfg;
}
gsi_insert_on_edge (loop_preheader_edge (level), new_stmt);
remove_phi_node (&bsi, false);
@ -1337,23 +1339,14 @@ move_computations_stmt (struct dom_walk_data *dw_data,
static unsigned int
move_computations (void)
{
struct dom_walk_data walk_data;
unsigned int todo = 0;
memset (&walk_data, 0, sizeof (struct dom_walk_data));
walk_data.global_data = &todo;
walk_data.dom_direction = CDI_DOMINATORS;
walk_data.before_dom_children = move_computations_stmt;
init_walk_dominator_tree (&walk_data);
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
fini_walk_dominator_tree (&walk_data);
move_computations_dom_walker walker (CDI_DOMINATORS);
walker.walk (cfun->cfg->x_entry_block_ptr);
gsi_commit_edge_inserts ();
if (need_ssa_update_p (cfun))
rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
return todo;
return walker.todo_;
}
/* Checks whether the statement defining variable *INDEX can be hoisted
@ -2632,7 +2625,8 @@ tree_ssa_lim (void)
/* For each statement determine the outermost loop in that it is
invariant and cost for computing the invariant. */
determine_invariantness ();
invariantness_dom_walker (CDI_DOMINATORS)
.walk (cfun->cfg->x_entry_block_ptr);
/* Execute store motion. Force the necessary invariants to be moved
out of the loops as well. */

View File

@ -1264,9 +1264,6 @@ struct ssa_names_hasher : typed_free_remove <name_to_bb>
Hash entries with phase < nt_call_phase are invalid. */
static unsigned int nt_call_phase;
/* The set of MEM_REFs which can't trap. */
static struct pointer_set_t *nontrap_set;
/* The hash function. */
inline hashval_t
@ -1378,9 +1375,22 @@ nonfreeing_call_p (gimple call)
return false;
}
class nontrapping_dom_walker : public dom_walker
{
public:
nontrapping_dom_walker (cdi_direction direction, pointer_set_t *ps)
: dom_walker (direction), nontrapping_ (ps) {}
virtual void before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
private:
pointer_set_t *nontrapping_;
};
/* Called by walk_dominator_tree, when entering the block BB. */
static void
nt_init_block (struct dom_walk_data *data ATTRIBUTE_UNUSED, basic_block bb)
void
nontrapping_dom_walker::before_dom_children (basic_block bb)
{
edge e;
edge_iterator ei;
@ -1406,15 +1416,15 @@ nt_init_block (struct dom_walk_data *data ATTRIBUTE_UNUSED, basic_block bb)
nt_call_phase++;
else if (gimple_assign_single_p (stmt) && !gimple_has_volatile_ops (stmt))
{
add_or_mark_expr (bb, gimple_assign_lhs (stmt), nontrap_set, true);
add_or_mark_expr (bb, gimple_assign_rhs1 (stmt), nontrap_set, false);
add_or_mark_expr (bb, gimple_assign_lhs (stmt), nontrapping_, true);
add_or_mark_expr (bb, gimple_assign_rhs1 (stmt), nontrapping_, false);
}
}
}
/* Called by walk_dominator_tree, when basic block BB is exited. */
static void
nt_fini_block (struct dom_walk_data *data ATTRIBUTE_UNUSED, basic_block bb)
void
nontrapping_dom_walker::after_dom_children (basic_block bb)
{
/* This BB isn't on the path to dominator root anymore. */
bb->aux = (void*)2;
@ -1427,28 +1437,16 @@ nt_fini_block (struct dom_walk_data *data ATTRIBUTE_UNUSED, basic_block bb)
static struct pointer_set_t *
get_non_trapping (void)
{
struct pointer_set_t *nontrap;
struct dom_walk_data walk_data;
nt_call_phase = 0;
nontrap = pointer_set_create ();
pointer_set_t *nontrap = pointer_set_create ();
seen_ssa_names.create (128);
/* We're going to do a dominator walk, so ensure that we have
dominance information. */
calculate_dominance_info (CDI_DOMINATORS);
/* Setup callbacks for the generic dominator tree walker. */
nontrap_set = nontrap;
walk_data.dom_direction = CDI_DOMINATORS;
walk_data.initialize_block_local_data = NULL;
walk_data.before_dom_children = nt_init_block;
walk_data.after_dom_children = nt_fini_block;
walk_data.global_data = NULL;
walk_data.block_local_data_size = 0;
nontrapping_dom_walker (CDI_DOMINATORS, nontrap)
.walk (cfun->cfg->x_entry_block_ptr);
init_walk_dominator_tree (&walk_data);
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
fini_walk_dominator_tree (&walk_data);
seen_ssa_names.dispose ();
clear_aux_for_blocks ();

View File

@ -4051,10 +4051,19 @@ eliminate_insert (gimple_stmt_iterator *gsi, tree val)
return res;
}
class eliminate_dom_walker : public dom_walker
{
public:
eliminate_dom_walker (cdi_direction direction) : dom_walker (direction) {}
virtual void before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
};
/* Perform elimination for the basic-block B during the domwalk. */
static void
eliminate_bb (dom_walk_data *, basic_block b)
void
eliminate_dom_walker::before_dom_children (basic_block b)
{
gimple_stmt_iterator gsi;
gimple stmt;
@ -4403,8 +4412,8 @@ eliminate_bb (dom_walk_data *, basic_block b)
/* Make no longer available leaders no longer available. */
static void
eliminate_leave_block (dom_walk_data *, basic_block)
void
eliminate_dom_walker::after_dom_children (basic_block)
{
tree entry;
while ((entry = el_avail_stack.pop ()) != NULL_TREE)
@ -4416,7 +4425,6 @@ eliminate_leave_block (dom_walk_data *, basic_block)
static unsigned int
eliminate (void)
{
struct dom_walk_data walk_data;
gimple_stmt_iterator gsi;
gimple stmt;
unsigned i;
@ -4430,15 +4438,7 @@ eliminate (void)
el_avail.create (0);
el_avail_stack.create (0);
walk_data.dom_direction = CDI_DOMINATORS;
walk_data.initialize_block_local_data = NULL;
walk_data.before_dom_children = eliminate_bb;
walk_data.after_dom_children = eliminate_leave_block;
walk_data.global_data = NULL;
walk_data.block_local_data_size = 0;
init_walk_dominator_tree (&walk_data);
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
fini_walk_dominator_tree (&walk_data);
eliminate_dom_walker (CDI_DOMINATORS).walk (cfun->cfg->x_entry_block_ptr);
el_avail.release ();
el_avail_stack.release ();

View File

@ -1926,12 +1926,20 @@ do_invalidate (basic_block dombb, gimple phi, bitmap visited, int *count)
}
}
class strlen_dom_walker : public dom_walker
{
public:
strlen_dom_walker (cdi_direction direction) : dom_walker (direction) {}
virtual void before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
};
/* Callback for walk_dominator_tree. Attempt to optimize various
string ops by remembering string lenths pointed by pointer SSA_NAMEs. */
static void
strlen_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
basic_block bb)
void
strlen_dom_walker::before_dom_children (basic_block bb)
{
gimple_stmt_iterator gsi;
basic_block dombb = get_immediate_dominator (CDI_DOMINATORS, bb);
@ -2014,9 +2022,8 @@ strlen_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
/* Callback for walk_dominator_tree. Free strinfo vector if it is
owned by the current bb, clear bb->aux. */
static void
strlen_leave_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
basic_block bb)
void
strlen_dom_walker::after_dom_children (basic_block bb)
{
if (bb->aux)
{
@ -2040,8 +2047,6 @@ strlen_leave_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
static unsigned int
tree_ssa_strlen (void)
{
struct dom_walk_data walk_data;
ssa_ver_to_stridx.safe_grow_cleared (num_ssa_names);
max_stridx = 1;
strinfo_pool = create_alloc_pool ("strinfo_struct pool",
@ -2051,21 +2056,7 @@ tree_ssa_strlen (void)
/* String length optimization is implemented as a walk of the dominator
tree and a forward walk of statements within each block. */
walk_data.dom_direction = CDI_DOMINATORS;
walk_data.initialize_block_local_data = NULL;
walk_data.before_dom_children = strlen_enter_block;
walk_data.after_dom_children = strlen_leave_block;
walk_data.block_local_data_size = 0;
walk_data.global_data = NULL;
/* Initialize the dominator walker. */
init_walk_dominator_tree (&walk_data);
/* Recursively walk the dominator tree. */
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
/* Finalize the dominator walker. */
fini_walk_dominator_tree (&walk_data);
strlen_dom_walker (CDI_DOMINATORS).walk (cfun->cfg->x_entry_block_ptr);
ssa_ver_to_stridx.release ();
free_alloc_pool (strinfo_pool);

View File

@ -259,11 +259,6 @@ associate_equivalences_with_edges (void)
so with each value we have a list of SSA_NAMEs that have the
same value. */
/* As we enter each block we record the value for any edge equivalency
leading to this block. If no such edge equivalency exists, then we
record NULL. These equivalences are live until we leave the dominator
subtree rooted at the block where we record the equivalency. */
static vec<tree> equiv_stack;
/* Main structure for recording equivalences into our hash table. */
struct equiv_hash_elt
@ -316,8 +311,6 @@ val_ssa_equiv_hasher::remove (value_type *elt)
able to reuse tree-vn for this code. */
static hash_table <val_ssa_equiv_hasher> val_ssa_equiv;
static void uncprop_enter_block (struct dom_walk_data *, basic_block);
static void uncprop_leave_block (struct dom_walk_data *, basic_block);
static void uncprop_into_successor_phis (basic_block);
/* Remove the most recently recorded equivalency for VALUE. */
@ -361,47 +354,54 @@ record_equiv (tree value, tree equivalence)
an_equiv_elt_p->equivalences.safe_push (equivalence);
}
class uncprop_dom_walker : public dom_walker
{
public:
uncprop_dom_walker (cdi_direction direction)
: dom_walker (direction)
{
equiv_stack_.create (2);
}
~uncprop_dom_walker ()
{
equiv_stack_.release ();
}
virtual void before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
private:
/* As we enter each block we record the value for any edge equivalency
leading to this block. If no such edge equivalency exists, then we
record NULL. These equivalences are live until we leave the dominator
subtree rooted at the block where we record the equivalency. */
vec<tree> equiv_stack_;
};
/* Main driver for un-cprop. */
static unsigned int
tree_ssa_uncprop (void)
{
struct dom_walk_data walk_data;
basic_block bb;
associate_equivalences_with_edges ();
/* Create our global data structures. */
val_ssa_equiv.create (1024);
equiv_stack.create (2);
/* We're going to do a dominator walk, so ensure that we have
dominance information. */
calculate_dominance_info (CDI_DOMINATORS);
/* Setup callbacks for the generic dominator tree walker. */
walk_data.dom_direction = CDI_DOMINATORS;
walk_data.initialize_block_local_data = NULL;
walk_data.before_dom_children = uncprop_enter_block;
walk_data.after_dom_children = uncprop_leave_block;
walk_data.global_data = NULL;
walk_data.block_local_data_size = 0;
/* Now initialize the dominator walker. */
init_walk_dominator_tree (&walk_data);
/* Recursively walk the dominator tree undoing unprofitable
constant/copy propagations. */
walk_dominator_tree (&walk_data, ENTRY_BLOCK_PTR);
uncprop_dom_walker (CDI_DOMINATORS).walk (cfun->cfg->x_entry_block_ptr);
/* Finalize and clean up. */
fini_walk_dominator_tree (&walk_data);
/* EQUIV_STACK should already be empty at this point, so we just
need to empty elements out of the hash table, free EQUIV_STACK,
and cleanup the AUX field on the edges. */
/* we just need to empty elements out of the hash table, and cleanup the
AUX field on the edges. */
val_ssa_equiv.dispose ();
equiv_stack.release ();
FOR_EACH_BB (bb)
{
edge e;
@ -424,12 +424,11 @@ tree_ssa_uncprop (void)
any finalization actions in preparation for leaving this node in
the dominator tree. */
static void
uncprop_leave_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
basic_block bb ATTRIBUTE_UNUSED)
void
uncprop_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
{
/* Pop the topmost value off the equiv stack. */
tree value = equiv_stack.pop ();
tree value = equiv_stack_.pop ();
/* If that value was non-null, then pop the topmost equivalency off
its equivalency stack. */
@ -547,9 +546,8 @@ single_incoming_edge_ignoring_loop_edges (basic_block bb)
return retval;
}
static void
uncprop_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
basic_block bb)
void
uncprop_dom_walker::before_dom_children (basic_block bb)
{
basic_block parent;
edge e;
@ -568,13 +566,13 @@ uncprop_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
struct edge_equivalency *equiv = (struct edge_equivalency *) e->aux;
record_equiv (equiv->rhs, equiv->lhs);
equiv_stack.safe_push (equiv->rhs);
equiv_stack_.safe_push (equiv->rhs);
recorded = true;
}
}
if (!recorded)
equiv_stack.safe_push (NULL_TREE);
equiv_stack_.safe_push (NULL_TREE);
uncprop_into_successor_phis (bb);
}