Bugfix in copy-opt-heur and constraint perms.
authorDaniel Grund <grund@cs.uni-saarland.de>
Fri, 23 Dec 2005 15:54:18 +0000 (15:54 +0000)
committerDaniel Grund <grund@cs.uni-saarland.de>
Fri, 23 Dec 2005 15:54:18 +0000 (15:54 +0000)
Refactored copyoptmain
Removed Debugging levels
etc. pp.

Happy Christmas!

12 files changed:
ir/be/beconstrperm.c
ir/be/becopyheur.c
ir/be/becopyilp.c
ir/be/becopyopt.c
ir/be/becopyopt.h
ir/be/becopyoptmain.c
ir/be/becopyoptmain.h
ir/be/becopystat.c
ir/be/beifg.c
ir/be/beifg_std.c
ir/be/beifg_t.h
ir/be/bemain.c

index 9c30b4a..9522260 100644 (file)
@@ -35,6 +35,7 @@ static void walker_insert_constr_perms(ir_node *bl, void *env) {
                        /* if a restriction is found, insert a perm before the irn */
                        if (req.type == arch_register_req_type_limited) {
                                insert_Perm_after(menv, cenv->cls, cenv->dom_front, sched_prev(irn));
+                               /* TODO: Next line is overkill. Update_liveness would suffice. */
                                be_liveness(get_irn_irg(bl));
                                break;
                        }
index bf75e77..e8bafa6 100644 (file)
@@ -156,6 +156,7 @@ static INLINE int qnode_get_new_color(const qnode_t *qn, ir_node *irn) {
 static INLINE void qnode_set_new_color(const qnode_t *qn, ir_node *irn, int color) {
        node_stat_t *found = qnode_find_or_insert_node(qn, irn);
        found->new_color = color;
+       DBG((dbg, LEVEL_3, "\t      col(%+F) := %d\n", irn, color));
 }
 
 /**
@@ -178,6 +179,8 @@ static INLINE int qnode_is_pinned_local(const qnode_t *qn, ir_node *irn) {
 static INLINE void qnode_pin_local(const qnode_t *qn, ir_node *irn) {
        node_stat_t *found = qnode_find_or_insert_node(qn, irn);
        found->pinned_local = 1;
+       if (found->new_color == NO_COLOR)
+               found->new_color = get_irn_col(qn->ou->co, irn);
 }
 
 /**
@@ -203,130 +206,56 @@ static INLINE void qnode_pin_local(const qnode_t *qn, ir_node *irn) {
  *             This should be true in SSA.
  */
 static ir_node *qnode_color_irn(const qnode_t *qn, ir_node *irn, int col, const ir_node *trigger) {
-       ir_node *res;
-       struct obstack confl_ob;
-       ir_node **confl, *cn;
-       int i, irn_col;
        const be_chordal_env_t *chordal_env = qn->ou->co->chordal_env;
-       const arch_env_t *arch_env = get_arch_env(qn->ou->co);
        const arch_register_class_t *cls = chordal_env->cls;
+       const arch_env_t *arch_env = chordal_env->main_env->arch_env;
+       int irn_col = qnode_get_new_color(qn, irn);
 
-       DBG((dbg, LEVEL_3, "\t      %+F \tcaused col(%+F) \t%2d --> %2d\n", trigger, irn, qnode_get_new_color(qn, irn), col));
-       obstack_init(&confl_ob);
-       irn_col = qnode_get_new_color(qn, irn);
+       DBG((dbg, LEVEL_3, "\t    %+F \tcaused col(%+F) \t%2d --> %2d\n", trigger, irn, irn_col, col));
 
        if (irn_col == col) {
-               DBG((dbg, LEVEL_4, "\t      Already same color.\n"));
-               goto ret_save;
+               DBG((dbg, LEVEL_3, "\t      %+F same color\n", irn));
+               return CHANGE_SAVE;
        }
        if (pset_find_ptr(pinned_global, irn) || qnode_is_pinned_local(qn, irn)) {
-               res = irn;
-               goto ret_confl;
+               DBG((dbg, LEVEL_3, "\t      %+F conflicting\n", irn));
+               return irn;
+       }
+       if (!arch_reg_is_allocatable(arch_env, irn, -1, arch_register_for_index(cls, col))) {
+               DBG((dbg, LEVEL_3, "\t      %+F impossible\n", irn));
+               return CHANGE_IMPOSSIBLE;
        }
-       if (!arch_reg_is_allocatable(arch_env,
-                                                                irn,
-                                                                -1,
-                                                                arch_register_for_index(cls, col)))
-               goto ret_imposs;
 
-       /* get all nodes which would conflict with this change */
+       /*
+        * Process all nodes which would conflict with this change
+        */
        {
-               struct obstack q;
-               int in, out;
-               ir_node *irn_bl;
-
-               irn_bl = get_nodes_block(irn);
-
-               /* first check for a conflicting node which is 'living in' the irns block */
-               {
-                       ir_node *n;
-                       pset *live_ins = put_live_in(irn_bl, pset_new_ptr_default());
-                       for (n = pset_first(live_ins); n; n = pset_next(live_ins)) {
-                               DBG((dbg, LEVEL_4, "Checking %+F which is live-in at the block\n", n));
-                               if (arch_irn_has_reg_class(arch_env, n, -1, cls)
-                                       && n != trigger && qnode_get_new_color(qn, n) == col
-                                       && nodes_interfere(chordal_env, irn, n)) {
-
-                                       DBG((dbg, LEVEL_4, "\t        %+F\ttroubles\n", n));
-                                       obstack_ptr_grow(&confl_ob, n);
-                                       pset_break(live_ins);
-                                       break;
-                               }
-                       }
-            del_pset(live_ins);
-               }
+               be_ifg_t *ifg = chordal_env->ifg;
+               void *iter = be_ifg_neighbours_iter_alloca(ifg);
+               ir_node *sub_res, *curr;
 
-               /* setup the queue of blocks. */
-               obstack_init(&q);
-               obstack_ptr_grow(&q, irn_bl);
-               in = 1;
-               out = 0;
-
-               /* process the queue. The code below checks for every block dominated
-                * by the irns one, and in which the irn is live, if there are
-                * conflicting nodes */
-               while (out < in) {
-                       ir_node *curr_bl, *sub_bl;
-                       int i, max;
-
-                       curr_bl = ((ir_node **)obstack_base(&q))[out++];
-
-                       /* Add to the result all nodes in the block, which have
-                        * the target color and interfere with the irn */
-                       for (i = 0, max = get_irn_n_outs(curr_bl); i < max; ++i) {
-                               ir_node *n = get_irn_out(curr_bl, i);
-                               DBG((dbg, LEVEL_4, "Checking %+F defined in same block\n", n));
-                               if (arch_irn_has_reg_class(arch_env, n, -1, cls)
-                                       && n != trigger && qnode_get_new_color(qn, n) == col
-                                       && nodes_interfere(chordal_env, irn, n)) {
-                                               DBG((dbg, LEVEL_4, "\t        %+F\ttroubles\n", n));
-                                               obstack_ptr_grow(&confl_ob, n);
+               /*
+                * Try to color all conflicting nodes 'curr'
+                * with the color of the irn itself.
+                */
+               be_ifg_foreach_neighbour(ifg, iter, irn, curr) {
+                       DBG((dbg, LEVEL_3, "\t      Confl %+F(%d)\n", curr, qnode_get_new_color(qn, curr)));
+                       if (qnode_get_new_color(qn, curr) == col && curr != trigger) {
+                               sub_res = qnode_color_irn(qn, curr, irn_col, irn);
+                               if (sub_res != CHANGE_SAVE) {
+                                       be_ifg_neighbours_break(ifg, iter);
+                                       return sub_res;
                                }
                        }
-
-                       /* If irn lives out check i-dominated blocks where the irn lives in */
-                       /* Fill the queue */
-                       if (is_live_out(curr_bl, irn)) {
-                               dominates_for_each(curr_bl, sub_bl)
-                                       if (is_live_in(sub_bl, irn)) {
-                                               obstack_ptr_grow(&q, sub_bl);
-                                               in++;
-                                       }
-                       }
                }
-               obstack_free(&q, NULL);
-               obstack_ptr_grow(&confl_ob, NULL);
-               confl = (ir_node **) obstack_finish(&confl_ob);
        }
 
-       /* process all nodes which would conflict with this change */
-       for (i = 0, cn = confl[0]; cn; cn = confl[++i]) {
-               ir_node *sub_res;
-
-               /* try to color the conflicting node cn with the color of the irn itself */
-               sub_res = qnode_color_irn(qn, cn, irn_col, irn);
-               if (sub_res != CHANGE_SAVE) {
-                       res = sub_res;
-                       goto ret_confl;
-               }
-       }
-       /* if we arrive here all sub changes can be applied, so it's save to change this irn */
-
-ret_save:
-       DBG((dbg, LEVEL_3, "\t      %+F save\n", irn));
-       obstack_free(&confl_ob, NULL);
+       /*
+        * If we arrive here, all sub changes have been applied.
+        * So it's save to change this irn
+        */
        qnode_set_new_color(qn, irn, col);
        return CHANGE_SAVE;
-
-ret_imposs:
-       DBG((dbg, LEVEL_3, "\t      %+F impossible\n", irn));
-       obstack_free(&confl_ob, NULL);
-       return CHANGE_IMPOSSIBLE;
-
-ret_confl:
-       DBG((dbg, LEVEL_3, "\t      %+F conflicting\n", irn));
-       obstack_free(&confl_ob, NULL);
-       return res;
 }
 
 /**
@@ -377,21 +306,6 @@ static int qnode_try_color(const qnode_t *qn) {
        return 1;
 }
 
-typedef int(*confl_f)(const ir_node *a, const ir_node *b, void *data);
-
-/**
- * @param result       Gets filled with the computed maximum independent set.
- * @param count                The size of input arrays / the number of nodes
- * @param nodes                A set of nodes to copmute the max. ind. set for
- * @param weights      Weights associated to the nodes in @p nodes
- * @param confl                Callback function to decide if two values interfere
- * @param data         Passed into all callbacks
- * @return The size of the computed set
- */
-//int max_ind_set(ir_node **result, int count, ir_node **nodes, int *weights, confl_f confl, void *data) {
-//
-//}
-
 /**
  * Determines a maximum weighted independent set with respect to
  * the interference and conflict edges of all nodes in a qnode.
@@ -437,7 +351,7 @@ static INLINE void qnode_max_ind_set(qnode_t *qn, const unit_t *ou) {
        best = bitset_alloca(unsafe_count);
 
        if (unsafe_count > MIS_HEUR_TRIGGER) {
-               /* Heuristik: Greedy trial and error form index 0 to unsafe_count-1 */
+               /* Heuristic: Greedy trial and error form index 0 to unsafe_count-1 */
                for (i=0; i<unsafe_count; ++i) {
                        bitset_set(best, i);
                        /* check if it is a stable set */
@@ -570,6 +484,7 @@ static void ou_optimize(unit_t *ou) {
                /* try */
                if (qnode_try_color(curr))
                        break;
+
                /* no success, so re-insert */
                del_set(curr->changed_nodes);
                curr->changed_nodes = new_set(set_cmp_node_stat_t, SLOTS_CHANGED_NODES);
@@ -579,13 +494,14 @@ static void ou_optimize(unit_t *ou) {
        /* apply the best found qnode */
        if (curr->mis_size >= 2) {
                node_stat_t *ns;
+               int root_col = qnode_get_new_color(curr, ou->nodes[0]);
                DBG((dbg, LEVEL_1, "\t  Best color: %d  Costs: %d << %d << %d\n", curr->color, ou->min_nodes_costs, ou->all_nodes_costs - curr->mis_costs, ou->all_nodes_costs));
                /* globally pin root and all args which have the same color */
                pset_insert_ptr(pinned_global, ou->nodes[0]);
                for (i=1; i<ou->node_count; ++i) {
                        ir_node *irn = ou->nodes[i];
                        int nc = qnode_get_new_color(curr, irn);
-                       if (nc != NO_COLOR && nc == qnode_get_new_color(curr, ou->nodes[0]))
+                       if (nc != NO_COLOR && nc == root_col)
                                pset_insert_ptr(pinned_global, irn);
                }
 
@@ -597,10 +513,6 @@ static void ou_optimize(unit_t *ou) {
                                set_irn_col(ou->co, ns->irn, ns->new_color);
                        }
                }
-               /*
-                * Enable for checking register allocation after each ou
-                * be_ra_chordal_check(ou->co->chordal_env);
-                */
        }
 
        /* free best qnode (curr) and queue */
@@ -612,10 +524,6 @@ static void ou_optimize(unit_t *ou) {
 void co_heur_opt(copy_opt_t *co) {
        unit_t *curr;
        dbg = firm_dbg_register("ir.be.copyoptheur");
-       if (!strcmp(co->name, DEBUG_IRG))
-               firm_dbg_set_mask(dbg, DEBUG_IRG_LVL_HEUR);
-       else
-               firm_dbg_set_mask(dbg, DEBUG_LVL_HEUR);
 
        pinned_global = pset_new_ptr(SLOTS_PINNED_GLOBAL);
        list_for_each_entry(unit_t, curr, &co->units, units)
index 3c3e168..8f49c34 100644 (file)
@@ -993,10 +993,6 @@ int co_ilp_opt(copy_opt_t *co, double time_limit) {
        problem_instance_t *pi;
 
        dbg = firm_dbg_register("ir.be.copyoptilp");
-       if (!strcmp(co->name, DEBUG_IRG))
-               firm_dbg_set_mask(dbg, DEBUG_IRG_LVL_ILP);
-       else
-               firm_dbg_set_mask(dbg, DEBUG_LVL_ILP);
 
        pi = new_pi(co);
        if (!pi->all_simplicial) {
index 308bd22..b82e951 100644 (file)
@@ -185,7 +185,7 @@ static void co_collect_units(ir_node *irn, void *env) {
        } else
 
        /* Proj of a perm with corresponding arg */
-       if (is_Copy(get_arch_env(co), irn)) {
+       if (is_Perm_Proj(get_arch_env(co), irn)) {
                assert(!nodes_interfere(co->chordal_env, irn, get_Copy_src(irn)));
                unit->nodes = xmalloc(2 * sizeof(*unit->nodes));
                unit->costs = xmalloc(2 * sizeof(*unit->costs));
@@ -198,17 +198,20 @@ static void co_collect_units(ir_node *irn, void *env) {
        /* Src == Tgt of a 2-addr-code instruction */
        if (is_2addr_code(get_arch_env(co), irn, &req)) {
                int pos = req.data.pos;
-               unit->nodes = xmalloc(2 * sizeof(*unit->nodes));
-               unit->costs = xmalloc(2 * sizeof(*unit->costs));
-               unit->node_count = 2;
-               unit->nodes[0] = irn;
-               unit->nodes[1] = get_irn_n(irn, pos);
-               unit->costs[1] = co->get_costs(irn, unit->nodes[1], pos);
+               ir_node *other = get_irn_n(irn, pos);
+               if (!nodes_interfere(co->chordal_env, irn, other)) {
+                       unit->nodes = xmalloc(2 * sizeof(*unit->nodes));
+                       unit->costs = xmalloc(2 * sizeof(*unit->costs));
+                       unit->node_count = 2;
+                       unit->nodes[0] = irn;
+                       unit->nodes[1] = other;
+                       unit->costs[1] = co->get_costs(irn, other, pos);
+               }
        } else
                assert(0 && "This is not an optimizable node!");
 
        /* Insert the new unit at a position according to its costs */
-       {
+       if (unit->node_count > 1) {
                int i;
                struct list_head *tmp;
 
@@ -226,6 +229,8 @@ static void co_collect_units(ir_node *irn, void *env) {
                while (tmp->next != &co->units && list_entry_units(tmp->next)->sort_key > unit->sort_key)
                        tmp = tmp->next;
                list_add(&unit->units, tmp);
+       } else {
+               free(unit);
        }
 }
 
@@ -235,7 +240,6 @@ copy_opt_t *new_copy_opt(be_chordal_env_t *chordal_env, int (*get_costs)(ir_node
        copy_opt_t *co;
 
        dbg = firm_dbg_register("ir.be.copyopt");
-       firm_dbg_set_mask(dbg, DEBUG_LVL_CO);
 
        co = xcalloc(1, sizeof(*co));
        co->chordal_env = chordal_env;
@@ -247,10 +251,6 @@ copy_opt_t *new_copy_opt(be_chordal_env_t *chordal_env, int (*get_costs)(ir_node
        len = strlen(s1) + strlen(s2) + strlen(s3) + 5;
        co->name = xmalloc(len);
        snprintf(co->name, len, "%s__%s__%s", s1, s2, s3);
-       if (!strcmp(co->name, DEBUG_IRG))
-               firm_dbg_set_mask(dbg, DEBUG_IRG_LVL_CO);
-       else
-               firm_dbg_set_mask(dbg, DEBUG_LVL_CO);
 
        DBG((dbg, LEVEL_1, "\tCollecting optimization units\n"));
        INIT_LIST_HEAD(&co->units);
@@ -263,17 +263,19 @@ void free_copy_opt(copy_opt_t *co) {
        xfree(co->name);
        list_for_each_entry_safe(unit_t, curr, tmp, &co->units, units) {
                xfree(curr->nodes);
+               xfree(curr->costs);
                xfree(curr);
        }
 }
 
 int is_optimizable_arg(const copy_opt_t *co, ir_node *irn) {
-       int i, max;
        arch_env_t *aenv = co->chordal_env->main_env->arch_env;
+       const ir_edge_t *edge;
 
-       for(i=0, max=get_irn_n_outs(irn); i<max; ++i) {
-               ir_node *n = get_irn_out(irn, i);
+       foreach_out_edge(irn, edge) {
+               ir_node *n = edge->src;
                arch_register_req_t req;
+
                arch_get_register_req(aenv, &req, n, -1);
 
                if(     (       (req.type == arch_register_req_type_should_be_same && get_irn_n(n, req.data.pos) == irn) ||
@@ -282,6 +284,7 @@ int is_optimizable_arg(const copy_opt_t *co, ir_node *irn) {
                        ) && (irn == n || !nodes_interfere(co->chordal_env, irn, n)))
                                return 1;
        }
+
        return 0;
 }
 
index 701f00b..38a0298 100644 (file)
 #include "bechordal_t.h"
 #include "bearch.h"
 
-#define DEBUG_IRG "!!deflate.c__longest_match__datab"
-#define DEBUG_IRG_LVL_CO   SET_LEVEL_1
-#define DEBUG_IRG_LVL_HEUR SET_LEVEL_1
-#define DEBUG_IRG_LVL_ILP  SET_LEVEL_1
-#define DEBUG_LVL_CO   SET_LEVEL_0
-#define DEBUG_LVL_HEUR SET_LEVEL_0
-#define DEBUG_LVL_ILP  SET_LEVEL_0
-
 #define MIS_HEUR_TRIGGER 8
 
-
 typedef int(*cost_fct_t)(ir_node*, ir_node*, int);
 
 /**
@@ -82,6 +73,12 @@ typedef struct _unit_t {
 
 #define list_entry_units(lh) list_entry(lh, unit_t, units)
 
+#define get_Copy_src(irn) (get_irn_n(get_Proj_pred(irn), get_Proj_proj(irn)))
+#define is_Perm(arch_env, irn)                         (arch_irn_classify(arch_env, irn) == arch_irn_class_perm)
+#define is_Reg_Phi(irn)                                                (is_Phi(irn) && mode_is_data(get_irn_mode(irn)))
+#define is_Perm_Proj(arch_env, irn)                    (is_Proj(irn) && is_Perm(arch_env, get_Proj_pred(irn)))
+#define is_2addr_code(arch_env, irn, req)      (arch_get_register_req(arch_env, req, irn, -1)->type == arch_register_req_type_should_be_same)
+
 
 /**
  * Generate the problem. Collect all infos and optimizable nodes.
@@ -93,20 +90,13 @@ copy_opt_t *new_copy_opt(be_chordal_env_t *chordal_env, int (*get_costs)(ir_node
  */
 void free_copy_opt(copy_opt_t *co);
 
-#define get_Copy_src(irn) (get_irn_n(get_Proj_pred(irn), get_Proj_proj(irn)))
-#define is_Perm(arch_env, irn)                         (arch_irn_classify(arch_env, irn) == arch_irn_class_perm)
-
-#define is_Reg_Phi(irn)                                                (is_Phi(irn) && mode_is_data(get_irn_mode(irn)))
-#define is_Copy(arch_env, irn)                         (is_Proj(irn) && is_Perm(arch_env, get_Proj_pred(irn)))
-#define is_2addr_code(arch_env, irn, req)      (arch_get_register_req(arch_env, req, irn, -1)->type == arch_register_req_type_should_be_same)
-
 /**
  * Checks if a node is optimizable, viz. has somthing to do with coalescing
  * @param arch The architecture environment
  * @param irn  The irn to check
  * @param req  A register_requirement structure (used to check for 2-addr-code)
  */
-#define is_optimizable(arch, irn, req) (is_Reg_Phi(irn) || is_Copy(arch, irn) || is_2addr_code(arch, irn, req))
+#define is_optimizable(arch, irn, req) (is_Reg_Phi(irn) || is_Perm_Proj(arch, irn) || is_2addr_code(arch, irn, req))
 
 /**
  * Checks if the irn is a non-interfering argument of a node which 'is_optimizable'
index 5fc48f4..d24842c 100644 (file)
@@ -5,9 +5,11 @@
  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
 
  * Main file for the optimization reducing the copies needed for:
- * - phi coalescing
- * - register-constrained nodes
+ * - Phi coalescing
+ * - Register-constrained nodes
+ * - Two-address code instructions
  */
+
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 #include "phiclass.h"
 
 #define DO_HEUR
-#undef DO_ILP_5_SEC
-#undef DO_ILP_30_SEC
+#undef DO_CLASSES
 #undef DO_ILP
 
-#define DEBUG_LVL SET_LEVEL_1
 static firm_dbg_module_t *dbg = NULL;
 
-void be_copy_opt_init(void) {
-       dbg = firm_dbg_register("ir.be.copyoptmain");
-       firm_dbg_set_mask(dbg, DEBUG_LVL);
-}
+
+/**
+ * Helpers for saving and restoring colors of nodes.
+ * Used to get dependable and comparable benchmark results.
+ */
+#if (defined(DO_HEUR) && defined(DO_BETTER)) || (defined(DO_HEUR) && defined(DO_ILP)) || (defined(DO_BETTER) && defined(DO_ILP))
 
 typedef struct color_saver {
        arch_env_t *arch_env;
        be_chordal_env_t *chordal_env;
        pmap *saved_colors;
-       int flag;  /* 0 save; 1 load */
+       int flag; /* 0 save, 1 load */
 } color_save_t;
 
 static void save_load(ir_node *irn, void *env) {
@@ -66,93 +68,118 @@ static void load_colors(color_save_t *color_saver) {
        irg_walk_graph(color_saver->chordal_env->irg, save_load, NULL, color_saver);
 }
 
+#endif /* Need save/load stuff */
+
+
+
+void be_copy_opt_init(void) {
+       dbg = firm_dbg_register("ir.be.copyoptmain");
+}
+
+
+
 void be_copy_opt(be_chordal_env_t *chordal_env) {
        copy_opt_t *co;
-       int costs, costs_init=-1, costs_heur=-1, costs_ilp_5_sec=-1, costs_ilp_30_sec=-1, costs_ilp=-1;
-       int lower_bound = -1;
-       int was_optimal = 0;
 
+#ifdef DO_STAT
+       lc_timer_t *timer;
        color_save_t saver;
-       saver.arch_env = chordal_env->main_env->arch_env;
-       saver.chordal_env = chordal_env;
-       saver.saved_colors = pmap_create();
+       int costs, costs_inevit, costs_init, costs_heur, costs_classes, costs_ilp, lower_bound;
+#endif
 
-       /* BETTER: You can remove this if you replace all
-        * `grep get_irn_out *.c` by the irouts.h module.*/
-       compute_irg_outs(chordal_env->irg);
 
        co = new_copy_opt(chordal_env, get_costs_loop_depth);
        DBG((dbg, LEVEL_1, "----> CO: %s\n", co->name));
        phi_class_compute(chordal_env->irg);
 
+
 #ifdef DO_STAT
-       lower_bound = co_get_lower_bound(co);
-       DBG((dbg, LEVEL_1, "Lower Bound: %3d\n", lower_bound));
-       DBG((dbg, LEVEL_1, "Inevit Costs: %3d\n", co_get_inevit_copy_costs(co)));
-
-       costs = co_get_copy_costs(co);
-       costs_init = costs;
-       copystat_add_max_costs(co_get_max_copy_costs(co));
-       copystat_add_inevit_costs(co_get_inevit_copy_costs(co));
-       copystat_add_init_costs(costs_init);
-       DBG((dbg, LEVEL_1, "Init costs: %3d\n", costs_init));
+#if (defined(DO_HEUR) && defined(DO_BETTER)) || (defined(DO_HEUR) && defined(DO_ILP)) || (defined(DO_BETTER) && defined(DO_ILP))
+               saver.arch_env = chordal_env->main_env->arch_env;
+               saver.chordal_env = chordal_env;
+               saver.saved_colors = pmap_create();
+               save_colors(&saver);
+#endif
+
+               costs_inevit = co_get_inevit_copy_costs(co);
+               lower_bound  = co_get_lower_bound(co);
+               costs_init   = co_get_copy_costs(co);
+
+               DBG((dbg, LEVEL_1, "Inevit Costs: %3d\n", costs_inevit));
+               DBG((dbg, LEVEL_1, "Lower Bound: %3d\n", lower_bound));
+               DBG((dbg, LEVEL_1, "Init costs: %3d\n", costs_init));
+
+               copystat_add_inevit_costs(costs_inevit);
+               copystat_add_init_costs(costs_init);
+               copystat_add_max_costs(co_get_max_copy_costs(co));
 #endif
 
-//     save_colors(&saver);
 
 #ifdef DO_HEUR
-       {
-               lc_timer_t *timer = lc_timer_register("heur", NULL);
-               lc_timer_reset_and_start(timer);
-               co_heur_opt(co);
-               lc_timer_stop(timer);
-               copystat_add_heur_time(lc_timer_elapsed_msec(timer));
-       }
 #ifdef DO_STAT
-       costs = co_get_copy_costs(co);
-       costs_heur = costs;
-       copystat_add_heur_costs(costs_heur);
-       DBG((dbg, LEVEL_1, "Heur costs: %3d\n", costs_heur));
+       timer = lc_timer_register("heur", NULL);
+       lc_timer_reset_and_start(timer);
 #endif
-       assert(lower_bound == -1 || costs_heur == -1 || lower_bound <= costs_heur);
+
+       co_heur_opt(co);
+
+#ifdef DO_STAT
+       lc_timer_stop(timer);
+       costs_heur = co_get_copy_costs(co);
+       DBG((dbg, LEVEL_1, "Heur costs: %3d\n", costs_heur));
+       copystat_add_heur_time(lc_timer_elapsed_msec(timer));
+       copystat_add_heur_costs(costs_heur);
+       assert(lower_bound <= costs_heur);
 #endif
+#endif /* DO_HEUR */
 
-#ifdef DO_ILP_5_SEC
-       load_colors(&saver);
-       was_optimal = co_ilp_opt(co, 5.0);
+
+
+#ifdef DO_CLASSES
 #ifdef DO_STAT
-       costs = co_get_copy_costs(co);
-       costs_ilp_5_sec = costs;
-       copystat_add_ilp_5_sec_costs(costs_ilp_5_sec);
-       DBG((dbg, LEVEL_1, "5_Sec costs: %3d\n", costs_ilp_5_sec));
+#ifdef DO_HEUR
+       load_colors(&saver);
 #endif
+       timer = lc_timer_register("classes", NULL);
+       lc_timer_reset_and_start(timer);
 #endif
 
-#ifdef DO_ILP_30_SEC
-       if (!was_optimal) {
-               load_colors(&saver);
-               co_ilp_opt(co, 30.0);
-       }
+       co_classes_opt(co);
+
 #ifdef DO_STAT
-       costs = co_get_copy_costs(co);
-       costs_ilp_30_sec = costs;
-       copystat_add_ilp_30_sec_costs(costs_ilp_30_sec);
-       DBG((dbg, LEVEL_1, "30_Sec costs: %3d\n", costs_ilp_30_sec));
-#endif
+       lc_timer_stop(timer);
+       costs_classes = co_get_copy_costs(co);
+       DBG((dbg, LEVEL_1, "Classes costs: %3d\n", costs_classes));
+       copystat_add_classes_time(lc_timer_elapsed_msec(timer));
+       copystat_add_classes_costs(costs_heur);
+       assert(lower_bound <= costs_classes);
 #endif
+#endif /* DO_CLASSES */
+
+
 
 #ifdef DO_ILP
+#ifdef DO_STAT
+#if defined(DO_HEUR) || defined(DO_CLASSES)
        load_colors(&saver);
+#endif
+#endif
+
        co_ilp_opt(co, 60.0);
+
 #ifdef DO_STAT
-       costs = co_get_copy_costs(co);
-       costs_ilp = costs;
-       copystat_add_opt_costs(costs_ilp);
+       costs_ilp = co_get_copy_costs(co);
        DBG((dbg, LEVEL_1, "Opt  costs: %3d\n", costs_ilp));
+       copystat_add_opt_costs(costs_ilp);
+       assert(lower_bound <= costs_ilp);
 #endif
-       assert(lower_bound == -1 || costs_ilp == -1 || lower_bound <= costs_ilp);
-#endif
+#endif /* DO_ILP */
+
 
+#ifdef DO_STAT
+#if (defined(DO_HEUR) && defined(DO_BETTER)) || (defined(DO_HEUR) && defined(DO_ILP)) || (defined(DO_BETTER) && defined(DO_ILP))
        pmap_destroy(saver.saved_colors);
+#endif
+#endif
        free_copy_opt(co);
 }
index 51d2cb1..2156197 100644 (file)
@@ -4,9 +4,10 @@
  * Copyright:   (c) Universitaet Karlsruhe
  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
 
- * Main header for the optimization reducing the copy costs needed for:
- * - phi coalescing
- * - register-constrained nodes
+ * Main file for the optimization reducing the copies needed for:
+ * - Phi coalescing
+ * - Register-constrained nodes
+ * - Two-address code instructions
  */
 
 #ifndef _BECOPYOPTMAIN_H
@@ -19,6 +20,5 @@
 
 void be_copy_opt_init(void);
 void be_copy_opt(be_chordal_env_t *chordal_env);
-void be_copy_opt_verify(be_chordal_env_t *chordal_env);
 
 #endif
index f202392..7fa9c06 100644 (file)
@@ -125,8 +125,10 @@ static void irg_stat_walker(ir_node *node, void *env) {
        if (is_Reg_Phi(node)) /* collect phis */
                pset_insert_ptr(all_phi_nodes, node);
 
-       if (is_Copy(arch_env, node))
+       if (is_Perm_Proj(arch_env, node))
                pset_insert_ptr(all_copy_nodes, node);
+
+       /* TODO: Add 2-Addr-Code nodes */
 }
 
 static void copystat_collect_irg(ir_graph *irg, arch_env_t *arch_env) {
index 143c40a..76ca11c 100644 (file)
@@ -120,7 +120,7 @@ int be_ifg_is_simplicial(const be_ifg_t *ifg, const ir_node *irn)
 
 void be_ifg_check(const be_ifg_t *ifg)
 {
-       void *iter1 = be_ifg_neighbours_iter_alloca(ifg);
+       void *iter1 = be_ifg_nodes_iter_alloca(ifg);
        void *iter2 = be_ifg_neighbours_iter_alloca(ifg);
 
        ir_node *n, *m;
index 79b8017..28ca81d 100644 (file)
@@ -20,6 +20,7 @@
 #include "irgwalk.h"
 
 #include "be_t.h"
+#include "belive_t.h"
 #include "bera.h"
 #include "beifg_t.h"
 #include "bechordal_t.h"
@@ -71,8 +72,9 @@ static void find_nodes(const void *self, void *iter) {
        nodes_iter_t *it = iter;
 
        obstack_init(&it->obst);
-       it->n    = 0;
-       it->curr = 0;
+       it->n     = 0;
+       it->curr  = 0;
+       it->env   = ifg->env;
 
        irg_block_walk_graph(ifg->env->irg, nodes_walker, NULL, iter);
        it->nodes = obstack_finish(&it->obst);
@@ -118,80 +120,64 @@ static void ifg_std_nodes_break(const void *self, void *iter)
 typedef struct _adj_iter_t {
        const be_chordal_env_t *env;
        const ir_node *irn;
-       struct obstack obst;
-       int degree;
-       unsigned visited_nr;
-       unsigned build_list : 1;
-
-       int curr;
-       ir_node **neighbours;
+       int reached_end;
+       pset *neighbours;
 } adj_iter_t;
 
 static void find_neighbour_walker(ir_node *block, void *data)
 {
        adj_iter_t *it          = data;
-       unsigned visited        = it->visited_nr;
        struct list_head *head  = get_block_border_head(it->env, block);
 
        border_t *b;
        int has_started = 0;
 
+       if(!is_live_in(block, it->irn) && block != get_nodes_block(it->irn))
+               return;
+
        foreach_border_head(head, b) {
                ir_node *irn = b->irn;
 
-               if(irn == it->irn)
-                       has_started = b->is_def;
-
-               /*
-                * If the def/use of the node is inside the live range
-                * of the node in question, they interfere.
-                * To avoid that a node is added twice, we record the
-                * visit in the visited number provided by core firm.
-                */
-               else if(has_started && get_irn_visited(irn) < visited) {
-                       if(it->build_list)
-                               obstack_ptr_grow(&it->obst, irn);
-
-                       set_irn_visited(irn, visited);
-                       it->degree++;
+               if(irn == it->irn) {
+                       if(b->is_def)
+                               has_started = 1;
+                       else
+                               break; /* if we reached the end of the node's lifetime we can safely break */
+               }
+               else if(b->is_def) {
+                       /* if any other node than the one in question starts living, add it to the set */
+                       pset_insert_ptr(it->neighbours, irn);
+               }
+               else if(!has_started) {
+                       /* we only delete, if the live range in question has not yet started */
+                       pset_remove_ptr(it->neighbours, irn);
                }
+
        }
 }
 
-static void find_neighbours(const ifg_std_t *ifg, adj_iter_t *it, const ir_node *irn, int build_list)
+static void find_neighbours(const ifg_std_t *ifg, adj_iter_t *it, const ir_node *irn)
 {
-       if(build_list)
-               obstack_init(&it->obst);
-
-       it->env        = ifg->env;
-       it->irn        = irn;
-       it->degree     = 0;
-       it->visited_nr = get_irg_visited(ifg->env->irg) + 1;
-       it->build_list = build_list;
-       it->neighbours = NULL;
-       it->curr       = 0;
+       it->env         = ifg->env;
+       it->irn         = irn;
+       it->neighbours  = pset_new_ptr(16);
+       it->reached_end = 0;
 
-       set_irg_visited(ifg->env->irg, it->visited_nr);
        dom_tree_walk(get_nodes_block(irn), find_neighbour_walker, NULL, it);
-
-       if(build_list)
-               it->neighbours = obstack_finish(&it->obst);
 }
 
 static INLINE void neighbours_break(adj_iter_t *it, int force)
 {
-       if((it->curr >= it->degree || force) && it->neighbours) {
-               obstack_free(&it->obst, NULL);
+       if((it->reached_end || force) && it->neighbours) {
+               del_pset(it->neighbours);
                it->neighbours = NULL;
        }
 }
 
 static ir_node *get_next_neighbour(adj_iter_t *it) {
-       ir_node *res = NULL;
-
-       if(it->curr < it->degree)
-               res = it->neighbours[it->curr++];
+       ir_node *res = pset_next(it->neighbours);
 
+       it->reached_end = res == NULL;
        neighbours_break(it, 0);
 
        return res;
@@ -199,8 +185,9 @@ static ir_node *get_next_neighbour(adj_iter_t *it) {
 
 static ir_node *ifg_std_neighbours_begin(const void *self, void *iter, const ir_node *irn)
 {
-       find_neighbours(self, iter, irn, 1);
-       return get_next_neighbour(iter);
+       adj_iter_t *it = iter;
+       find_neighbours(self, iter, irn);
+       return pset_first(it->neighbours);
 }
 
 static ir_node *ifg_std_neighbours_next(const void *self, void *iter)
@@ -216,8 +203,11 @@ static void ifg_std_neighbours_break(const void *self, void *iter)
 static int ifg_std_degree(const void *self, const ir_node *irn)
 {
        adj_iter_t it;
-       find_neighbours(self, &it, irn, 0);
-       return it.degree;
+       int degree;
+       find_neighbours(self, &it, irn);
+       degree = pset_count(it.neighbours);
+       neighbours_break(&it, 1);
+       return degree;
 }
 
 static const be_ifg_impl_t ifg_std_impl = {
index a2a3bf4..bf8700a 100644 (file)
@@ -49,4 +49,6 @@ struct _be_ifg_t {
 
 #endif
 
+void be_ifg_check(const be_ifg_t *ifg);
+
 #endif /*_BEIFG_T_H_*/
index c878c94..d9b2836 100644 (file)
@@ -72,7 +72,7 @@ static unsigned dump_flags = DUMP_INITIAL | DUMP_SCHED | DUMP_PREPARED | DUMP_RA
 static const be_ra_t *ra = &be_ra_chordal_allocator;
 
 /* back end instruction set architecture to use */
-static const arch_isa_if_t *isa_if = &ia32_isa_if;
+static const arch_isa_if_t *isa_if = &firm_isa;
 
 #ifdef WITH_LIBCORE