X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;ds=sidebyside;f=ir%2Fopt%2Fcode_placement.c;h=5ca8d400628c4f06295061da6ffab687a2c5fb46;hb=65daf5bc390b02d68581f4c431dbdbfaae11b88f;hp=577ad983e2503db818aa4d85aaaeea6a888d577b;hpb=5c4eda434996c01bb92310a1afcada0927115858;p=libfirm diff --git a/ir/opt/code_placement.c b/ir/opt/code_placement.c index 577ad983e..5ca8d4006 100644 --- a/ir/opt/code_placement.c +++ b/ir/opt/code_placement.c @@ -27,19 +27,16 @@ */ #include "config.h" +#include "iroptimize.h" #include "adt/pdeq.h" #include "irnode_t.h" #include "irouts.h" #include "irgopt.h" +#include "irpass.h" -/** - * Returns non-zero, is a block is not reachable from Start. - * - * @param block the block to test - */ -static int -is_Block_unreachable(ir_node *block) { - return is_Block_dead(block) || get_Block_dom_depth(block) < 0; +static int is_Block_unreachable(ir_node *block) +{ + return get_Block_dom_depth(block) < 0; } /** @@ -53,7 +50,7 @@ is_Block_unreachable(ir_node *block) { * all "living" nodes into a living block. That's why we must * move nodes in dead block with "live" successors into a valid * block. - * We move them just into the same block as it's successor (or + * We move them just into the same block as its successor (or * in case of a Phi into the effective use block). For Phi successors, * this may still be a dead block, but then there is no real use, as * the control flow will be dead later. @@ -61,8 +58,8 @@ is_Block_unreachable(ir_node *block) { * @param n the node to be placed * @param worklist a worklist, predecessors of non-floating nodes are placed here */ -static void -place_floats_early(ir_node *n, waitq *worklist) { +static void place_floats_early(ir_node *n, waitq *worklist) +{ int i, irn_arity; /* we must not run into an infinite loop */ @@ -75,12 +72,13 @@ place_floats_early(ir_node *n, waitq *worklist) { int in_dead_block = is_Block_unreachable(curr_block); int depth = 0; ir_node *b = NULL; /* The block to place this node in */ + ir_graph *irg = get_irn_irg(n); - assert(is_no_Block(n)); + assert(!is_Block(n)); if (is_irn_start_block_placed(n)) { /* These nodes will not be placed by the loop below. */ - b = get_irg_start_block(current_ir_graph); + b = get_irg_start_block(irg); depth = 1; } @@ -95,9 +93,10 @@ place_floats_early(ir_node *n, waitq *worklist) { /* * If the current node is NOT in a dead block, but one of its - * predecessors is, we must move the predecessor to a live block. - * Such thing can happen, if global CSE chose a node from a dead block. - * We move it simply to our block. + * predecessors is, we must move the predecessor to a live + * block. + * Such thing can happen, if global CSE chose a node from a + * dead block. We move it simply to our block. * Note that neither Phi nor End nodes are floating, so we don't * need to handle them here. */ @@ -116,22 +115,22 @@ place_floats_early(ir_node *n, waitq *worklist) { if (in_dead_block) continue; - /* Because all loops contain at least one op_pin_state_pinned node, now all - our inputs are either op_pin_state_pinned or place_early() has already - been finished on them. We do not have any unfinished inputs! */ + /* Because all loops contain at least one op_pin_state_pinned node, + now all our inputs are either op_pin_state_pinned or + place_early() has already been finished on them. + We do not have any unfinished inputs! */ pred_block = get_nodes_block(pred); - if ((!is_Block_dead(pred_block)) && - (get_Block_dom_depth(pred_block) > depth)) { + if (get_Block_dom_depth(pred_block) > depth) { b = pred_block; depth = get_Block_dom_depth(pred_block); } - /* Avoid that the node is placed in the Start block if we are not in the - backend phase. */ + /* Avoid that the node is placed in the Start block if we are not + in the backend phase. */ if (depth == 1 && get_Block_dom_depth(get_nodes_block(n)) > 1 && - get_irg_phase_state(current_ir_graph) != phase_backend) { - b = get_Block_cfg_out(get_irg_start_block(current_ir_graph), 0); - assert(b != get_irg_start_block(current_ir_graph)); + get_irg_phase_state(irg) != phase_backend) { + b = get_Block_cfg_out(get_irg_start_block(irg), 0); + assert(b != get_irg_start_block(irg)); depth = 2; } } @@ -141,7 +140,8 @@ place_floats_early(ir_node *n, waitq *worklist) { /* * Add predecessors of non floating nodes and non-floating predecessors - * of floating nodes to worklist and fix their blocks if the are in dead block. + * of floating nodes to worklist and fix their blocks if the are in dead + * block. */ irn_arity = get_irn_arity(n); @@ -219,26 +219,28 @@ place_floats_early(ir_node *n, waitq *worklist) { /** * Floating nodes form subgraphs that begin at nodes as Const, Load, - * Start, Call and that end at op_pin_state_pinned nodes as Store, Call. Place_early - * places all floating nodes reachable from its argument through floating - * nodes and adds all beginnings at op_pin_state_pinned nodes to the worklist. + * Start, Call and that end at op_pin_state_pinned nodes as Store, Call. + * Place_early places all floating nodes reachable from its argument through + * floating nodes and adds all beginnings at op_pin_state_pinned nodes to the + * worklist. * * @param worklist a worklist, used for the algorithm, empty on in/output */ -static void place_early(waitq *worklist) { +static void place_early(ir_graph *irg, waitq *worklist) +{ assert(worklist); - inc_irg_visited(current_ir_graph); + inc_irg_visited(irg); /* this inits the worklist */ - place_floats_early(get_irg_end(current_ir_graph), worklist); + place_floats_early(get_irg_end(irg), worklist); /* Work the content of the worklist. */ while (!waitq_empty(worklist)) { - ir_node *n = waitq_get(worklist); + ir_node *n = (ir_node*)waitq_get(worklist); if (!irn_visited(n)) place_floats_early(n, worklist); } - set_irg_pinned(current_ir_graph, op_pin_state_pinned); + set_irg_pinned(irg, op_pin_state_pinned); } /** @@ -250,15 +252,13 @@ static void place_early(waitq *worklist) { * * @return the deepest common dominator tree ancestor of block and dca */ -static ir_node *calc_dom_dca(ir_node *dca, ir_node *block) { - assert(block); - - /* we do not want to place nodes in dead blocks */ - if (is_Block_dead(block)) - return dca; +static ir_node *calc_dom_dca(ir_node *dca, ir_node *block) +{ + assert(block != NULL); /* We found a first legal placement. */ - if (!dca) return block; + if (!dca) + return block; /* Find a placement that is dominates both, dca and block. */ while (get_Block_dom_depth(block) > get_Block_dom_depth(dca)) @@ -293,6 +293,8 @@ static ir_node *consumer_dom_dca(ir_node *dca, ir_node *consumer, ir_node *produ for (i = 0; i < arity; i++) { if (get_Phi_pred(consumer, i) == producer) { ir_node *new_block = get_Block_cfgpred_block(phi_block, i); + if (is_Bad(new_block)) + continue; if (!is_Block_unreachable(new_block)) dca = calc_dom_dca(dca, new_block); @@ -304,18 +306,20 @@ static ir_node *consumer_dom_dca(ir_node *dca, ir_node *consumer, ir_node *produ return dca; } -static inline int get_block_loop_depth(ir_node *block) { +static inline int get_block_loop_depth(ir_node *block) +{ return get_loop_depth(get_irn_loop(block)); } /** - * Move n to a block with less loop depth than it's current block. The + * Move n to a block with less loop depth than its current block. The * new block must be dominated by early. * * @param n the node that should be moved * @param early the earliest block we can n move to */ -static void move_out_of_loops(ir_node *n, ir_node *early) { +static void move_out_of_loops(ir_node *n, ir_node *early) +{ ir_node *best, *dca; assert(n && early); @@ -347,7 +351,8 @@ static void move_out_of_loops(ir_node *n, ir_node *early) { * * @return the deepest common dominator ancestor of all blocks of node's users */ -static ir_node *get_deepest_common_dom_ancestor(ir_node *node, ir_node *dca) { +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) { @@ -382,7 +387,8 @@ static ir_node *get_deepest_common_dom_ancestor(ir_node *node, ir_node *dca) { * @param node the mode_T node * @param block the block to put the Proj nodes to */ -static void set_projs_block(ir_node *node, ir_node *block) { +static void set_projs_block(ir_node *node, ir_node *block) +{ int i; for (i = get_irn_n_outs(node) - 1; i >= 0; --i) { @@ -409,7 +415,8 @@ static void set_projs_block(ir_node *node, ir_node *block) { * @param worklist a worklist, all successors of non-floating nodes are * placed here */ -static void place_floats_late(ir_node *n, pdeq *worklist) { +static void place_floats_late(ir_node *n, pdeq *worklist) +{ int i, n_outs; ir_node *early_blk; @@ -421,6 +428,7 @@ static void place_floats_late(ir_node *n, pdeq *worklist) { if (!is_Block(n) && (!is_cfop(n)) && (get_irn_mode(n) != mode_X)) { + ir_op *op; /* Remember the early_blk placement of this block to move it out of loop no further than the early_blk placement. */ early_blk = get_nodes_block(n); @@ -445,27 +453,25 @@ static void place_floats_late(ir_node *n, pdeq *worklist) { place_floats_late(succ, worklist); } - if (! is_Block_dead(early_blk)) { - /* do only move things that where not dead */ - ir_op *op = get_irn_op(n); - - /* We have to determine the final block of this node... except for - constants and Projs */ - if ((get_irn_pinned(n) == op_pin_state_floats) && - (op != op_Const) && - (op != op_SymConst) && - (op != op_Proj)) - { - /* deepest common ancestor in the dominator tree of all nodes' - blocks depending on us; our final placement has to dominate - DCA. */ - ir_node *dca = get_deepest_common_dom_ancestor(n, NULL); - if (dca != NULL) { - set_nodes_block(n, dca); - move_out_of_loops(n, early_blk); - if (get_irn_mode(n) == mode_T) { - set_projs_block(n, get_nodes_block(n)); - } + /* do only move things that where not dead */ + op = get_irn_op(n); + + /* We have to determine the final block of this node... except for + constants and Projs */ + if ((get_irn_pinned(n) == op_pin_state_floats) && + (op != op_Const) && + (op != op_SymConst) && + (op != op_Proj)) + { + /* deepest common ancestor in the dominator tree of all nodes' + blocks depending on us; our final placement has to dominate + DCA. */ + ir_node *dca = get_deepest_common_dom_ancestor(n, NULL); + if (dca != NULL) { + set_nodes_block(n, dca); + move_out_of_loops(n, early_blk); + if (get_irn_mode(n) == mode_T) { + set_projs_block(n, get_nodes_block(n)); } } } @@ -488,52 +494,64 @@ static void place_floats_late(ir_node *n, pdeq *worklist) { * * @param worklist the worklist containing the nodes to place */ -static void place_late(waitq *worklist) { +static void place_late(ir_graph *irg, waitq *worklist) +{ assert(worklist); - inc_irg_visited(current_ir_graph); + inc_irg_visited(irg); /* This fills the worklist initially. */ - place_floats_late(get_irg_start_block(current_ir_graph), worklist); + place_floats_late(get_irg_start_block(irg), worklist); /* And now empty the worklist again... */ while (!waitq_empty(worklist)) { - ir_node *n = waitq_get(worklist); + ir_node *n = (ir_node*)waitq_get(worklist); if (!irn_visited(n)) place_floats_late(n, worklist); } } /* Code Placement. */ -void place_code(ir_graph *irg) { +void place_code(ir_graph *irg) +{ waitq *worklist; - ir_graph *rem = current_ir_graph; - current_ir_graph = irg; remove_critical_cf_edges(irg); /* Handle graph state */ assert(get_irg_phase_state(irg) != phase_building); + assure_irg_outs(irg); assure_doms(irg); - - if (1 || get_irg_loopinfo_state(irg) != loopinfo_consistent) { - free_loop_information(irg); - construct_cf_backedges(irg); - } + assure_cf_loop(irg); /* Place all floating nodes as early as possible. This guarantees a legal code placement. */ worklist = new_waitq(); - place_early(worklist); + place_early(irg, worklist); /* Note: place_early changes only blocks, no data edges. So, the * data out edges are still valid, no need to recalculate them here. */ /* Now move the nodes down in the dominator tree. This reduces the unnecessary executions of the node. */ - place_late(worklist); + place_late(irg, worklist); set_irg_outs_inconsistent(irg); set_irg_loopinfo_inconsistent(irg); del_waitq(worklist); - current_ir_graph = rem; +} + +/** + * Wrapper for place_code() inside the place_code pass. + */ +static void place_code_wrapper(ir_graph *irg) +{ + set_opt_global_cse(1); + optimize_graph_df(irg); + place_code(irg); + set_opt_global_cse(0); +} + +ir_graph_pass_t *place_code_pass(const char *name) +{ + return def_graph_pass(name ? name : "place", place_code_wrapper); }