reduce code size
[libfirm] / ir / be / bepeephole.c
index 508f142..3d4c4ca 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
  *
  * This file is part of libFirm.
  *
 #include "belive_t.h"
 #include "bearch_t.h"
 #include "besched_t.h"
+#include "bemodule.h"
+
+DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 
 static const arch_env_t *arch_env;
 static be_lv_t          *lv;
+static ir_node          *current_node;
 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;
@@ -64,10 +68,11 @@ static void clear_value(ir_node *node)
        cls_idx = arch_register_class_index(cls);
 
        //assert(register_values[cls_idx][reg_idx] != NULL);
+       DBG((dbg, LEVEL_1, "Clear Register %s\n", reg->name));
        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;
@@ -77,7 +82,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);
        }
@@ -87,12 +92,7 @@ static void set_value(ir_node *node)
        reg_idx = arch_register_get_index(reg);
        cls_idx = arch_register_class_index(cls);
 
-#ifdef DEBUG_libfirm
-       {
-               ir_node *old_value = register_values[cls_idx][reg_idx];
-               assert(old_value == NULL || old_value == node);
-       }
-#endif
+       DBG((dbg, LEVEL_1, "Set Register %s: %+F\n", reg->name, node));
        register_values[cls_idx][reg_idx] = node;
 }
 
@@ -103,10 +103,10 @@ static void clear_defs(ir_node *node)
                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);
        }
 }
 
@@ -118,17 +118,56 @@ static void set_uses(ir_node *node)
        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);
        }
 }
 
+void be_peephole_before_exchange(const ir_node *old_node, ir_node *new_node)
+{
+       const arch_register_t       *reg;
+       const arch_register_class_t *cls;
+       unsigned                     reg_idx;
+       unsigned                     cls_idx;
+
+       DBG((dbg, LEVEL_1, "About to exchange %+F with %+F\n", old_node, new_node));
+
+       if(old_node == current_node) {
+               if(is_Proj(new_node)) {
+                       current_node = get_Proj_pred(new_node);
+               } else {
+                       current_node = new_node;
+               }
+       }
+
+       if(!mode_is_data(get_irn_mode(old_node)))
+               return;
+
+       reg = arch_get_irn_register(arch_env, old_node);
+       if(reg == NULL) {
+               panic("No register assigned at %+F\n", old_node);
+       }
+       cls     = arch_register_get_class(reg);
+       reg_idx = arch_register_get_index(reg);
+       cls_idx = arch_register_class_index(cls);
+
+       if(register_values[cls_idx][reg_idx] == old_node) {
+               register_values[cls_idx][reg_idx] = new_node;
+       }
+
+       be_liveness_remove(lv, old_node);
+}
+
+void be_peephole_after_exchange(ir_node *new_node)
+{
+       be_liveness_introduce(lv, new_node);
+}
+
 static void process_block(ir_node *block, void *data)
 {
        arch_isa_t *isa = arch_env->isa;
        unsigned n_classes;
        unsigned i;
        int l;
-       ir_node *node;
        (void) data;
 
        /* construct initial register assignment */
@@ -140,33 +179,37 @@ static void process_block(ir_node *block, void *data)
        }
 
        assert(lv->nodes && "live sets must be computed");
+       DBG((dbg, LEVEL_1, "\nProcessing block %+F (from end)\n", block));
        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);
        }
+       DBG((dbg, LEVEL_1, "\nstart processing\n"));
 
-       /* walk the block */
-       node = sched_last(block);
-       for( ; !sched_is_begin(node); node = sched_prev(node)) {
+       /* walk the block from last insn to the first */
+       current_node = sched_last(block);
+       for( ; !sched_is_begin(current_node);
+                       current_node = sched_prev(current_node)) {
                ir_op             *op;
+               ir_node           *last;
                peephole_opt_func  func;
 
-               if(is_Phi(node))
+               if(is_Phi(current_node))
                        break;
 
-               clear_defs(node);
-               set_uses(node);
+               clear_defs(current_node);
+               set_uses(current_node);
 
-               op   = get_irn_op(node);
+               op   = get_irn_op(current_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);
-                       }
+               if(func == NULL)
+                       continue;
+
+               last = current_node;
+               func(current_node);
+               /* was the current node replaced? */
+               if(current_node != last) {
+                       set_uses(current_node);
                }
        }
 }
@@ -202,3 +245,10 @@ void be_peephole_init(void)
 {
        clear_irp_opcodes_generic_func();
 }
+
+void be_init_peephole(void)
+{
+       FIRM_DBG_REGISTER(dbg, "firm.be.peephole");
+}
+
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_spillbelady);