X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Funreachable.c;h=a66a054dbf5327a324419dbbcf1a70298b6fb708;hb=3db23eee84cbabb3f399f1ca820948114a9c837c;hp=c52bee288e6d200c0ae37fbd46c900c33576ed6f;hpb=e9bb88e839f3ec18454a968adf3236d1dc0d812f;p=libfirm diff --git a/ir/ir/unreachable.c b/ir/ir/unreachable.c index c52bee288..a66a054db 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,100 @@ #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); + assure_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE); 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); - } - set_irg_state(irg, IR_GRAPH_STATE_NO_UNREACHABLE_CODE); + confirm_irg_properties(irg, changed + ? IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES + | IR_GRAPH_PROPERTY_NO_TUPLES + | IR_GRAPH_PROPERTY_ONE_RETURN + | IR_GRAPH_PROPERTY_MANY_RETURNS + : IR_GRAPH_PROPERTIES_ALL); + add_irg_properties(irg, IR_GRAPH_PROPERTY_NO_UNREACHABLE_CODE); }