remove morgan spiller, it's unused and the coming bespill changes won't support morga...
[libfirm] / ir / be / bepeephole.c
index 0895366..ca37ec6 100644 (file)
 
 /**
  * @file
- * @brief       modifies schedule so flags dependencies are respected.
- * @author      Matthias Braun, Christoph Mallon
+ * @brief       Peephole optimisation framework keeps track of which registers contain which values
+ * @author      Matthias Braun
  * @version     $Id$
  */
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
+#include "bepeephole.h"
+
 #include "iredges_t.h"
 #include "irgwalk.h"
 #include "irprintf.h"
 #include "besched_t.h"
 
 static const arch_env_t *arch_env;
-static const be_lv_t    *lv;
-ir_node              ***register_values;
+static be_lv_t          *lv;
+ir_node               ***register_values;
 
-static void clear_value(ir_node *node)
+static void clear_reg_value(ir_node *node)
 {
        const arch_register_t       *reg;
        const arch_register_class_t *cls;
@@ -61,10 +63,11 @@ static void clear_value(ir_node *node)
        reg_idx = arch_register_get_index(reg);
        cls_idx = arch_register_class_index(cls);
 
+       //assert(register_values[cls_idx][reg_idx] != NULL);
        register_values[cls_idx][reg_idx] = NULL;
 }
 
-static void set_value(ir_node *node)
+static void set_reg_value(ir_node *node)
 {
        const arch_register_t       *reg;
        const arch_register_class_t *cls;
@@ -74,7 +77,7 @@ static void set_value(ir_node *node)
        if(!mode_is_data(get_irn_mode(node)))
                return;
 
-       reg     = arch_get_irn_register(arch_env, node);
+       reg = arch_get_irn_register(arch_env, node);
        if(reg == NULL) {
                panic("No register assigned at %+F\n", node);
        }
@@ -93,26 +96,29 @@ static void set_value(ir_node *node)
        register_values[cls_idx][reg_idx] = node;
 }
 
-static void advance(ir_node *node)
+static void clear_defs(ir_node *node)
 {
-       int i, arity;
-
        /* clear values defined */
        if(get_irn_mode(node) == mode_T) {
                const ir_edge_t *edge;
                foreach_out_edge(node, edge) {
                        ir_node *proj = get_edge_src_irn(edge);
-                       clear_value(proj);
+                       clear_reg_value(proj);
                }
        } else {
-               clear_value(node);
+               clear_reg_value(node);
        }
+}
+
+static void set_uses(ir_node *node)
+{
+       int i, arity;
 
        /* set values used */
        arity = get_irn_arity(node);
        for(i = 0; i < arity; ++i) {
                ir_node *in = get_irn_n(node, i);
-               set_value(in);
+               set_reg_value(in);
        }
 }
 
@@ -136,15 +142,32 @@ static void process_block(ir_node *block, void *data)
        assert(lv->nodes && "live sets must be computed");
        be_lv_foreach(lv, block, be_lv_state_end, l) {
                ir_node *node = be_lv_get_irn(lv, block, l);
-               set_value(node);
+               set_reg_value(node);
        }
 
-       /* walk the block */
-       sched_foreach_reverse(block, node) {
+       /* walk the block from last insn to the first */
+       node = sched_last(block);
+       for( ; !sched_is_begin(node); node = sched_prev(node)) {
+               ir_op             *op;
+               peephole_opt_func  func;
+
                if(is_Phi(node))
                        break;
 
-               advance(node);
+               clear_defs(node);
+               set_uses(node);
+
+               op   = get_irn_op(node);
+               func = (peephole_opt_func) op->ops.generic;
+               if(func != NULL) {
+                       ir_node *new_node = func(node);
+                       if(new_node != NULL && new_node != node) {
+                               be_liveness_remove(lv, node);
+                               be_liveness_introduce(lv, new_node);
+                               node = new_node;
+                               set_uses(node);
+                       }
+               }
        }
 }
 
@@ -174,3 +197,8 @@ void be_peephole_opt(be_irg_t *birg)
 
        irg_block_walk_graph(irg, process_block, NULL, NULL);
 }
+
+void be_peephole_init(void)
+{
+       clear_irp_opcodes_generic_func();
+}