X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fcfopt.c;h=1569db97f320cf51f3a1f480a8340b4199b21ab7;hb=f1a1a6092d9e4ebd9e22dd1c57d76ef8aeda74fc;hp=107039a32963d9592b6b4a5d0efd3232afa070fc;hpb=a35b27fb6714965db9163831357b77ecbfb29a63;p=libfirm diff --git a/ir/opt/cfopt.c b/ir/opt/cfopt.c index 107039a32..1569db97f 100644 --- a/ir/opt/cfopt.c +++ b/ir/opt/cfopt.c @@ -36,6 +36,7 @@ #include "firmstat.h" #include "cfopt.h" +#include "iropt_dbg.h" /*------------------------------------------------------------------*/ /* Control flow optimization. */ @@ -50,13 +51,13 @@ * Replace binary Conds that jumps twice into the same block * by a simple Jmp. * E.g. - * @code + * @verbatim * Cond Jmp Bad * / \ | / * ProjX True ProjX False ==> | / * \ / | / * Block Block - * @endcode + * @endverbatim * * Such pattern are the result of if-conversion. * @@ -65,32 +66,32 @@ */ static void remove_senseless_conds(ir_node *bl, void *data) { - int i, j; - int n = get_Block_n_cfgpreds(bl); + int i, j; + int n = get_Block_n_cfgpreds(bl); - assert(is_Block(bl)); + assert(is_Block(bl)); - for (i = 0; i < n; ++i) { - ir_node *pred_i = get_Block_cfgpred(bl, i); - ir_node *cond_i = skip_Proj(pred_i); + for (i = 0; i < n; ++i) { + ir_node *pred_i = get_Block_cfgpred(bl, i); + ir_node *cond_i = skip_Proj(pred_i); - for (j = i + 1; j < n; ++j) { - ir_node *pred_j = get_Block_cfgpred(bl, j); - ir_node *cond_j = skip_Proj(pred_j); + for (j = i + 1; j < n; ++j) { + ir_node *pred_j = get_Block_cfgpred(bl, j); + ir_node *cond_j = skip_Proj(pred_j); - if (cond_j == cond_i - && get_irn_op(cond_i) == op_Cond - && get_irn_mode(get_Cond_selector(cond_i)) == mode_b) { + if (cond_j == cond_i + && get_irn_op(cond_i) == op_Cond + && get_irn_mode(get_Cond_selector(cond_i)) == mode_b) { - ir_node *jmp = new_r_Jmp(current_ir_graph, get_nodes_block(cond_i)); - set_irn_n(bl, i, jmp); - set_irn_n(bl, j, new_Bad()); + ir_node *jmp = new_r_Jmp(current_ir_graph, get_nodes_block(cond_i)); + set_irn_n(bl, i, jmp); + set_irn_n(bl, j, new_Bad()); DBG_OPT_IFSIM2(cond_i, jmp); - break; - } - } - } + break; + } + } + } } @@ -119,17 +120,17 @@ static void merge_blocks(ir_node *n, void *env) { /* see below */ new_block = equivalent_node(n); - if (new_block != n && ! is_Bad(new_block)) + if (new_block != n && ! is_Block_dead(new_block)) exchange (n, new_block); } else if (get_opt_optimize() && (get_irn_mode(n) == mode_X)) { /* We will soon visit a block. Optimize it before visiting! */ ir_node *b = get_nodes_block(skip_Proj(n)); - if (!is_Bad(b)) { + if (!is_Block_dead(b)) { new_block = equivalent_node(b); - while (irn_not_visited(b) && (!is_Bad(new_block)) && (new_block != b)) { + while (irn_not_visited(b) && (!is_Block_dead(new_block)) && (new_block != b)) { /* We would have to run gigo() if new is bad, so we promote it directly below. Nevertheless, we sometimes reach a block the first time through a dataflow node. In this case we optimized the @@ -145,7 +146,7 @@ static void merge_blocks(ir_node *n, void *env) { /* normally, we would create a Bad block here, but this must be * prevented, so just set it's cf to Bad. */ - if (is_Bad(new_block)) + if (is_Block_dead(new_block)) exchange(n, new_Bad()); } } @@ -170,7 +171,7 @@ static void remove_dead_block_cf(ir_node *block, void *env) if (! is_Bad(pred_X)) { ir_node *pred_bl = get_nodes_block(skip_Proj(pred_X)); - if (is_Bad(pred_bl) || (get_Block_dom_depth(pred_bl) == -1)) + if (is_Block_dead(pred_bl) || (get_Block_dom_depth(pred_bl) < 0)) exchange (pred_X, new_Bad()); } } @@ -220,21 +221,22 @@ static int is_pred_of(ir_node *pred, ir_node *b) { * The test is rather tricky. * * The situation is something like the following: - * + * @verbatim * if-block * / \ * then-b else-b * \ / * b + * @endverbatim * - * b merges the control flow of an if-then-else. We may not remove - * the 'then' _and_ the 'else' block of an 'if' if there is a Phi - * node in b, even if both are empty. The destruction of this Phi - * requires that a copy is added before the merge. We have to - * keep one of the case blocks to place the copies in. + * b merges the control flow of an if-then-else. We may not remove + * the 'then' _and_ the 'else' block of an 'if' if there is a Phi + * node in b, even if both are empty. The destruction of this Phi + * requires that a copy is added before the merge. We have to + * keep one of the case blocks to place the copies in. * - * To perform the test for pos, we must regard predecessors before pos - * as already removed. + * To perform the test for pos, we must regard predecessors before pos + * as already removed. **/ static int test_whether_dispensable(ir_node *b, int pos) { int i, j, n_preds = 1; @@ -301,22 +303,23 @@ static int test_whether_dispensable(ir_node *b, int pos) { * for all nodes, not regarding whether there is a possibility for optimization. * * For each predecessor p of a Block b there are three cases: - * 1. The predecessor p is a Bad node: just skip it. The in array of b shrinks by one. - * 2. The predecessor p is empty. Remove p. All predecessors of p are now - * predecessors of b. - * 3. The predecessor p is a block containing useful code. Just keep p as is. + * -#. The predecessor p is a Bad node: just skip it. The in array of b shrinks by one. + * -#. The predecessor p is empty. Remove p. All predecessors of p are now + * predecessors of b. + * -#. The predecessor p is a block containing useful code. Just keep p as is. * * For Phi nodes f we have to check the conditions at the Block of f. * For cases 1 and 3 we proceed as for Blocks. For case 2 we can have two * cases: - * 2a: The old predecessor of the Phi f is a Phi pred_f IN THE BLOCK REMOVED. In this + * -2a: The old predecessor of the Phi f is a Phi pred_f IN THE BLOCK REMOVED. In this * case we proceed as for blocks. We remove pred_f. All * predecessors of pred_f now are predecessors of f. - * 2b: The old predecessor of f is NOT in the block removed. It might be a Phi, too. + * -2b: The old predecessor of f is NOT in the block removed. It might be a Phi, too. * We have to replicate f for each predecessor of the removed block. Or, with * other words, the removed predecessor block has exactly one predecessor. * * Further there is a special case for self referencing blocks: + * @verbatim * * then_b else_b then_b else_b * \ / \ / @@ -329,6 +332,7 @@ static int test_whether_dispensable(ir_node *b, int pos) { * | | | | | | * | |____| | |____| * | | + * @endverbatim * * If there is a Phi in pred_b, but we remove pred_b, we have to generate a * Phi in loop_b, that has the ins of the Phi in pred_b and a self referencing @@ -569,6 +573,10 @@ void optimize_cf(ir_graph *irg) { irg_dom_state dom_state = get_irg_dom_state(current_ir_graph); current_ir_graph = irg; + /* if the graph is not pinned, we cannot determine empty blocks */ + assert(get_irg_pinned(irg) != op_pin_state_floats && + "Control flow optimization need a pinned graph"); + /* Handle graph state */ assert(get_irg_phase_state(irg) != phase_building); if (get_irg_outs_state(current_ir_graph) == outs_consistent) @@ -586,9 +594,11 @@ void optimize_cf(ir_graph *irg) { for (i = 0, n = get_End_n_keepalives(end); i < n; ++i) { ir_node *ka = get_End_keepalive(end, i); - if (is_Block(ka) && (get_Block_dom_depth(ka) == -1)) - set_End_keepalive(end, i, new_Bad()); - if (is_Phi(ka) && (get_Block_dom_depth(get_nodes_block(ka)) == -1)) + if (is_Block(ka)) { + if (get_Block_dom_depth(ka) == -1) + set_End_keepalive(end, i, new_Bad()); + } + else if (get_Block_dom_depth(get_nodes_block(ka)) == -1) set_End_keepalive(end, i, new_Bad()); } } @@ -621,6 +631,9 @@ void optimize_cf(ir_graph *irg) { } else if (get_irn_op(ka) == op_Phi) { mark_irn_visited(ka); ARR_APP1 (ir_node *, in, ka); + } else if (get_irn_op(ka) == op_IJmp) { + mark_irn_visited(ka); + ARR_APP1 (ir_node *, in, ka); } } }