diff options
author | Paolo Bonzini <bonzini@gnu.org> | 2009-06-27 14:45:51 +0000 |
---|---|---|
committer | Paolo Bonzini <bonzini@gcc.gnu.org> | 2009-06-27 14:45:51 +0000 |
commit | ccf5c864c9bae45e3c1a9858529f346005e5ca25 (patch) | |
tree | 4d282ef2e7bba7ac8b8f57bfadf3057c91cb6a6b /gcc/tree-ssa-dom.c | |
parent | c6bd4220c947db8bccef32768766ea2f030f70d5 (diff) | |
download | gcc-ccf5c864c9bae45e3c1a9858529f346005e5ca25.zip gcc-ccf5c864c9bae45e3c1a9858529f346005e5ca25.tar.gz gcc-ccf5c864c9bae45e3c1a9858529f346005e5ca25.tar.bz2 |
domwalk.h (struct dom_walk_data): Remove all callbacks except before_dom_children_before_stmts and...
2009-06-27 Paolo Bonzini <bonzini@gnu.org>
* domwalk.h (struct dom_walk_data): Remove all callbacks except
before_dom_children_before_stmts and after_dom_children_after_stmts.
Rename the two remaining callbacks to just before_dom_children and
after_dom_children. Remove other GIMPLE statement walking bits.
* domwalk.c (walk_dominator_tree): Remove now unsupported features.
* graphite.c: Do not include domwalk.h.
* tree-into-ssa.c (interesting_blocks): New global.
(struct mark_def_sites_global_data): Remove it and names_to_rename.
(mark_def_sites, rewrite_stmt, rewrite_add_phi_arguments,
rewrite_update_stmt, rewrite_update_phi_arguments): Simplify
now that they're not domwalk callbacks.
(rewrite_initialize_block): Rename to...
(rewrite_enter_block): ... this, place after called functions. Test
interesting_blocks, call rewrite_stmt and rewrite_add_phi_arguments.
(rewrite_finalize_block): Rename to...
(rewrite_leave_block): ... this, place after called functions.
(rewrite_update_init_block): Rename to...
(rewrite_update_enter_block): ... this, place after called functions.
Test interesting_blocks, call rewrite_update_stmt and
rewrite_update_phi_arguments.
(rewrite_update_fini_block): Rename to...
(rewrite_leave_block): ... this, place after called functions.
(rewrite_blocks): Remove last argument, simplify initialization of
walk_data.
(mark_def_sites_initialize_block): Rename to...
(mark_def_sites_block): ... this, call mark_def_sites.
(mark_def_sites_blocks): Remove argument, simplify initialization of
walk_data.
(rewrite_into_ssa): Adjust for interesting_blocks_being a global.
(update_ssa): Likewise.
* tree-ssa-dom.c (optimize_stmt): Simplify now that it's not a domwalk
callback.
(tree_ssa_dominator_optimize): Simplify initialization of walk_data.
(dom_opt_initialize_block): Rename to...
(dom_opt_enter_block): ... this, place after called functions. Walk
statements here, inline propagate_to_outgoing_edges.
(dom_opt_finalize_block): Rename to...
(dom_opt_leave_block): ... this, place after called functions.
* tree-ssa-dse.c (dse_optimize_stmt): Simplify now that it's not a
domwalk callback.
(dse_enter_block, dse_record_phi): New.
(dse_record_phis): Delete.
(dse_finalize_block): Rename to...
(dse_leave_block): ... this.
(tree_ssa_dse): Simplify initialization of walk_data.
* tree-ssa-loop-im.c (determine_invariantness, move_computations):
Adjust initialization of walk_data.
* tree-ssa-loop-unswitch.c: Do not include domwalk.h.
* tree-ssa-loop-phiopt.c (get_non_trapping):
Adjust initialization of walk_data.
* tree-ssa-loop-threadedge.c: Do not include domwalk.h.
* tree-ssa-uncprop.c (uncprop_into_successor_phis): Simplify now that
it's not a domwalk callback.
(uncprop_initialize_block): Rename to...
(dse_enter_block): ... this, call uncprop_into_successor_phis.
(dse_finalize_block): Rename to...
(dse_leave_block): ... this.
(tree_ssa_uncprop): Simplify initialization of walk_data.
* Makefile.in: Adjust dependencies.
From-SVN: r149008
Diffstat (limited to 'gcc/tree-ssa-dom.c')
-rw-r--r-- | gcc/tree-ssa-dom.c | 319 |
1 files changed, 152 insertions, 167 deletions
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c index 55a13b9..0a2c490 100644 --- a/gcc/tree-ssa-dom.c +++ b/gcc/tree-ssa-dom.c @@ -183,9 +183,7 @@ struct opt_stats_d static struct opt_stats_d opt_stats; /* Local functions. */ -static void optimize_stmt (struct dom_walk_data *, - basic_block, - gimple_stmt_iterator); +static void optimize_stmt (basic_block, gimple_stmt_iterator); static tree lookup_avail_expr (gimple, bool); static hashval_t avail_expr_hash (const void *); static hashval_t real_avail_expr_hash (const void *); @@ -199,9 +197,8 @@ static void record_equivalences_from_incoming_edge (basic_block); static bool 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_finalize_block (struct dom_walk_data *, basic_block); -static void dom_opt_initialize_block (struct dom_walk_data *, basic_block); -static void propagate_to_outgoing_edges (struct dom_walk_data *, basic_block); +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); @@ -630,21 +627,15 @@ tree_ssa_dominator_optimize (void) need_eh_cleanup = BITMAP_ALLOC (NULL); /* Setup callbacks for the generic dominator tree walker. */ - walk_data.walk_stmts_backward = false; walk_data.dom_direction = CDI_DOMINATORS; walk_data.initialize_block_local_data = NULL; - walk_data.before_dom_children_before_stmts = dom_opt_initialize_block; - walk_data.before_dom_children_walk_stmts = optimize_stmt; - walk_data.before_dom_children_after_stmts = propagate_to_outgoing_edges; - walk_data.after_dom_children_before_stmts = NULL; - walk_data.after_dom_children_walk_stmts = NULL; - walk_data.after_dom_children_after_stmts = dom_opt_finalize_block; + 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; - walk_data.interesting_blocks = NULL; /* Now initialize the dominator walker. */ init_walk_dominator_tree (&walk_data); @@ -827,24 +818,6 @@ canonicalize_comparison (gimple condstmt) upon entry to BB. Equivalences can come from the edge traversed to reach BB or they may come from PHI nodes at the start of BB. */ -static void -dom_opt_initialize_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED, - basic_block bb) -{ - if (dump_file && (dump_flags & TDF_DETAILS)) - fprintf (dump_file, "\n\nOptimizing block #%d\n\n", bb->index); - - /* Push a marker on the stacks of local information so that we know how - far to unwind when we finalize this block. */ - VEC_safe_push (expr_hash_elt_t, heap, avail_exprs_stack, NULL); - VEC_safe_push (tree, heap, const_and_copies_stack, NULL_TREE); - - record_equivalences_from_incoming_edge (bb); - - /* PHI nodes can create equivalences too. */ - record_equivalences_from_phis (bb); -} - /* Remove all the expressions in LOCALS from TABLE, stopping when there are LIMIT entries left in LOCALs. */ @@ -935,131 +908,6 @@ dom_thread_across_edge (struct dom_walk_data *walk_data, edge e) simplify_stmt_for_jump_threading); } -/* We have finished processing the dominator children of BB, perform - any finalization actions in preparation for leaving this node in - the dominator tree. */ - -static void -dom_opt_finalize_block (struct dom_walk_data *walk_data, basic_block bb) -{ - gimple last; - - /* If we have an outgoing edge to a block with multiple incoming and - outgoing edges, then we may be able to thread the edge, i.e., we - may be able to statically determine which of the outgoing edges - will be traversed when the incoming edge from BB is traversed. */ - if (single_succ_p (bb) - && (single_succ_edge (bb)->flags & EDGE_ABNORMAL) == 0 - && potentially_threadable_block (single_succ (bb))) - { - dom_thread_across_edge (walk_data, single_succ_edge (bb)); - } - else if ((last = last_stmt (bb)) - && gimple_code (last) == GIMPLE_COND - && EDGE_COUNT (bb->succs) == 2 - && (EDGE_SUCC (bb, 0)->flags & EDGE_ABNORMAL) == 0 - && (EDGE_SUCC (bb, 1)->flags & EDGE_ABNORMAL) == 0) - { - edge true_edge, false_edge; - - extract_true_false_edges_from_block (bb, &true_edge, &false_edge); - - /* Only try to thread the edge if it reaches a target block with - more than one predecessor and more than one successor. */ - if (potentially_threadable_block (true_edge->dest)) - { - struct edge_info *edge_info; - unsigned int i; - - /* Push a marker onto the available expression stack so that we - unwind any expressions related to the TRUE arm before processing - the false arm below. */ - VEC_safe_push (expr_hash_elt_t, heap, avail_exprs_stack, NULL); - VEC_safe_push (tree, heap, const_and_copies_stack, NULL_TREE); - - edge_info = (struct edge_info *) true_edge->aux; - - /* If we have info associated with this edge, record it into - our equivalence tables. */ - if (edge_info) - { - struct cond_equivalence *cond_equivalences = edge_info->cond_equivalences; - tree lhs = edge_info->lhs; - tree rhs = edge_info->rhs; - - /* If we have a simple NAME = VALUE equivalence, record it. */ - if (lhs && TREE_CODE (lhs) == SSA_NAME) - record_const_or_copy (lhs, rhs); - - /* If we have 0 = COND or 1 = COND equivalences, record them - into our expression hash tables. */ - if (cond_equivalences) - for (i = 0; i < edge_info->max_cond_equivalences; i++) - record_cond (&cond_equivalences[i]); - } - - dom_thread_across_edge (walk_data, true_edge); - - /* And restore the various tables to their state before - we threaded this edge. */ - remove_local_expressions_from_table (); - } - - /* Similarly for the ELSE arm. */ - if (potentially_threadable_block (false_edge->dest)) - { - struct edge_info *edge_info; - unsigned int i; - - VEC_safe_push (tree, heap, const_and_copies_stack, NULL_TREE); - edge_info = (struct edge_info *) false_edge->aux; - - /* If we have info associated with this edge, record it into - our equivalence tables. */ - if (edge_info) - { - struct cond_equivalence *cond_equivalences = edge_info->cond_equivalences; - tree lhs = edge_info->lhs; - tree rhs = edge_info->rhs; - - /* If we have a simple NAME = VALUE equivalence, record it. */ - if (lhs && TREE_CODE (lhs) == SSA_NAME) - record_const_or_copy (lhs, rhs); - - /* If we have 0 = COND or 1 = COND equivalences, record them - into our expression hash tables. */ - if (cond_equivalences) - for (i = 0; i < edge_info->max_cond_equivalences; i++) - record_cond (&cond_equivalences[i]); - } - - /* Now thread the edge. */ - dom_thread_across_edge (walk_data, false_edge); - - /* No need to remove local expressions from our tables - or restore vars to their original value as that will - be done immediately below. */ - } - } - - remove_local_expressions_from_table (); - restore_vars_to_original_value (); - - /* If we queued any statements to rescan in this block, then - go ahead and rescan them now. */ - while (VEC_length (gimple, stmts_to_rescan) > 0) - { - gimple stmt = VEC_last (gimple, stmts_to_rescan); - basic_block stmt_bb = gimple_bb (stmt); - - if (stmt_bb != bb) - break; - - VEC_pop (gimple, stmts_to_rescan); - update_stmt (stmt); - } -} - /* PHI nodes can create equivalences too. Ignoring any alternatives which are the same as the result, if @@ -1787,20 +1635,158 @@ record_edge_info (basic_block bb) } } -/* Propagate information from BB to its outgoing edges. - - This can include equivalence information implied by control statements - at the end of BB and const/copy propagation into PHIs in BB's - successor blocks. */ - static void -propagate_to_outgoing_edges (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED, - basic_block bb) +dom_opt_enter_block (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED, + basic_block bb) { + gimple_stmt_iterator gsi; + + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "\n\nOptimizing block #%d\n\n", bb->index); + + /* Push a marker on the stacks of local information so that we know how + far to unwind when we finalize this block. */ + VEC_safe_push (expr_hash_elt_t, heap, avail_exprs_stack, NULL); + VEC_safe_push (tree, heap, const_and_copies_stack, NULL_TREE); + + record_equivalences_from_incoming_edge (bb); + + /* PHI nodes can create equivalences too. */ + record_equivalences_from_phis (bb); + + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + optimize_stmt (bb, gsi); + + /* Now prepare to process dominated blocks. */ record_edge_info (bb); cprop_into_successor_phis (bb); } +/* We have finished processing the dominator children of BB, perform + 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) +{ + gimple last; + + /* If we have an outgoing edge to a block with multiple incoming and + outgoing edges, then we may be able to thread the edge, i.e., we + may be able to statically determine which of the outgoing edges + will be traversed when the incoming edge from BB is traversed. */ + if (single_succ_p (bb) + && (single_succ_edge (bb)->flags & EDGE_ABNORMAL) == 0 + && potentially_threadable_block (single_succ (bb))) + { + dom_thread_across_edge (walk_data, single_succ_edge (bb)); + } + else if ((last = last_stmt (bb)) + && gimple_code (last) == GIMPLE_COND + && EDGE_COUNT (bb->succs) == 2 + && (EDGE_SUCC (bb, 0)->flags & EDGE_ABNORMAL) == 0 + && (EDGE_SUCC (bb, 1)->flags & EDGE_ABNORMAL) == 0) + { + edge true_edge, false_edge; + + extract_true_false_edges_from_block (bb, &true_edge, &false_edge); + + /* Only try to thread the edge if it reaches a target block with + more than one predecessor and more than one successor. */ + if (potentially_threadable_block (true_edge->dest)) + { + struct edge_info *edge_info; + unsigned int i; + + /* Push a marker onto the available expression stack so that we + unwind any expressions related to the TRUE arm before processing + the false arm below. */ + VEC_safe_push (expr_hash_elt_t, heap, avail_exprs_stack, NULL); + VEC_safe_push (tree, heap, const_and_copies_stack, NULL_TREE); + + edge_info = (struct edge_info *) true_edge->aux; + + /* If we have info associated with this edge, record it into + our equivalence tables. */ + if (edge_info) + { + struct cond_equivalence *cond_equivalences = edge_info->cond_equivalences; + tree lhs = edge_info->lhs; + tree rhs = edge_info->rhs; + + /* If we have a simple NAME = VALUE equivalence, record it. */ + if (lhs && TREE_CODE (lhs) == SSA_NAME) + record_const_or_copy (lhs, rhs); + + /* If we have 0 = COND or 1 = COND equivalences, record them + into our expression hash tables. */ + if (cond_equivalences) + for (i = 0; i < edge_info->max_cond_equivalences; i++) + record_cond (&cond_equivalences[i]); + } + + dom_thread_across_edge (walk_data, true_edge); + + /* And restore the various tables to their state before + we threaded this edge. */ + remove_local_expressions_from_table (); + } + + /* Similarly for the ELSE arm. */ + if (potentially_threadable_block (false_edge->dest)) + { + struct edge_info *edge_info; + unsigned int i; + + VEC_safe_push (tree, heap, const_and_copies_stack, NULL_TREE); + edge_info = (struct edge_info *) false_edge->aux; + + /* If we have info associated with this edge, record it into + our equivalence tables. */ + if (edge_info) + { + struct cond_equivalence *cond_equivalences = edge_info->cond_equivalences; + tree lhs = edge_info->lhs; + tree rhs = edge_info->rhs; + + /* If we have a simple NAME = VALUE equivalence, record it. */ + if (lhs && TREE_CODE (lhs) == SSA_NAME) + record_const_or_copy (lhs, rhs); + + /* If we have 0 = COND or 1 = COND equivalences, record them + into our expression hash tables. */ + if (cond_equivalences) + for (i = 0; i < edge_info->max_cond_equivalences; i++) + record_cond (&cond_equivalences[i]); + } + + /* Now thread the edge. */ + dom_thread_across_edge (walk_data, false_edge); + + /* No need to remove local expressions from our tables + or restore vars to their original value as that will + be done immediately below. */ + } + } + + remove_local_expressions_from_table (); + restore_vars_to_original_value (); + + /* If we queued any statements to rescan in this block, then + go ahead and rescan them now. */ + while (VEC_length (gimple, stmts_to_rescan) > 0) + { + gimple stmt = VEC_last (gimple, stmts_to_rescan); + basic_block stmt_bb = gimple_bb (stmt); + + if (stmt_bb != bb) + break; + + VEC_pop (gimple, stmts_to_rescan); + update_stmt (stmt); + } +} + /* Search for redundant computations in STMT. If any are found, then replace them with the variable holding the result of the computation. @@ -2114,8 +2100,7 @@ cprop_into_stmt (gimple stmt) the variable in the LHS in the CONST_AND_COPIES table. */ static void -optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED, - basic_block bb, gimple_stmt_iterator si) +optimize_stmt (basic_block bb, gimple_stmt_iterator si) { gimple stmt, old_stmt; bool may_optimize_p; |