Improve the AM folding heuristics: Do not fold AM if at least one of the AM operands...
[libfirm] / ir / be / beschednormal.c
index 74cffb9..aa8ad83 100644 (file)
@@ -20,7 +20,7 @@
 /**
  * @brief   Use the strong normal form theorem (though it does not hold)
  * @author  Christoph Mallon
- * @version $Id: beschedrand.c 14604 2007-06-18 14:07:07Z matze $
+ * @version $Id$
  */
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -34,6 +34,7 @@
 #include "beutil.h"
 #include "irtools.h"
 #include "irgwalk.h"
+#include "benode_t.h"
 
 
 // XXX there is no one time init for schedulers
@@ -105,6 +106,10 @@ static int count_result(const ir_node* irn)
 }
 
 
+/* TODO high cost for store trees
+ */
+
+
 static int normal_tree_cost(ir_node* irn)
 {
        flag_and_cost* fc    = get_irn_link(irn);
@@ -114,6 +119,8 @@ static int normal_tree_cost(ir_node* irn)
        int            count_max = 0;
        int            n_res;
        int            cost;
+       int            n_op_res = 0;
+       int            i;
 
        if (fc == NULL) {
                irn_cost_pair* costs;
@@ -127,13 +134,16 @@ static int normal_tree_cost(ir_node* irn)
                        ir_node* pred = get_irn_n(irn, i);
                        int cost;
 
-                       if (is_Phi(irn) || get_irn_mode(pred) == mode_M) {
+                       if (is_Phi(irn) || get_irn_mode(pred) == mode_M || is_Block(pred)) {
                                cost = 0;
                        } else if (get_nodes_block(pred) != block) {
                                cost = 1;
                        } else {
+                               flag_and_cost* pred_fc;
+
                                cost = normal_tree_cost(pred);
-                               flag_and_cost* pred_fc = get_irn_link(pred);
+                               if (be_is_Barrier(pred)) cost = 1; // XXX hack: the barrier causes all users to have a reguse of #regs
+                               pred_fc = get_irn_link(pred);
                                pred_fc->no_root = 1;
 #if defined NORMAL_DBG
                                ir_fprintf(stderr, "%+F says that %+F is no root\n", irn, pred);
@@ -167,12 +177,15 @@ static int normal_tree_cost(ir_node* irn)
                }
        }
 
-       n_res = count_result(irn);
-       if (cost_max == 0) {
-               cost = n_res;
-       } else {
-               cost = MAX(n_res, cost_max + count_max - 1);
+       cost = 0;
+       for (i = 0; i < arity; ++i) {
+               if (get_irn_mode(fc->costs[i].irn) == mode_M) continue;
+               if (arch_irn_is(cur_arch_env, fc->costs[i].irn, ignore)) continue;
+               cost = MAX(fc->costs[i].cost + n_op_res, cost);
+               ++n_op_res;
        }
+       n_res = count_result(irn);
+       cost = MAX(n_res, cost);
 
 #if defined NORMAL_DBG
        ir_fprintf(stderr, "reguse of %+F is %d\n", irn, cost);
@@ -182,38 +195,6 @@ static int normal_tree_cost(ir_node* irn)
 }
 
 
-static void normal_tree_sched(ir_node* irn)
-{
-       irn_cost_pair* irns  = get_irn_link(irn);
-       int            arity = get_irn_arity(irn);
-       int            i;
-
-       if (irns == NULL) return;
-
-       for (i = 0; i < arity; ++i) {
-               normal_tree_sched(irns[i].irn);
-       }
-
-       if (1) { // TODO check if node needs to be scheduled
-               ir_node*  block = get_nodes_block(irn);
-               ir_node** sched = get_irn_link(block);
-
-#if defined NORMAL_DBG
-               ir_fprintf(stderr, "scheduling %+F in array %p\n", irn, sched);
-#endif
-
-               if (sched == NULL) {
-                       sched = NEW_ARR_F(ir_node*, 0);
-               }
-               ARR_APP1(ir_node*, sched, irn);
-               set_irn_link(block, sched);
-       }
-
-       free(irns);
-       set_irn_link(irn, NULL);
-}
-
-
 static void normal_cost_walker(ir_node* irn, void* env)
 {
        (void)env;
@@ -254,18 +235,26 @@ static void collect_roots(ir_node* irn, void* env)
 
 static ir_node** sched_node(ir_node** sched, ir_node* irn)
 {
-       ir_node* block = get_nodes_block(irn);
-       int arity = get_irn_arity(irn);
-       int i;
+       ir_node*       block = get_nodes_block(irn);
+       flag_and_cost* fc    = get_irn_link(irn);
+       irn_cost_pair* irns  = fc->costs;
+       int            arity = get_irn_arity(irn);
+       int            i;
+
+       if (irn_visited(irn)) return sched;
+
+       if (is_End(irn)) return sched;
 
        if (!is_Phi(irn)) {
                for (i = 0; i < arity; ++i) {
-                       ir_node* pred = get_irn_n(irn, i);
+                       ir_node* pred = irns[i].irn;
                        if (get_nodes_block(pred) != block) continue;
+                       if (get_irn_mode(pred) == mode_M) continue;
                        sched = sched_node(sched, pred);
                }
        }
 
+       mark_irn_visited(irn);
        ARR_APP1(ir_node*, sched, irn);
        return sched;
 }
@@ -315,12 +304,7 @@ static void normal_sched_block(ir_node* block, void* env)
 
                ir_fprintf(stderr, "Scheduling of %+F:\n", block);
                for (i = 0; i < n; ++i) {
-                       int j;
-                       for (j = 0; j < i; ++j) {
-                               if (sched[i] == sched[j]) goto skip;
-                       }
                        ir_fprintf(stderr, "  %+F\n", sched[i]);
-skip:;
                }
                fprintf(stderr, "\n");
        }
@@ -341,6 +325,7 @@ static void *normal_init_graph(const list_sched_selector_t *vtab,
 
        irg_walk_graph(irg, normal_cost_walker,  NULL, NULL);
        irg_walk_graph(irg, collect_roots, NULL, NULL);
+       inc_irg_visited(irg);
        irg_block_walk_graph(irg, normal_sched_block, NULL, NULL);
 
        return NULL;
@@ -356,7 +341,7 @@ static void *normal_init_block(void *graph_env, ir_node *block)
 }
 
 
-static const list_sched_selector_t normal_selector_struct = {
+const list_sched_selector_t normal_selector = {
        normal_init_graph,
        normal_init_block,
        normal_select,
@@ -368,5 +353,3 @@ static const list_sched_selector_t normal_selector_struct = {
        NULL,              /* finish_block */
        NULL               /* finish_graph */
 };
-
-const list_sched_selector_t *normal_selector = &normal_selector_struct;