introduce Switch node
[libfirm] / ir / opt / loop.c
index 4f5a1e1..46665db 100644 (file)
 #include "beutil.h"
 #include "irpass.h"
 #include "irdom.h"
+#include "opt_manage.h"
 
 #include <math.h>
 #include "irbackedge_t.h"
-#include "irphase_t.h"
+#include "irnodemap.h"
 #include "irloop_t.h"
 
-
-DEBUG_ONLY(static firm_dbg_module_t *dbg);
+DEBUG_ONLY(static firm_dbg_module_t *dbg;)
 
 /**
  * Convenience macro for iterating over every phi node of the given block.
@@ -211,7 +211,8 @@ static entry_edge *loop_entries;
 /* Number of unrolls to perform */
 static int unroll_nr;
 /* Phase is used to keep copies of nodes. */
-static ir_phase *phase;
+static ir_nodemap     map;
+static struct obstack obst;
 
 /* Loop operations.  */
 typedef enum loop_op_t {
@@ -495,16 +496,14 @@ static void set_unroll_copy(ir_node *n, int nr, ir_node *cp)
        unrolling_node_info *info;
        assert(nr != 0 && "0 reserved");
 
-       info = (unrolling_node_info *)phase_get_irn_data(phase, n);
+       info = (unrolling_node_info*)ir_nodemap_get(&map, n);
        if (! info) {
-               ir_node **arr;
+               ir_node **arr = NEW_ARR_D(ir_node*, &obst, unroll_nr);
+               memset(arr, 0, unroll_nr * sizeof(ir_node*));
 
-               info = XMALLOCZ(unrolling_node_info);
-               arr = NEW_ARR_F(ir_node *, unroll_nr);
+               info = OALLOCZ(&obst, unrolling_node_info);
                info->copies = arr;
-               memset(info->copies, 0, (unroll_nr) * sizeof(ir_node *));
-
-               phase_set_irn_data(phase, n, info);
+               ir_nodemap_insert(&map, n, info);
        }
        /* Original node */
        info->copies[0] = n;
@@ -516,7 +515,7 @@ static void set_unroll_copy(ir_node *n, int nr, ir_node *cp)
 static ir_node *get_unroll_copy(ir_node *n, int nr)
 {
        ir_node             *cp;
-       unrolling_node_info *info = (unrolling_node_info *)phase_get_irn_data(phase, n);
+       unrolling_node_info *info = (unrolling_node_info *)ir_nodemap_get(&map, n);
        if (! info)
                return NULL;
 
@@ -530,13 +529,13 @@ static ir_node *get_unroll_copy(ir_node *n, int nr)
 /* Sets copy cp of node n. */
 static void set_inversion_copy(ir_node *n, ir_node *cp)
 {
-       phase_set_irn_data(phase, n, cp);
+       ir_nodemap_insert(&map, n, cp);
 }
 
 /* Getter of copy of n for inversion */
 static ir_node *get_inversion_copy(ir_node *n)
 {
-       ir_node *cp = (ir_node *)phase_get_irn_data(phase, n);
+       ir_node *cp = (ir_node *)ir_nodemap_get(&map, n);
        return cp;
 }
 
@@ -1309,7 +1308,8 @@ static void loop_inversion(ir_graph *irg)
        inversion_blocks_in_cc = 0;
 
        /* Use phase to keep copy of nodes from the condition chain. */
-       phase = new_phase(irg, phase_irn_init_default);
+       ir_nodemap_init(&map, irg);
+       obstack_init(&obst);
 
        /* Search for condition chains and temporarily save the blocks in an array. */
        cc_blocks = NEW_ARR_F(ir_node *, 0);
@@ -1354,14 +1354,15 @@ static void loop_inversion(ir_graph *irg)
                DEL_ARR_F(cur_head_outs);
 
                /* Duplicated blocks changed doms */
-               set_irg_doms_inconsistent(irg);
-               set_irg_loopinfo_state(irg, loopinfo_cf_inconsistent);
+               clear_irg_state(irg, IR_GRAPH_STATE_CONSISTENT_DOMINANCE
+                                  | IR_GRAPH_STATE_CONSISTENT_LOOPINFO);
 
                ++stats.inverted;
        }
 
        /* free */
-       phase_free(phase);
+       obstack_free(&obst, NULL);
+       ir_nodemap_destroy(&map);
        DEL_ARR_F(cond_chain_entries);
        DEL_ARR_F(head_df_loop);
 
@@ -2554,7 +2555,8 @@ static void unroll_loop(void)
                }
 
                /* Use phase to keep copy of nodes from the condition chain. */
-               phase = new_phase(current_ir_graph, phase_irn_init_default);
+               ir_nodemap_init(&map, current_ir_graph);
+               obstack_init(&obst);
 
                /* Copies the loop */
                copy_loop(loop_entries, unroll_nr - 1);
@@ -2573,9 +2575,11 @@ static void unroll_loop(void)
                else
                        ++stats.invariant_unroll;
 
-               set_irg_doms_inconsistent(current_ir_graph);
+               clear_irg_state(current_ir_graph, IR_GRAPH_STATE_CONSISTENT_DOMINANCE);
 
                DEL_ARR_F(loop_entries);
+               obstack_free(&obst, NULL);
+               ir_nodemap_destroy(&map);
        }
 
 }
@@ -2679,10 +2683,6 @@ void loop_optimization(ir_graph *irg)
        /* Preconditions */
        set_current_ir_graph(irg);
 
-       edges_assure(irg);
-       assure_irg_outs(irg);
-       assure_cf_loop(irg);
-
        ir_reserve_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
        collect_phiprojs(irg);
 
@@ -2720,24 +2720,54 @@ void loop_optimization(ir_graph *irg)
        ir_free_resources(irg, IR_RESOURCE_IRN_LINK | IR_RESOURCE_PHI_LIST);
 }
 
-void do_loop_unrolling(ir_graph *irg)
+static ir_graph_state_t perform_loop_unrolling(ir_graph *irg)
 {
        loop_op = loop_op_unrolling;
        loop_optimization(irg);
+       return 0;
 }
 
-void do_loop_inversion(ir_graph *irg)
+static ir_graph_state_t perform_loop_inversion(ir_graph *irg)
 {
        loop_op = loop_op_inversion;
        loop_optimization(irg);
+       return 0;
 }
 
-void do_loop_peeling(ir_graph *irg)
+static ir_graph_state_t perform_loop_peeling(ir_graph *irg)
 {
        loop_op = loop_op_peeling;
        loop_optimization(irg);
+       return 0;
 }
 
+static optdesc_t opt_unroll_loops = {
+       "unroll-loops",
+       IR_GRAPH_STATE_CONSISTENT_OUT_EDGES | IR_GRAPH_STATE_CONSISTENT_OUTS | IR_GRAPH_STATE_CONSISTENT_LOOPINFO,
+       perform_loop_unrolling,
+};
+
+static optdesc_t opt_invert_loops = {
+       "invert-loops",
+       IR_GRAPH_STATE_CONSISTENT_OUT_EDGES | IR_GRAPH_STATE_CONSISTENT_OUTS | IR_GRAPH_STATE_CONSISTENT_LOOPINFO,
+       perform_loop_inversion,
+};
+
+static optdesc_t opt_peel_loops = {
+       "peel-loops",
+       IR_GRAPH_STATE_CONSISTENT_OUT_EDGES | IR_GRAPH_STATE_CONSISTENT_OUTS | IR_GRAPH_STATE_CONSISTENT_LOOPINFO,
+       perform_loop_peeling,
+};
+
+void do_loop_unrolling(ir_graph *irg)
+{ perform_irg_optimization(irg, &opt_unroll_loops); }
+
+void do_loop_inversion(ir_graph *irg)
+{ perform_irg_optimization(irg, &opt_invert_loops); }
+
+void do_loop_peeling(ir_graph *irg)
+{ perform_irg_optimization(irg, &opt_peel_loops); }
+
 ir_graph_pass_t *loop_inversion_pass(const char *name)
 {
        return def_graph_pass(name ? name : "loop_inversion", do_loop_inversion);