lower_highlevel didn't invalidate outedges, code_placement must assure doms
[libfirm] / ir / opt / code_placement.c
index edeacc1..1eea766 100644 (file)
  *           Michael Beck
  * @version  $Id$
  */
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
+#include "config.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) {
+static int is_Block_unreachable(ir_node *block)
+{
        return is_Block_dead(block) || get_Block_dom_depth(block) < 0;
 }
 
@@ -63,12 +62,12 @@ 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 */
-       assert(irn_not_visited(n));
+       assert(!irn_visited(n));
        mark_irn_visited(n);
 
        /* Place floating nodes. */
@@ -92,14 +91,15 @@ place_floats_early(ir_node *n, waitq *worklist) {
                        ir_node *pred = get_irn_n(n, i);
                        ir_node *pred_block;
 
-                       if ((irn_not_visited(pred))
+                       if (!irn_visited(pred)
                            && (get_irn_pinned(pred) == op_pin_state_floats)) {
 
                                /*
                                 * 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.
                                 */
@@ -118,17 +118,18 @@ 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)) {
                                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) {
@@ -143,7 +144,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);
 
@@ -154,7 +156,7 @@ place_floats_early(ir_node *n, waitq *worklist) {
                 */
                for (i = -1; i < irn_arity; ++i) {
                        ir_node *pred = get_irn_n(n, i);
-                       if (irn_not_visited(pred))
+                       if (!irn_visited(pred))
                                waitq_put(worklist, pred);
                }
        } else if (is_Block(n)) {
@@ -164,7 +166,7 @@ place_floats_early(ir_node *n, waitq *worklist) {
                 */
                for (i = irn_arity - 1; i >= 0; --i) {
                        ir_node *pred = get_irn_n(n, i);
-                       if (irn_not_visited(pred))
+                       if (!irn_visited(pred))
                                waitq_put(worklist, pred);
                }
        } else if (is_Phi(n)) {
@@ -177,13 +179,13 @@ place_floats_early(ir_node *n, waitq *worklist) {
                 * of the Phi-input if the Phi is not in a bad block.
                 */
                pred = get_nodes_block(n);
-               if (irn_not_visited(pred))
+               if (!irn_visited(pred))
                        waitq_put(worklist, pred);
 
                for (i = irn_arity - 1; i >= 0; --i) {
                        ir_node *pred = get_irn_n(n, i);
 
-                       if (irn_not_visited(pred)) {
+                       if (!irn_visited(pred)) {
                                if (! in_dead_block &&
                                        get_irn_pinned(pred) == op_pin_state_floats &&
                                        is_Block_unreachable(get_nodes_block(pred))) {
@@ -201,13 +203,13 @@ place_floats_early(ir_node *n, waitq *worklist) {
                 * All other nodes: move nodes from dead blocks into the same block.
                 */
                pred = get_nodes_block(n);
-               if (irn_not_visited(pred))
+               if (!irn_visited(pred))
                        waitq_put(worklist, pred);
 
                for (i = irn_arity - 1; i >= 0; --i) {
                        ir_node *pred = get_irn_n(n, i);
 
-                       if (irn_not_visited(pred)) {
+                       if (!irn_visited(pred)) {
                                if (! in_dead_block &&
                                        get_irn_pinned(pred) == op_pin_state_floats &&
                                        is_Block_unreachable(get_nodes_block(pred))) {
@@ -221,13 +223,15 @@ 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(waitq *worklist)
+{
        assert(worklist);
        inc_irg_visited(current_ir_graph);
 
@@ -237,7 +241,7 @@ static void place_early(waitq *worklist) {
        /* Work the content of the worklist. */
        while (!waitq_empty(worklist)) {
                ir_node *n = waitq_get(worklist);
-               if (irn_not_visited(n))
+               if (!irn_visited(n))
                        place_floats_early(n, worklist);
        }
        set_irg_pinned(current_ir_graph, op_pin_state_pinned);
@@ -252,8 +256,9 @@ 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);
+static ir_node *calc_dom_dca(ir_node *dca, ir_node *block)
+{
+       assert(block != NULL);
 
        /* we do not want to place nodes in dead blocks */
        if (is_Block_dead(block))
@@ -306,10 +311,9 @@ static ir_node *consumer_dom_dca(ir_node *dca, ir_node *consumer, ir_node *produ
        return dca;
 }
 
-/* FIXME: the name clashes here with the function from ana/field_temperature.c
- * please rename. */
-static INLINE int get_irn_loop_depth(ir_node *n) {
-       return get_loop_depth(get_irn_loop(n));
+static inline int get_block_loop_depth(ir_node *block)
+{
+       return get_loop_depth(get_irn_loop(block));
 }
 
 /**
@@ -319,7 +323,8 @@ static INLINE int get_irn_loop_depth(ir_node *n) {
  * @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);
 
@@ -333,7 +338,7 @@ static void move_out_of_loops(ir_node *n, ir_node *early) {
        while (dca != early) {
                dca = get_Block_idom(dca);
                if (!dca || is_Bad(dca)) break; /* may be Bad if not reachable from Start */
-               if (get_irn_loop_depth(dca) < get_irn_loop_depth(best)) {
+               if (get_block_loop_depth(dca) < get_block_loop_depth(best)) {
                        best = dca;
                }
        }
@@ -351,7 +356,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) {
@@ -386,7 +392,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) {
@@ -413,11 +420,12 @@ 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;
 
-       assert(irn_not_visited(n)); /* no multiple placement */
+       assert(!irn_visited(n)); /* no multiple placement */
 
        mark_irn_visited(n);
 
@@ -445,7 +453,7 @@ static void place_floats_late(ir_node *n, pdeq *worklist) {
                    producer of one of their inputs in the same block anyway. */
                for (i = get_irn_n_outs(n) - 1; i >= 0; --i) {
                        ir_node *succ = get_irn_out(n, i);
-                       if (irn_not_visited(succ) && !is_Phi(succ))
+                       if (!irn_visited(succ) && !is_Phi(succ))
                                place_floats_late(succ, worklist);
                }
 
@@ -480,7 +488,7 @@ static void place_floats_late(ir_node *n, pdeq *worklist) {
        n_outs = get_irn_n_outs(n);
        for (i = 0; i < n_outs; i++) {
                ir_node *succ = get_irn_out(n, i);
-               if (irn_not_visited(succ)) {
+               if (!irn_visited(succ)) {
                        pdeq_putr(worklist, succ);
                }
        }
@@ -492,7 +500,8 @@ 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(waitq *worklist)
+{
        assert(worklist);
        inc_irg_visited(current_ir_graph);
 
@@ -502,13 +511,14 @@ static void place_late(waitq *worklist) {
        /* And now empty the worklist again... */
        while (!waitq_empty(worklist)) {
                ir_node *n = waitq_get(worklist);
-               if (irn_not_visited(n))
+               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;
 
@@ -517,6 +527,7 @@ void place_code(ir_graph *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) {
@@ -541,3 +552,19 @@ void place_code(ir_graph *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);
+}