X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fir%2Frm_bads.c;h=831a646c9dc753692d5bf9e6e3a084d23cd7156b;hb=2f8553d98a05815a9d24eb5746cab1e17858a2a0;hp=3bdae72aba0767f0ef78f23a9d513d0fb4fa6065;hpb=1cf50338e8a4db0b308ff38f2214242d9f3b79f7;p=libfirm diff --git a/ir/ir/rm_bads.c b/ir/ir/rm_bads.c index 3bdae72ab..831a646c9 100644 --- a/ir/ir/rm_bads.c +++ b/ir/ir/rm_bads.c @@ -38,7 +38,7 @@ */ static int count_non_bads(ir_node *node) { - int arity = get_irn_arity(node); + int arity = get_Block_n_cfgpreds(node); int count = 0; int i; for (i = 0; i < arity; ++i) { @@ -52,26 +52,23 @@ static int count_non_bads(ir_node *node) * Block-walker, remove Bad block predecessors and shorten Phis. * Phi links must be uptodate. */ -static void block_remove_bads(ir_node *block, void *env) +static void block_remove_bads(ir_node *block) { - int *changed = (int *)env; - int i, j; - ir_node **new_in, *new_block, *phi; - const int max = get_irn_arity(block); - const int new_max = count_non_bads(block); + ir_graph *irg = get_irn_irg(block); + const int max = get_Block_n_cfgpreds(block); + const int new_max = count_non_bads(block); + ir_node **new_in = ALLOCAN(ir_node*, new_max); + int i; + int j; + ir_node *new_block; + ir_node *phi; + ir_node *next; + ir_entity *block_entity; assert(max >= new_max); - if (is_Bad(block) || max == new_max) - return; - - new_in = ALLOCAN(ir_node*, new_max); - *changed = 1; - - assert(get_Block_dom_depth(block) >= 0); - /* 1. Create a new block without Bad inputs */ for (i = j = 0; i < max; ++i) { - ir_node *block_pred = get_irn_n(block, i); + ir_node *const block_pred = get_Block_cfgpred(block, i); if (!is_Bad(block_pred)) { new_in[j++] = block_pred; } @@ -80,62 +77,73 @@ static void block_remove_bads(ir_node *block, void *env) /* If the end block is unreachable, it might have zero predecessors. */ if (new_max == 0) { - ir_node *end_block = get_irg_end_block(get_irn_irg(block)); + ir_node *end_block = get_irg_end_block(irg); if (block == end_block) { set_irn_in(block, new_max, new_in); return; } } - new_block = new_r_Block(get_irn_irg(block), new_max, new_in); + new_block = new_r_Block(irg, new_max, new_in); + block_entity = get_Block_entity(block); + if (block_entity) + set_Block_entity(new_block, block_entity); /* 2. Remove inputs on Phis, where the block input is Bad. */ - phi = get_Block_phis(block); - if (phi != NULL) { - do { - ir_node *next = get_Phi_next(phi); - if (get_irn_arity(phi) != new_max) { - ir_node *new_phi; - - for (i = j = 0; i < max; ++i) { - ir_node *block_pred = get_irn_n(block, i); - - if (!is_Bad(block_pred)) { - ir_node *pred = get_irn_n(phi, i); - new_in[j++] = pred; - } - } - assert(j == new_max); - - new_phi = new_r_Phi(new_block, new_max, new_in, get_irn_mode(phi)); - exchange(phi, new_phi); + for (phi = get_Block_phis(block); phi != NULL; phi = next) { + ir_node *new_phi; + + next = get_Phi_next(phi); + assert(get_irn_arity(phi) == max); + + for (i = j = 0; i < max; ++i) { + ir_node *const block_pred = get_Block_cfgpred(block, i); + if (!is_Bad(block_pred)) { + ir_node *pred = get_irn_n(phi, i); + new_in[j++] = pred; } - phi = next; - } while (phi != NULL); + } + assert(j == new_max); + + new_phi = new_r_Phi(new_block, new_max, new_in, get_irn_mode(phi)); + exchange(phi, new_phi); } exchange(block, new_block); } -/* Remove Bad nodes from Phi and Block inputs. - * - * This does NOT remove unreachable code. - * - * Postcondition: No Bad nodes. - */ -int remove_bads(ir_graph *irg) +static void collect(ir_node *node, void *env) +{ + firm_collect_block_phis(node, NULL); + if (is_Block(node)) { + ir_node ***blocks_to_process = (ir_node***)env; + int arity = get_Block_n_cfgpreds(node); + int non_bads = count_non_bads(node); + if (arity != non_bads) + ARR_APP1(ir_node*, *blocks_to_process, node); + } +} + +void remove_bads(ir_graph *irg) { - int changed = 0; + size_t i; + size_t n_to_process; + ir_node **blocks_to_process = NEW_ARR_F(ir_node*, 0); + /* build phi list per block */ - irg_walk_graph(irg, firm_clear_block_phis, firm_collect_block_phis, NULL); + irg_walk_graph(irg, firm_clear_block_phis, collect, &blocks_to_process); - /* actually remove Bads */ - irg_block_walk_graph(irg, NULL, block_remove_bads, (void *)&changed); + n_to_process = ARR_LEN(blocks_to_process); + for (i = 0; i < n_to_process; ++i) { + ir_node *block = blocks_to_process[i]; + block_remove_bads(block); + } + DEL_ARR_F(blocks_to_process); - if (changed) { + if (n_to_process > 0) { edges_deactivate(irg); - set_irg_outs_inconsistent(irg); + clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_OUTS); + clear_irg_properties(irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE); } - - return changed; + add_irg_properties(irg, IR_GRAPH_PROPERTY_NO_BADS); }