irop: Provide macro wrappers for [gs]et_generic_function_ptr_().
[libfirm] / ir / opt / code_placement.c
index 1f9c2e1..d12e6b4 100644 (file)
@@ -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
 #include "iroptimize.h"
 #include "adt/pdeq.h"
 #include "irnode_t.h"
-#include "irouts.h"
+#include "iredges_t.h"
 #include "irgopt.h"
 #include "irpass.h"
-#include "opt_manage.h"
 
 static bool is_block_reachable(ir_node *block)
 {
@@ -83,7 +81,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 || only_used_by_keepalive(n)) {
                /* we can't move pinned nodes */
                arity = get_irn_arity(n);
                for (i = 0; i < arity; ++i) {
@@ -122,9 +120,10 @@ static void place_floats_early(ir_node *n, waitq *worklist)
        irg         = get_irn_irg(n);
        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);
+               !irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_BACKEND)) {
+               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 */
@@ -268,10 +267,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))
@@ -286,6 +283,18 @@ static ir_node *get_deepest_common_dom_ancestor(ir_node *node, ir_node *dca)
                        dca = consumer_dom_dca(dca, succ, node);
                }
        }
+       /* respect the keepalive rule: if our only user is a keepalive, then we must
+        * not move the node any further */
+       if (dca == NULL) {
+               assert(only_used_by_keepalive(node));
+               return get_nodes_block(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;
 }
 
@@ -297,17 +306,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);
        }
 }
 
@@ -321,27 +329,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);
        }
 
@@ -350,11 +355,7 @@ 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;
        }
 
@@ -397,12 +398,17 @@ static void place_late(ir_graph *irg, waitq *worklist)
 }
 
 /* Code Placement. */
-static ir_graph_state_t do_codeplacement(ir_graph *irg)
+void place_code(ir_graph *irg)
 {
        waitq *worklist;
 
        /* Handle graph state */
-       assert(get_irg_phase_state(irg) != phase_building);
+       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. */
@@ -420,21 +426,7 @@ static ir_graph_state_t do_codeplacement(ir_graph *irg)
        place_late(irg, worklist);
 
        del_waitq(worklist);
-       return 0;
-}
-
-optdesc_t opt_codeplacement = {
-       "code-placement",
-       IR_GRAPH_STATE_NO_CRITICAL_EDGES |
-       IR_GRAPH_STATE_CONSISTENT_OUTS |
-       IR_GRAPH_STATE_CONSISTENT_DOMINANCE |
-       IR_GRAPH_STATE_CONSISTENT_LOOPINFO,
-       do_codeplacement,
-};
-
-void place_code(ir_graph *irg)
-{
-       perform_irg_optimization(irg, &opt_codeplacement);
+       confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_CONTROL_FLOW);
 }
 
 /**
@@ -448,24 +440,6 @@ static void place_code_wrapper(ir_graph *irg)
        set_opt_global_cse(0);
 }
 
-static ir_graph_state_t do_gcse(ir_graph *irg)
-{
-       set_opt_global_cse(1);
-       optimize_graph_df(irg);
-       do_codeplacement(irg);
-       set_opt_global_cse(0);
-       return 0;
-}
-
-optdesc_t opt_gcse = {
-       "gcse",
-       IR_GRAPH_STATE_NO_CRITICAL_EDGES |
-       IR_GRAPH_STATE_CONSISTENT_OUTS |
-       IR_GRAPH_STATE_CONSISTENT_DOMINANCE |
-       IR_GRAPH_STATE_CONSISTENT_LOOPINFO,
-       do_gcse,
-};
-
 ir_graph_pass_t *place_code_pass(const char *name)
 {
        return def_graph_pass(name ? name : "place", place_code_wrapper);