From: Matthias Braun Date: Fri, 16 Sep 2011 13:54:00 +0000 (+0200) Subject: change unreachable code elmination to the simpler remove links into unreachable code... X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=30a48b51f75dab1a41560ba21f4ac0ab59e3a189;p=libfirm change unreachable code elmination to the simpler remove links into unreachable code scheme --- diff --git a/include/libfirm/irgopt.h b/include/libfirm/irgopt.h index a4cf9f701..f7f9e1f24 100644 --- a/include/libfirm/irgopt.h +++ b/include/libfirm/irgopt.h @@ -59,9 +59,9 @@ FIRM_API void local_optimize_graph(ir_graph *irg); FIRM_API int optimize_graph_df(ir_graph *irg); /** - * Transforms unreachable blocks and nodes in there into Bad nodes + * Eliminates (obviously) unreachable code */ -FIRM_API void remove_unreachable_blocks(ir_graph *irg); +FIRM_API void remove_unreachable_code(ir_graph *irg); /** * Removes all Bad nodes from a graph. diff --git a/ir/be/bemain.c b/ir/be/bemain.c index f85257a5b..d02d54342 100644 --- a/ir/be/bemain.c +++ b/ir/be/bemain.c @@ -414,7 +414,7 @@ static void initialize_birg(be_irg_t *birg, ir_graph *irg, be_main_env_t *env) current_ir_graph = irg; /* For code generation all unreachable code and Bad nodes should be gone */ - remove_unreachable_blocks(irg); + remove_unreachable_code(irg); remove_bads(irg); /* we do this before critical edge split. As this produces less returns, diff --git a/ir/ir/unreachable.c b/ir/ir/unreachable.c index c52bee288..dbb033ae7 100644 --- a/ir/ir/unreachable.c +++ b/ir/ir/unreachable.c @@ -14,11 +14,16 @@ */ /** - * @brief Convert all unreachable blocks into Bad nodes + * @brief Remove unreachable code * @author Andreas Zwinkau + * + * This is done by elminiating all edges into the unreachable code. So that + * after that the unreachable code should be dead. */ #include "config.h" +#include "irgopt.h" + #include #include @@ -28,45 +33,101 @@ #include "irgwalk.h" #include "irtools.h" +static bool is_block_unreachable(ir_node *block) +{ + return get_Block_dom_depth(block) < 0; +} + /** - * Block-walker + * Eliminate block- and phi-inputs pointing to unreachable code */ static void unreachable_to_bad(ir_node *node, void *env) { bool *changed = (bool *)env; - ir_graph *irg = get_irn_irg(node); if (is_Block(node)) { - if (get_Block_dom_depth(node) < 0) { - exchange(node, new_r_Bad(irg, mode_BB)); + ir_graph *irg; + int arity; + int i; + /* optimisation: we do not have to do anything inside the unreachable + * code */ + if (is_block_unreachable(node)) + return; + + arity = get_irn_arity(node); + irg = get_irn_irg(node); + for (i = 0; i < arity; ++i) { + ir_node *pred = get_Block_cfgpred(node, i); + if (is_Bad(pred) || !is_block_unreachable(get_nodes_block(pred))) + continue; + set_irn_n(node, i, new_r_Bad(irg, mode_X)); *changed = true; } - } else if (is_Bad(node)) { - /* nothing to do */ - } else { - ir_node *block = get_nodes_block(node); - if (is_Bad(block) || get_Block_dom_depth(block) < 0) { - exchange(node, new_r_Bad(irg, get_irn_mode(node))); + } else if (is_Phi(node)) { + ir_node *block = get_nodes_block(node); + int arity; + int i; + ir_graph *irg; + /* optimisation: we do not have to do anything inside the unreachable + * code */ + if (is_block_unreachable(block)) + return; + + irg = get_irn_irg(node); + arity = get_irn_arity(node); + for (i = 0; i < arity; ++i) { + ir_node *block_pred; + ir_node *phi_pred = get_irn_n(node, i); + if (is_Bad(phi_pred)) + continue; + block_pred = get_Block_cfgpred(block, i); + if (!is_Bad(block_pred) && !is_block_unreachable(get_nodes_block(block_pred))) + continue; + + set_irn_n(node, i, new_r_Bad(irg, get_irn_mode(node))); *changed = true; } } } -/* - * Transforms unreachable blocks and the nodes within into Bad nodes +/** + * remove kept nodes in unreachable blocks */ -void remove_unreachable_blocks(ir_graph *irg) +static void remove_unreachable_keeps(ir_graph *irg) +{ + ir_node *end = get_irg_end(irg); + int arity = get_irn_arity(end); + ir_node **new_in = XMALLOCN(ir_node*, arity); + int new_arity = 0; + int i; + + for (i = 0; i < arity; ++i) { + ir_node *ka = get_End_keepalive(end, i); + ir_node *block = is_Block(ka) ? ka : get_nodes_block(ka); + if (is_block_unreachable(block)) + continue; + new_in[new_arity++] = ka; + } + if (new_arity != arity) + set_End_keepalives(end, new_arity, new_in); + free(new_in); +} + +void remove_unreachable_code(ir_graph *irg) { bool changed = false; assure_doms(irg); irg_walk_graph(irg, unreachable_to_bad, NULL, &changed); + remove_unreachable_keeps(irg); if (changed) { edges_deactivate(irg); - clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS); - clear_irg_state(irg, IR_GRAPH_STATE_NO_BADS); + clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_OUTS + | IR_GRAPH_STATE_NO_BADS + | IR_GRAPH_STATE_CONSISTENT_OUT_EDGES + | IR_GRAPH_STATE_CONSISTENT_LOOPINFO); } set_irg_state(irg, IR_GRAPH_STATE_NO_UNREACHABLE_CODE); } diff --git a/ir/opt/opt_manage.c b/ir/opt/opt_manage.c index 327595ce3..1ffe76454 100644 --- a/ir/opt/opt_manage.c +++ b/ir/opt/opt_manage.c @@ -29,7 +29,7 @@ void perform_irg_optimization(ir_graph *irg, optdesc_t *opt) #define PREPARE(st,func) if (st & (required ^ irg->state)) {func(irg); set_irg_state(irg,st);} PREPARE(IR_GRAPH_STATE_ONE_RETURN, normalize_one_return) PREPARE(IR_GRAPH_STATE_NO_CRITICAL_EDGES, remove_critical_cf_edges) - PREPARE(IR_GRAPH_STATE_NO_UNREACHABLE_CODE, remove_unreachable_blocks) + PREPARE(IR_GRAPH_STATE_NO_UNREACHABLE_CODE, remove_unreachable_code) PREPARE(IR_GRAPH_STATE_NO_BADS, remove_bads) PREPARE(IR_GRAPH_STATE_CONSISTENT_DOMINANCE, assure_doms) PREPARE(IR_GRAPH_STATE_CONSISTENT_POSTDOMINANCE, assure_postdoms)