added bearch.c
[libfirm] / ir / be / becopyheur.c
index a7c6d59..a3ae35b 100644 (file)
@@ -8,8 +8,20 @@
  * @author Daniel Grund
  * @date 12.04.2005
  */
-
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_ALLOCA_H
+#include <alloca.h>
+#endif
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+
+#include "xmalloc.h"
 #include "becopyopt.h"
+#include "becopystat.h"
 
 #define DEBUG_LVL 0 //SET_LEVEL_1
 static firm_dbg_module_t *dbg = NULL;
@@ -31,7 +43,7 @@ typedef struct _conflict_t {
 
 /**
  * If an irn is changed, the changes first get stored in a node_stat_t,
- * to allow undo of changes  (=drop new data) in case of conflicts.
+ * to allow undo of changes (=drop new data) in case of conflicts.
  */
 typedef struct _node_stat_t {
        const ir_node *irn;
@@ -44,10 +56,11 @@ typedef struct _node_stat_t {
  */
 typedef struct _qnode_t {
        struct list_head queue;         /**< chaining of unit_t->queue */
+       const unit_t *ou;                       /**< the opt unit this qnode belongs to */
        int color;                                      /**< target color */
        set *conflicts;                         /**< contains conflict_t's. All internal conflicts */
        int mis_size;                           /**< number of nodes in the mis. */
-       const ir_node **mis;            /**< the nodes of unit_t->nodes[] beeing part of the max idependent set */
+       const ir_node **mis;            /**< the nodes of unit_t->nodes[] being part of the max independent set */
        set *changed_nodes;                     /**< contains node_stat_t's. */
 } qnode_t;
 
@@ -176,11 +189,11 @@ static INLINE void qnode_pin_local(const qnode_t *qn, const ir_node *irn) {
  * @param  irn The node to set the color for
  * @param  col The color to set
  * @param  trigger The irn that caused the wish to change the color of the irn
- * @return CHANGE_SAVE iff setting the color is possible, with all transiteve effects.
+ * @return CHANGE_SAVE iff setting the color is possible, with all transitive effects.
  *         CHANGE_IMPOSSIBLE iff conflicts with reg-constraintsis occured.
  *         Else the first conflicting ir_node encountered is returned.
  *
- * ASSUMPTION: Assumes that a life range of a single value can't be spilt into
+ * ASSUMPTION: Assumes that a life range of a single value can't be split into
  *                        several smaller intervals where other values can live in between.
  *             This should be true in SSA.
  */
@@ -196,12 +209,12 @@ static const ir_node *qnode_color_irn(const qnode_t *qn, const ir_node *irn, int
 
        if (irn_col == col)
                goto ret_save;
-       if (!is_possible_color(irn, col))
-               goto ret_imposs;
        if (pset_find_ptr(pinned_global, irn) || qnode_is_pinned_local(qn, irn)) {
                res = irn;
                goto ret_confl;
        }
+       if (!qn->ou->co->isa->is_reg_allocatable(irn, arch_register_for_index(qn->ou->co->cls, col)))
+               goto ret_imposs;
 
        /* get all nodes which would conflict with this change */
        {
@@ -286,7 +299,7 @@ ret_save:
 ret_imposs:
        DBG((dbg, LEVEL_3, "\t      %n impossible\n", irn));
        obstack_free(&confl_ob, NULL);
-       return res;
+       return CHANGE_IMPOSSIBLE;
 
 ret_confl:
        DBG((dbg, LEVEL_3, "\t      %n conflicting\n", irn));
@@ -357,7 +370,7 @@ static INLINE void qnode_max_ind_set(qnode_t *qn, const unit_t *ou) {
        /* stores the currently examined set */
        curr = alloca(all_size*sizeof(*curr));
 
-       while (1) { /* this loop will terminate because at least a single node'll be a max indep. set */
+       while (1) { /* this loop will terminate because at least a single node will be a max indep. set */
                /* build current set */
                for (i=0; i<curr_size; ++i)
                        curr[i] = all[which[all_size-curr_size+i]];
@@ -406,7 +419,8 @@ conflict_found:
  * Creates a new qnode
  */
 static INLINE qnode_t *new_qnode(const unit_t *ou, int color) {
-       qnode_t *qn = malloc(sizeof(*qn));
+       qnode_t *qn = xmalloc(sizeof(*qn));
+       qn->ou = ou;
        qn->color = color;
        qn->mis = malloc(ou->node_count * sizeof(*qn->mis));
        qn->conflicts = new_set(set_cmp_conflict_t, SLOTS_CONFLICTS);
@@ -420,12 +434,12 @@ static INLINE qnode_t *new_qnode(const unit_t *ou, int color) {
 static INLINE void free_qnode(qnode_t *qn) {
        del_set(qn->conflicts);
        del_set(qn->changed_nodes);
-       free(qn->mis);
-       free(qn);
+       xfree(qn->mis);
+       xfree(qn);
 }
 
 /**
- * Inserts a qnode in the sorted queue of the outimization unit. Queue is
+ * Inserts a qnode in the sorted queue of the optimization unit. Queue is
  * ordered by field 'size' (the size of the mis) in decreasing order.
  */
 static INLINE void ou_insert_qnode(unit_t *ou, qnode_t *qn) {
@@ -465,6 +479,7 @@ static INLINE void ou_insert_qnode(unit_t *ou, qnode_t *qn) {
 static void ou_optimize(unit_t *ou) {
        int i;
        qnode_t *curr, *tmp;
+       bitset_t *pos_regs = bitset_alloca(ou->co->cls->n_regs);
 
        DBG((dbg, LEVEL_1, "\tOptimizing unit:\n"));
        for (i=0; i<ou->node_count; ++i)
@@ -472,9 +487,9 @@ static void ou_optimize(unit_t *ou) {
 
        /* init queue */
        INIT_LIST_HEAD(&ou->queue);
-       for (i=0; i<MAX_COLORS; ++i)
-               if (is_possible_color(ou->nodes[0], i))
-                       ou_insert_qnode(ou, new_qnode(ou, i));
+       ou->co->isa->get_allocatable_regs(ou->nodes[0], ou->co->cls, pos_regs);
+       bitset_foreach(pos_regs, i)
+               ou_insert_qnode(ou, new_qnode(ou, i));
 
        /* search best */
        while (!list_empty(&ou->queue)) {
@@ -494,6 +509,8 @@ static void ou_optimize(unit_t *ou) {
 
        /* apply the best found qnode */
        if (curr->mis_size >= 2) {
+               node_stat_t *ns;
+
                DBG((dbg, LEVEL_1, "\t  Best color: %d  Copies: %d/%d\n", curr->color, ou->interf+ou->node_count-curr->mis_size, ou->interf+ou->node_count-1));
                /* globally pin root and eventually others */
                pset_insert_ptr(pinned_global, ou->nodes[0]);
@@ -505,7 +522,6 @@ static void ou_optimize(unit_t *ou) {
                }
 
                /* set color of all changed nodes */
-               node_stat_t *ns;
                for (ns = set_first(curr->changed_nodes); ns; ns = set_next(curr->changed_nodes)) {
                        /* NO_COLOR is possible, if we had an undo */
                        if (ns->new_color != NO_COLOR) {
@@ -525,11 +541,13 @@ void co_heur_opt(copy_opt_t *co) {
        unit_t *curr;
        dbg = firm_dbg_register("ir.be.copyoptheur");
        firm_dbg_set_mask(dbg, DEBUG_LVL);
+       if (!strcmp(co->name, DEBUG_IRG))
+               firm_dbg_set_mask(dbg, -1);
 
        pinned_global = pset_new_ptr(SLOTS_PINNED_GLOBAL);
-
        list_for_each_entry(unit_t, curr, &co->units, units)
-               ou_optimize(curr);
+               if (curr->node_count > 1)
+                       ou_optimize(curr);
 
        del_pset(pinned_global);
 }