X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fopt%2Fcode_placement.c;h=0cc25b353c928c8c9d22534db86cda5e4ffa8fc0;hb=babe0f4cc35d4b25e34e62a07324e2dd061e7cc8;hp=72fbdb95e33ddafc3ecbfcdb9a93a3097f68f5f2;hpb=ae9fd2c229cc7f4c724ce9ccc9263c16d77670fe;p=libfirm diff --git a/ir/opt/code_placement.c b/ir/opt/code_placement.c index 72fbdb95e..0cc25b353 100644 --- a/ir/opt/code_placement.c +++ b/ir/opt/code_placement.c @@ -23,7 +23,6 @@ * often. * @author Christian Schaefer, Goetz Lindenmaier, Sebastian Felis, * Michael Beck - * @version $Id$ * * The idea here is to push nodes as deep into the dominance tree as their * dependencies allow. After pushing them back up out of as many loops as @@ -36,7 +35,7 @@ #include "iroptimize.h" #include "adt/pdeq.h" #include "irnode_t.h" -#include "irouts.h" +#include "iredges_t.h" #include "irgopt.h" #include "irpass.h" @@ -45,6 +44,25 @@ static bool is_block_reachable(ir_node *block) return get_Block_dom_depth(block) >= 0; } +/** + * Firm keepalive edges are broken (the user should really be the endless loop + * and not the End node.) This wrong place of the user will lead to wrong + * results in place_early()/place_late(). We work around these problems by not + * moving nodes which just have keepalive edges as their users (or no users at + * all) + */ +static bool float_exceptions(const ir_node *node) +{ + foreach_out_edge(node, edge) { + ir_node *succ = get_edge_src_irn(edge); + if (is_End(succ)) + continue; + /* found a real user */ + return false; + } + return true; +} + /** * Find the earliest correct block for node n. --- Place n into the * same Block as its dominance-deepest Input. @@ -82,7 +100,7 @@ static void place_floats_early(ir_node *n, waitq *worklist) * This works because in firm each cycle contains a Phi or Block node * (which are pinned) */ - if (get_irn_pinned(n) != op_pin_state_floats) { + if (get_irn_pinned(n) != op_pin_state_floats || float_exceptions(n)) { /* we can't move pinned nodes */ arity = get_irn_arity(n); for (i = 0; i < arity; ++i) { @@ -95,10 +113,6 @@ static void place_floats_early(ir_node *n, waitq *worklist) } block = get_nodes_block(n); - /* do not move unreachable code (or its predecessors around) since dominance - * is inalid there */ - if (!is_block_reachable(block)) - return; /* first move predecessors up */ arity = get_irn_arity(n); @@ -126,8 +140,9 @@ static void place_floats_early(ir_node *n, waitq *worklist) start_block = get_irg_start_block(irg); if (new_block == start_block && block != start_block && get_irg_phase_state(irg) != phase_backend) { - assert(get_Block_n_cfg_outs(start_block) == 1); - new_block = get_Block_cfg_out(start_block, 0); + assert(get_irn_n_edges_kind(start_block, EDGE_KIND_BLOCK) == 1); + const ir_edge_t *edge = get_block_succ_first(start_block); + new_block = get_edge_src_irn(edge); } /* Set the new block */ @@ -215,8 +230,8 @@ static ir_node *consumer_dom_dca(ir_node *dca, ir_node *consumer, if (is_Bad(new_block)) continue; - if (is_block_reachable(new_block)) - dca = calc_dom_dca(dca, new_block); + assert(is_block_reachable(new_block)); + dca = calc_dom_dca(dca, new_block); } } } else { @@ -271,10 +286,8 @@ static void move_out_of_loops(ir_node *n, ir_node *early) */ static ir_node *get_deepest_common_dom_ancestor(ir_node *node, ir_node *dca) { - int i; - - for (i = get_irn_n_outs(node) - 1; i >= 0; --i) { - ir_node *succ = get_irn_out(node, i); + foreach_out_edge(node, edge) { + ir_node *succ = get_edge_src_irn(edge); /* keepalive edges are special and don't respect the dominance */ if (is_End(succ)) @@ -285,13 +298,15 @@ static ir_node *get_deepest_common_dom_ancestor(ir_node *node, ir_node *dca) * the users of Proj are our users. */ dca = get_deepest_common_dom_ancestor(succ, dca); } else { - /* ignore successors in unreachable code */ - ir_node *succ_blk = get_nodes_block(succ); - if (!is_block_reachable(succ_blk)) - continue; + assert(is_block_reachable(get_nodes_block(succ))); dca = consumer_dom_dca(dca, succ, node); } } + foreach_out_edge_kind(node, edge, EDGE_KIND_DEP) { + ir_node *succ = get_edge_src_irn(edge); + assert(is_block_reachable(get_nodes_block(succ))); + dca = consumer_dom_dca(dca, succ, node); + } return dca; } @@ -303,17 +318,16 @@ static ir_node *get_deepest_common_dom_ancestor(ir_node *node, ir_node *dca) */ static void set_projs_block(ir_node *node, ir_node *block) { - int i; - - for (i = get_irn_n_outs(node) - 1; i >= 0; --i) { - ir_node *succ = get_irn_out(node, i); + foreach_out_edge(node, edge) { + ir_node *succ = get_edge_src_irn(edge); - assert(is_Proj(succ)); + if (!is_Proj(succ)) + continue; + set_nodes_block(succ, block); if (get_irn_mode(succ) == mode_T) { set_projs_block(succ, block); } - set_nodes_block(succ, block); } } @@ -327,27 +341,24 @@ static void set_projs_block(ir_node *node, ir_node *block) */ static void place_floats_late(ir_node *n, pdeq *worklist) { - int n_outs; - int i; ir_node *block; ir_node *dca; if (irn_visited_else_mark(n)) return; - n_outs = get_irn_n_outs(n); /* break cycles at pinned nodes (see place place_floats_early) as to why */ if (get_irn_pinned(n) != op_pin_state_floats) { - for (i = 0; i < n_outs; ++i) { - ir_node *succ = get_irn_out(n, i); + foreach_out_edge(n, edge) { + ir_node *succ = get_edge_src_irn(edge); pdeq_putr(worklist, succ); } return; } /* place our users */ - for (i = 0; i < n_outs; ++i) { - ir_node *succ = get_irn_out(n, i); + foreach_out_edge(n, edge) { + ir_node *succ = get_edge_src_irn(edge); place_floats_late(succ, worklist); } @@ -356,18 +367,12 @@ static void place_floats_late(ir_node *n, pdeq *worklist) return; /* some nodes should simply stay in the startblock */ if (is_irn_start_block_placed(n)) { -#ifndef NDEBUG - ir_graph *irg = get_irn_irg(n); - ir_node *start_block = get_irg_start_block(irg); - assert(get_nodes_block(n) == start_block); -#endif + assert(get_nodes_block(n) == get_irg_start_block(get_irn_irg(n))); return; } - /* don't move unreachable code around */ block = get_nodes_block(n); - if (!is_block_reachable(block)) - return; + assert(is_block_reachable(block)); /* deepest common ancestor in the dominator tree of all nodes' blocks depending on us; our final placement has to dominate @@ -409,19 +414,23 @@ void place_code(ir_graph *irg) { waitq *worklist; - remove_critical_cf_edges(irg); - /* Handle graph state */ assert(get_irg_phase_state(irg) != phase_building); - assure_irg_outs(irg); - assure_doms(irg); - assure_cf_loop(irg); + assure_irg_properties(irg, + IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES | + IR_GRAPH_PROPERTY_NO_UNREACHABLE_CODE | + IR_GRAPH_PROPERTY_CONSISTENT_OUT_EDGES | + IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE | + IR_GRAPH_PROPERTY_CONSISTENT_LOOPINFO); /* Place all floating nodes as early as possible. This guarantees a legal code placement. */ worklist = new_waitq(); place_early(irg, worklist); + /* While GCSE might place nodes in unreachable blocks, + * these are now placed in reachable blocks. */ + /* Note: place_early changes only blocks, no data edges. So, the * data out edges are still valid, no need to recalculate them here. */ @@ -429,8 +438,8 @@ void place_code(ir_graph *irg) unnecessary executions of the node. */ place_late(irg, worklist); - set_irg_loopinfo_inconsistent(irg); del_waitq(worklist); + confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_CONTROL_FLOW); } /**