Lots of changes: Removed all file for phi-opt. Generic approach is now
authorDaniel Grund <grund@cs.uni-saarland.de>
Tue, 19 Apr 2005 10:14:45 +0000 (10:14 +0000)
committerDaniel Grund <grund@cs.uni-saarland.de>
Tue, 19 Apr 2005 10:14:45 +0000 (10:14 +0000)
copy-opt (phi-opt + register constrained nodes).

Additionally slightliy changed algo for copy-opt heuristic.
becopystat has to be done when new bemain.c is ready.

16 files changed:
ir/be/Makefile.in
ir/be/becopyheur.c [new file with mode: 0644]
ir/be/becopyilp.c [new file with mode: 0644]
ir/be/becopyopt.c [new file with mode: 0644]
ir/be/becopyopt.h [new file with mode: 0644]
ir/be/becopyoptmain.c [new file with mode: 0644]
ir/be/becopyoptmain.h [new file with mode: 0644]
ir/be/becopystat.c [new file with mode: 0644]
ir/be/becopystat.h [new file with mode: 0644]
ir/be/bemain.c
ir/be/bephicoal.c [deleted file]
ir/be/bephicoal_t.h [deleted file]
ir/be/bephicoalilp.c [deleted file]
ir/be/bephicoalilp_t.h [deleted file]
ir/be/bephiopt.c [deleted file]
ir/be/bephiopt.h [deleted file]

index bc68ce9..5ce6d22 100644 (file)
@@ -22,8 +22,9 @@ SOURCES = $(INSTALL_HEADERS)
 SOURCES +=     Makefile.in besched.h belistsched.h belistsched.c \
        beutil.h bemain.c besched.c bemain.c belive.c belive.h benumb.h \
        benumb_t.h benumb.c bechordal.c bera.c beutil.c phistat.c \
-       bephiopt.c bephicoal.c bephicoalilp.c bera.h bechordalspill.c \
-       beasm_dump_globals.c beasm_asm_gnu.c bearch.h bearch.c
+       bera.h bechordalspill.c beasm_dump_globals.c beasm_asm_gnu.c \
+       bearch.h bearch.c sp_matrix.c becopyoptmain.c becopyopt.c becopyheur.c \
+       becopyilp.c becopystat.c
 
 include $(topdir)/MakeRules
 
diff --git a/ir/be/becopyheur.c b/ir/be/becopyheur.c
new file mode 100644 (file)
index 0000000..358a1f4
--- /dev/null
@@ -0,0 +1,522 @@
+/**
+ * Heuristic for minimizing copies using a queue which holds 'qnodes' not yet
+ * examined. A qnode has a 'target color', nodes out of the opt unit and
+ * a 'conflict graph'. A 'max indep set' is determined form these. We try to
+ * color this mis using a color-exchanging mechanism. Occuring conflicts are
+ * modeled with 'conflict edges' and the qnode is reinserted in the queue. The
+ * first qnode colored without conflicts is the best one.
+ * @author Daniel Grund
+ * @date 12.04.2005
+ */
+
+#include "becopyopt.h"
+
+#define DEBUG_LVL SET_LEVEL_1
+static firm_dbg_module_t *dbg = NULL;
+
+#define SLOTS_PINNED_GLOBAL 256
+#define SLOTS_CONFLICTS 8
+#define SLOTS_CHANGED_NODES 32
+
+#define MIN(a,b) ((a<b)?a:b)
+#define list_entry_queue(lh) list_entry(lh, qnode_t, queue)
+#define HASH_CONFLICT(c) (HASH_PTR(c.n1) ^ HASH_PTR(c.n2))
+
+/**
+ * Modeling additional conflicts between nodes. NOT live range interference
+ */
+typedef struct _conflict_t {
+       const ir_node *n1, *n2;
+} 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.
+ */
+typedef struct _node_stat_t {
+       const ir_node *irn;
+       int new_color;
+       int pinned_local :1;
+} node_stat_t;
+
+/**
+ * Represents a node in the optimization queue.
+ */
+typedef struct _qnode_t {
+       struct list_head queue;         /**< chaining of unit_t->queue */
+       int color;                                      /**< target color */
+       bitset_t *nodes;                        /**< marks the nodes of unit_t->nodes[i] beeing part of this qnode */
+       set *conflicts;                         /**< contains conflict_t's. All internal conflicts */
+       int size;                                       /**< number of nodes in the mis. equals number of set bits in mis */
+       bitset_t *mis;                          /**< marks the nodes of unit_t->nodes[i] beeing part of the max idependent set */
+       set *changed_nodes;                     /**< contains node_stat_t's. */
+} qnode_t;
+
+
+static int set_cmp_conflict_t(const void *x, const void *y, size_t size) {
+       const conflict_t *xx = x;
+       const conflict_t *yy = y;
+       return ! (xx->n1 == yy->n1 && xx->n2 == yy->n2);
+}
+
+/**
+ * If a local pinned conflict occurs, a new edge in the conflict graph is added.
+ * The next maximum independent set build, will regard it.
+ */
+static INLINE void qnode_add_conflict(const qnode_t *qn, const ir_node *n1, const ir_node *n2) {
+       conflict_t c;
+       DBG((dbg, LEVEL_3, "\t    %n -- %n\n", n1, n2));
+
+       if ((int)n1 < (int)n2) {
+               c.n1 = n1;
+               c.n2 = n2;
+       } else {
+               c.n1 = n2;
+               c.n2 = n1;
+       }
+       set_insert(qn->conflicts, &c, sizeof(c), HASH_CONFLICT(c));
+}
+
+/**
+ * Checks if two nodes are in a conflict.
+ */
+static INLINE int qnode_are_conflicting(const qnode_t *qn, const ir_node *n1, const ir_node *n2) {
+       conflict_t c;
+       /* search for live range interference */
+       if (values_interfere(n1, n2))
+               return 1;
+       /* search for recoloring conflicts */
+       if ((int)n1 < (int)n2) {
+               c.n1 = n1;
+               c.n2 = n2;
+       } else {
+               c.n1 = n2;
+               c.n2 = n1;
+       }
+       return (int) set_find(qn->conflicts, &c, sizeof(c), HASH_CONFLICT(c));
+}
+
+static int set_cmp_node_stat_t(const void *x, const void *y, size_t size) {
+       return ((node_stat_t *)x)->irn != ((node_stat_t *)y)->irn;
+}
+
+/**
+ * Finds a node status entry of a node if existent. Otherwise return NULL
+ */
+static INLINE node_stat_t *qnode_find_node(const qnode_t *qn, const ir_node *irn) {
+       node_stat_t find;
+       find.irn = irn;
+       return set_find(qn->changed_nodes, &find, sizeof(find), HASH_PTR(irn));
+}
+
+/**
+ * Finds a node status entry of a node if existent. Otherwise it will return
+ * an initialized new entry for this node.
+ */
+static INLINE node_stat_t *qnode_find_or_insert_node(const qnode_t *qn, const ir_node *irn) {
+       node_stat_t find;
+       find.irn = irn;
+       find.new_color = NO_COLOR;
+       find.pinned_local = 0;
+       return set_insert(qn->changed_nodes, &find, sizeof(find), HASH_PTR(irn));
+}
+
+/**
+ * Returns the virtual color of a node if set before, else returns the real color.
+ */
+static INLINE int qnode_get_new_color(const qnode_t *qn, const ir_node *irn) {
+       node_stat_t *found = qnode_find_node(qn, irn);
+       if (found)
+               return found->new_color;
+       else
+               return get_irn_color(irn);
+}
+
+/**
+ * Sets the virtual color of a node.
+ */
+static INLINE void qnode_set_new_color(const qnode_t *qn, const ir_node *irn, int color) {
+       node_stat_t *found = qnode_find_or_insert_node(qn, irn);
+       found->new_color = color;
+}
+
+/**
+ * Checks if a node is local pinned. A node is local pinned, iff it belongs
+ * to the same optimization unit and has been optimized before the current
+ * processed node.
+ */
+static INLINE int qnode_is_pinned_local(const qnode_t *qn, const ir_node *irn) {
+       node_stat_t *found = qnode_find_node(qn, irn);
+       if (found)
+               return found->pinned_local;
+       else
+               return 0;
+}
+
+/**
+ * Local-pins a node, so optimizations of further nodes of the same opt unit
+ * can handle situations in which a color change would undo prior optimizations.
+ */
+static INLINE void qnode_pin_local(const qnode_t *qn, const ir_node *irn) {
+       node_stat_t *found = qnode_find_or_insert_node(qn, irn);
+       found->pinned_local = 1;
+}
+
+/**
+ * Possible return values of qnode_color_irn()
+ */
+#define CHANGE_SAVE NULL
+#define CHANGE_IMPOSSIBLE (ir_node *)1
+#define is_conflicting_node(n) (((int)n) > 1)
+
+/**
+ * Performs virtual re-coloring of node @p n to color @p col. Virtual colors of
+ * other nodes are changed too, as required to preserve correctness. Function is
+ * aware of local and global pinning. Recursive.
+ * @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.
+ *         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
+ *                        several smaller intervals where other values can live in between.
+ *             This should be true in SSA.
+ */
+static const ir_node *qnode_color_irn(const qnode_t *qn, const ir_node *irn, int col, const ir_node *trigger, const copy_opt_t *co) {
+       const ir_node *res;
+       struct obstack confl_ob;
+       ir_node **confl, *cn;
+       int i, irn_col;
+
+       DBG((dbg, LEVEL_3, "\t\t%n \tcaused col(%n) \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);
+
+       if (irn_col == col)
+               goto ret_save;
+       if (pset_find_ptr(co->pinned_global, irn) || qnode_is_pinned_local(qn, irn)) {
+               res = irn;
+               goto ret_confl;
+       }
+
+       /* get 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 = get_live_in(irn_bl);
+                       for (n = pset_first(live_ins); n; n = pset_next(live_ins))
+                               if (is_allocatable_irn(n) && n != trigger && qnode_get_new_color(qn, n) == col && values_interfere(irn, n)) {
+                                       DBG((dbg, LEVEL_4, "\t\t    %n\ttroubles\n", n));
+                                       obstack_ptr_grow(&confl_ob, n);
+                                       pset_break(live_ins);
+                                       break;
+                               }
+               }
+
+               /* 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);
+                               if (is_allocatable_irn(n) && n != trigger && qnode_get_new_color(qn, n) == col && values_interfere(irn, n)) {
+                                       DBG((dbg, LEVEL_4, "\t\t    %n\ttroubles\n", n));
+                                       obstack_ptr_grow(&confl_ob, n);
+                               }
+                       }
+
+                       /* 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]) {
+               const 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, co);
+               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\t%n save\n", irn));
+       obstack_free(&confl_ob, NULL);
+       qnode_set_new_color(qn, irn, col);
+       return CHANGE_SAVE;
+
+ret_confl:
+       DBG((dbg, LEVEL_3, "\t\t%n conflicting\n", irn));
+       obstack_free(&confl_ob, NULL);
+       return res;
+}
+
+/**
+ * Tries to set the colors for all members of this queue node;
+ * to the target color qn->color
+ * @returns 1 iff all members colors could be set
+ *          0 else
+ */
+static int qnode_try_color(const qnode_t *qn, const unit_t *ou, const copy_opt_t *co) {
+       int i;
+       bitset_foreach(qn->mis, i) {
+               const ir_node *test_node, *confl_node;
+
+               test_node = ou->nodes[i];
+               DBG((dbg, LEVEL_2, "\t    Testing %n\n", test_node));
+               confl_node = qnode_color_irn(qn, test_node, qn->color, test_node, co);
+
+               if (confl_node == CHANGE_SAVE) {
+                       DBG((dbg, LEVEL_2, "\t    Save\n"));
+                       qnode_pin_local(qn, test_node);
+               } else if (confl_node == CHANGE_IMPOSSIBLE) {
+                       DBG((dbg, LEVEL_2, "\t    Impossible\n"));
+                       bitset_clear(qn->nodes, i);
+               } else {
+                       DBG((dbg, LEVEL_2, "\t    Conflicting\n"));
+                       if (qnode_is_pinned_local(qn, confl_node)) {
+                               /* changing test_node would change back a node of current ou */
+                               qnode_add_conflict(qn, confl_node, test_node);
+                       }
+                       if (pset_find_ptr(co->pinned_global, confl_node)) {
+                               /* changing test_node would change back a node of a prior ou */
+                               bitset_clear(qn->nodes, i);
+                       }
+               }
+
+               if (confl_node != CHANGE_SAVE)
+                       return 0;
+       }
+       return 1;
+}
+
+/**
+ * Creates a new qnode
+ */
+static INLINE qnode_t *new_qnode(const unit_t *ou, int color) {
+       qnode_t *qn = malloc(sizeof(*qn));
+       qn->color = color;
+       qn->mis = bitset_malloc(ou->node_count-1);
+       qn->nodes = bitset_malloc(ou->node_count-1);
+       bitset_set_all(qn->nodes);
+       qn->conflicts = new_set(set_cmp_conflict_t, SLOTS_CONFLICTS);
+       qn->changed_nodes = new_set(set_cmp_node_stat_t, SLOTS_CHANGED_NODES);
+       return qn;
+}
+
+/**
+ * Frees space used by a queue node
+ */
+static INLINE void free_qnode(qnode_t *qn) {
+       del_set(qn->conflicts);
+       del_set(qn->changed_nodes);
+       bitset_free(qn->nodes);
+       bitset_free(qn->mis);
+       free(qn);
+}
+
+/**
+ * Determines a maximum independent set with respect to the interference and
+ * conflict edges of all nodes in a qnode.
+ */
+static INLINE void qnode_max_ind_set(qnode_t *qn, const unit_t *ou) {
+       int all_size, curr_size, i, o;
+       int *which;
+       const ir_node **curr, **all = alloca(bitset_popcnt(qn->nodes) * sizeof(*all));
+
+       /* all contains all nodes not removed in this qn */
+       assert(bitset_is_set(qn->nodes, 0) && "root is not element of this queue node");
+       all_size = 0;
+       bitset_foreach(qn->nodes, i)
+               all[all_size++] = ou->nodes[i];
+
+       /* which[i] says which element to take out of all[] and put into curr[i] */
+       which = alloca(all_size*sizeof(*which));
+       for (curr_size=0; curr_size<all_size; ++curr_size)
+               which[curr_size] = curr_size;
+
+       /* 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 */
+               /* build current set */
+               for (i=0; i<curr_size; ++i)
+                       curr[i] = all[which[all_size-curr_size+i]];
+
+               /* check current set */
+               for (i=0; i<curr_size; ++i)
+                       for (o=i+1; o<curr_size; ++o)
+                               if (qnode_are_conflicting(qn, curr[i], curr[o]))
+                                       goto conflict_found;
+
+               /* We had no conflict. This is the max indep. set */
+               bitset_clear_all(qn->mis);
+               qn->size = curr_size;
+               for (i=0; i<curr_size; ++i)
+                       for (o=0; o<ou->node_count; ++o)
+                               if (curr[i] == ou->nodes[o])
+                                       bitset_set(qn->mis, o);
+               return;
+
+conflict_found:
+               /* We had a conflict. Generate next set */
+               if (which[all_size-curr_size+1] == all_size-curr_size+1) {
+                       curr_size--;
+                       for (i=0; i<curr_size; ++i)
+                               which[all_size-curr_size+i] = i;
+               } else {
+                       int redo = 1;
+                       while (redo) {
+                               int pos = all_size;
+                               do {
+                                       pos--;
+                               } while (!(which[pos] = (which[pos]+1) % all_size));
+
+                               for (i=pos+1; i<all_size; ++i)
+                                       which[i] = MIN(which[i-1]+1, all_size-1);
+
+                               redo = 0;
+                               for (i=all_size-curr_size; i<all_size-1; ++i)
+                                       if (which[i]>=which[i+1]) {
+                                               redo = 1;
+                                               break;
+                                       }
+                       }
+               }
+       }
+}
+
+/**
+ * Inserts a qnode in the sorted queue of the outimization unit. Queue is
+ * ordered by field 'size' (the size of the mis) in decreasing order.
+ */
+static INLINE void qnode_insert(qnode_t *qn, unit_t *ou) {
+       struct list_head *lh;
+       /* root node is not in qnode */
+       if (!bitset_is_set(qn->nodes, 0)) {
+               free_qnode(qn);
+               return;
+       }
+
+       qnode_max_ind_set(qn, ou);
+       if (ou->mis_size < qn->size)
+               ou->mis_size = qn->size;
+
+       lh = &ou->queue;
+       while (lh->next != &ou->queue) {
+               qnode_t *curr = list_entry_queue(lh->next);
+               if (curr->size <= qn->size)
+                       break;
+               lh = lh->next;
+       }
+       list_add(&qn->queue, lh);
+}
+
+/**
+ * Tries to re-allocate colors of nodes in this opt unit, to achieve a lower
+ * number of copy instructions placed during SSA-destruction and lowering.
+ * Works only for opt units with exactly 1 root node, which is the
+ * case for approximately 80% of all phi classes and all register constrained
+ * nodes. (All other phi classes are reduced to this case.)
+ */
+static void co_heur_opt_unit(const copy_opt_t *co, unit_t *ou) {
+       int i;
+       qnode_t * curr;
+
+       /* init queue */
+       INIT_LIST_HEAD(&ou->queue);
+       for (i=MAX_COLORS-1; i>=0; --i)
+               if (is_possible_color(ou->nodes[0], i))
+                       qnode_insert(new_qnode(ou, i), ou);
+
+       /* search best */
+       while (!list_empty(&ou->queue)) {
+               /* get head of queue */
+               curr = list_entry_queue(ou->queue.next);
+               list_del(&curr->queue);
+               /* try */
+               if (qnode_try_color(curr, ou, co))
+                       break;
+               /* no success, so re-insert */
+               del_set(curr->changed_nodes);
+               curr->changed_nodes = new_set(set_cmp_node_stat_t, SLOTS_CHANGED_NODES);
+               qnode_insert(curr, ou);
+       }
+
+       /* apply the best found qnode */
+       if (curr->size >= 2) {
+               DBG((dbg, 1, "\tBest color: %d  Copies: %d/%d\n", curr->color, ou->interf+ou->node_count-1-curr->size));
+               /* globally pin root and eventually others */
+               pset_insert_ptr(co->pinned_global, ou->nodes[0]);
+               for (i=1; i<ou->node_count; ++i) {
+                       const 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]))
+                               pset_insert_ptr(co->pinned_global, irn);
+               }
+
+               /* 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) {
+                               DBG((dbg, 1, "\t    color(%n) := %d\n", ns->irn, ns->new_color));
+                               set_irn_color(ns->irn, ns->new_color);
+                       }
+               }
+       }
+
+       /* free best qnode (curr) and queue */
+       free_qnode(curr);
+       list_for_each_entry(qnode_t, curr, &ou->queue, queue)
+               free_qnode(curr);
+}
+
+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);
+
+       co->pinned_global = pset_new_ptr(SLOTS_PINNED_GLOBAL);
+
+       list_for_each_entry(unit_t, curr, &co->units, units)
+               co_heur_opt_unit(co, curr);
+
+       del_pset(co->pinned_global);
+}
diff --git a/ir/be/becopyilp.c b/ir/be/becopyilp.c
new file mode 100644 (file)
index 0000000..367bf6a
--- /dev/null
@@ -0,0 +1,673 @@
+/**
+ * Minimizing copies with an exact algorithm using mixed integer programming (MIP).
+ * Problem statement as a 'quadratic 0-1 program with linear constraints' with
+ * n binary variables. Constraints are knapsack (enforce color for each node) and
+ * cliques of ifg (interference constraints).
+ * Transformation into a 'mixed integer program' with n binary variables and
+ * additional 2n real variables. Constraints are the above the transformed
+ * objective function and 'complementary conditions' for two var classes.
+ * @author Daniel Grund
+ *
+ * NOTE: Unfortunately no good solver is available locally (or even for linking)
+ *       We use CPLEX 9.0 which runs on a machine residing at the Rechenzentrum.
+ * @date 12.04.2005
+ */
+
+#include "becopyopt.h"
+
+#define DUMP_MPS                       /**< dumps the problem in "CPLEX"-MPS format. NOT fixed-column-MPS. */
+#define USE_SOS                                /**< uses Special Ordered Sets when using MPS */
+#define DO_SOLVE                       /**< solve the MPS output with CPLEX */
+#define DUMP_MATRICES          /**< dumps all matrices completely. only recommended for small problems */
+#define DUMP_LP                                /**< dumps the problem in LP format. 'human-readable' equations etc... */
+#define DELETE_FILES           /**< deletes all dumped files after use */
+#define EXPECT_FILENAME "runme" /** name of the expect-script */
+
+/* CPLEX-account related stuff */
+#define SSH_USER_HOST_PATH "kb61@sp-smp.rz.uni-karlsruhe.de"
+#define SSH_PASSWD "!cplex90"
+
+#define DEBUG_LVL SET_LEVEL_1
+static firm_dbg_module_t *dbg = NULL;
+
+#define SLOTS_NUM2POS 256
+#define SLOTS_LIVING 32
+
+/**
+ * A type storing names of the x variables in the form x[NUMBER]_[COLOR]
+ */
+typedef struct _x_name_t {
+       int n, c;
+} x_name_t;
+
+/**
+ * For each node taking part in the opt-problem its position in the
+ * x-variable-vector is stored in a set. This set maps the node-nr (given by
+ * benumb) to the position in the vector.
+ */
+typedef struct _num2pos_t {
+       int num, pos;
+} num2pos_t;
+
+/**
+ * A type storing the unmodified '0-1 quadratic program' of the form
+ * min f = xQx
+ * udN:  Ax  = e
+ *       Bx <= e
+ *        x \in {0, 1}
+ *
+ * This problem is called the original problem
+ */
+typedef struct _problem_instance_t {
+       ir_graph* irg;
+       const char *name;
+       int x_dim, A_dim, B_dim;        /**< number of: x variables, rows in A, rows in B */
+       x_name_t *x;                            /**< stores the names of the x variables. all possible colors for a node are ordered and occupy consecutive entries. lives in obstack ob. */
+       set *num2pos;                           /**< maps node numbers to positions in x. */
+       sp_matrix_t *Q, *A, *B;         /**< the (sparse) matrices of this problem */
+
+       /* needed only for linearizations */
+       int bigM, maxQij, minQij;
+
+       /* overhead needed to build this */
+       struct obstack ob;
+       int curr_color;
+       int curr_row;
+} problem_instance_t;
+
+/* Nodes have consecutive numbers so this hash shoud be fine */
+#define HASH_NUM(num) num
+
+static int set_cmp_num2pos(const void *x, const void *y, size_t size) {
+       return ((num2pos_t *)x)->num != ((num2pos_t *)y)->num;
+}
+
+/**
+ * Sets the first position of node with number num to pos.
+ * See x_name_t *x in _problem_instance_t.
+ */
+static INLINE void pi_set_first_pos(problem_instance_t *pi, int num, int pos) {
+       num2pos_t find;
+       find.num = num;
+       find.pos = pos;
+       set_insert(pi->num2pos, &find, sizeof(find), HASH_NUM(num));
+}
+
+/**
+ * Get position by number. (First possible color)
+ * returns -1 if not found.
+ */
+static INLINE int pi_get_first_pos(problem_instance_t *pi, int num) {
+       num2pos_t find, *found;
+       find.num = num;
+       found = set_find(pi->num2pos, &find, sizeof(find), HASH_NUM(num));
+       if (found) {
+               assert(pi->x[found->pos].n == num && (found->pos == 0 || pi->x[found->pos-1].n != num) && "pi->num2pos is broken!");
+               return found->pos;
+       } else
+               return -1;
+}
+
+/**
+ * Get position by number and color.
+ * returns -1 if not found.
+ */
+static INLINE int pi_get_pos(problem_instance_t *pi, int num, int col) {
+       num2pos_t find, *found;
+       find.num = num;
+       int pos;
+       found = set_find(pi->num2pos, &find, sizeof(find), HASH_NUM(num));
+       if (!found)
+               return -1;
+       pos = found->pos;
+       while (pos < pi->x_dim && pi->x[pos].n == num && pi->x[pos].c < col)
+               pos++;
+
+       if (pi->x[pos].n == num && pi->x[pos].c == col)
+               return pos;
+       else
+               return -1;
+}
+
+static INLINE FILE *ffopen(const char *base, const char *ext, const char *mode) {
+       FILE *out;
+       char buf[1024];
+
+       snprintf(buf, sizeof(buf), "%s.%s", base, ext);
+       if (! (out = fopen(buf, mode))) {
+               fprintf(stderr, "Cannot open file %s in mode %s\n", buf, mode);
+               assert(0);
+       }
+       return out;
+}
+
+#ifdef DUMP_MATRICES
+/**
+ * Dump the raw matrices of the problem to a file for debugging.
+ */
+static void pi_dump_matrices(problem_instance_t *pi) {
+       int i;
+       FILE *out = ffopen(pi->name, "matrix", "wt");
+
+       DBG((dbg, LEVEL_1, "Dumping raw...\n"));
+       fprintf(out, "\n\nx-names =\n");
+       for (i=0; i<pi->x_dim; ++i)
+               fprintf(out, "%5d %2d\n", pi->x[i].n, pi->x[i].c);
+
+       fprintf(out, "\n\n-Q =\n");
+       matrix_dump(pi->Q, out, -1);
+
+       fprintf(out, "\n\nA =\n");
+       matrix_dump(pi->A, out, 1);
+
+       fprintf(out, "\n\nB =\n");
+       matrix_dump(pi->B, out, 1);
+
+       fclose(out);
+}
+#endif
+
+#ifdef DUMP_LP
+/**
+ * Dumps the problem instance as a MILP. The original problem is transformed into:
+ * min f = es - Mex
+ * udN:  Qx -y -s +Me = 0
+ *       Ax  = e
+ *       Bx <= e
+ *        y <= 2M(e-x)
+ *        x \in N   y, s >= 0
+ *
+ * with M >= max sum Q'ij * x_j
+ *            i   j
+ */
+static void pi_dump_lp(problem_instance_t *pi) {
+       int i, max_abs_Qij;
+       matrix_elem_t *e;
+       FILE *out = ffopen(pi->name, "lpo", "wt");
+
+       DBG((dbg, LEVEL_1, "Dumping lp_org...\n"));
+       /* calc the big M for Q */
+       max_abs_Qij = pi->maxQij;
+       if (-pi->minQij > max_abs_Qij)
+               max_abs_Qij = -pi->minQij;
+       pi->bigM = pi->A_dim * max_abs_Qij;
+       DBG((dbg, LEVEL_2, "BigM = %d\n", pi->bigM));
+
+       /* generate objective function */
+       fprintf(out, "min: ");
+       for (i=0; i<pi->x_dim; ++i)
+               fprintf(out, "+s%d_%d -%dx%d_%d ", pi->x[i].n, pi->x[i].c, pi->bigM, pi->x[i].n, pi->x[i].c);
+       fprintf(out, ";\n\n");
+
+       /* constraints for former objective function */
+       for (i=0; i<pi->x_dim; ++i)     {
+               matrix_foreach_in_row(pi->Q, i, e) {
+                       int Qio = e->val;
+                               if (Qio == 1)
+                                       fprintf(out, "+x%d_%d ", pi->x[e->col].n, pi->x[e->col].c);
+                               else if(Qio == -1)
+                                       fprintf(out, "-x%d_%d ", pi->x[e->col].n, pi->x[e->col].c);
+                               else
+                                       fprintf(out, "%+dx%d_%d ", Qio, pi->x[e->col].n, pi->x[e->col].c);
+               }
+               fprintf(out, "-y%d_%d -s%d_%d +%d= 0;\n", pi->x[i].n, pi->x[i].c, pi->x[i].n, pi->x[i].c, pi->bigM);
+       }
+       fprintf(out, "\n\n");
+
+       /* constraints for (special) complementary condition */
+       for (i=0; i<pi->x_dim; ++i)
+               fprintf(out, "y%d_%d <= %d - %dx%d_%d;\n", pi->x[i].n, pi->x[i].c, 2*pi->bigM, 2*pi->bigM, pi->x[i].n, pi->x[i].c);
+       fprintf(out, "\n\n");
+
+       /* knapsack constraints */
+       for (i=0; i<pi->A_dim; ++i)     {
+               matrix_foreach_in_row(pi->Q, i, e)
+                       fprintf(out, "+x%d_%d ", pi->x[e->col].n, pi->x[e->col].c);
+               fprintf(out, " = 1;\n");
+       }
+       fprintf(out, "\n\n");
+
+       /* interference graph constraints */
+       for (i=0; i<pi->B_dim; ++i)     {
+               matrix_foreach_in_row(pi->Q, i, e)
+                       fprintf(out, "+x%d_%d ", pi->x[e->col].n, pi->x[e->col].c);
+               fprintf(out, " <= 1;\n");
+       }
+       fprintf(out, "\n\n");
+
+       /* integer constraints */
+       fprintf(out, "int x%d_%d", pi->x[0].n, pi->x[0].c);
+       for (i=1; i<pi->x_dim; ++i)
+               fprintf(out, ", x%d_%d", pi->x[i].n, pi->x[i].c);
+       fprintf(out, ";\n");
+
+       fclose(out);
+}
+#endif
+
+#ifdef DUMP_MPS
+/**
+ * Dumps an mps file representing the problem. This is NOT the old-style,
+ * fixed-column format. Some white spaces are important, in general spaces
+ * are separators, MARKER-lines are used in COLUMN section to define binaries.
+ */
+//BETTER use last 2 fields in COLUMNS section
+static void pi_dump_mps(problem_instance_t *pi) {
+       int i, max_abs_Qij;
+       matrix_elem_t *e;
+       FILE *out = ffopen(pi->name, "mps", "wt");
+
+       DBG((dbg, LEVEL_1, "Dumping mps...\n"));
+       max_abs_Qij = pi->maxQij;
+       if (-pi->minQij > max_abs_Qij)
+               max_abs_Qij = -pi->minQij;
+       pi->bigM = pi->A_dim * max_abs_Qij;
+       DBG((dbg, LEVEL_2, "BigM = %d\n", pi->bigM));
+
+       fprintf(out, "NAME %s\n", pi->name);
+
+       fprintf(out, "ROWS\n");
+       fprintf(out, " N obj\n");
+       for (i=0; i<pi->x_dim; ++i)
+               fprintf(out, " E cQ%d\n", i);
+       for (i=0; i<pi->A_dim; ++i)
+               fprintf(out, " E cA%d\n", i);
+       for (i=0; i<pi->B_dim; ++i)
+               fprintf(out, " L cB%d\n", i);
+       for (i=0; i<pi->x_dim; ++i)
+               fprintf(out, " L cy%d\n", i);
+
+       fprintf(out, "COLUMNS\n");
+       /* the x vars come first */
+       /* mark them as binaries */
+       fprintf(out, "    MARKI0\t'MARKER'\t'INTORG'\n");
+#ifdef USE_SOS
+       int sos_cnt = 0;
+       fprintf(out, " S1 SOS_%d\t'MARKER'\t'SOSORG'\n", sos_cnt++);
+#endif
+       for (i=0; i<pi->x_dim; ++i) {
+#ifdef USE_SOS
+               if (i>0 && pi->x[i].n != pi->x[i-1].n) {
+                       fprintf(out, "    SOS_%d\t'MARKER'\t'SOSEND'\n", sos_cnt++);
+                       fprintf(out, " S1 SOS_%d\t'MARKER'\t'SOSORG'\n", sos_cnt++);
+               }
+#endif
+               /* participation in objective */
+               fprintf(out, "    x%d_%d\tobj\t%d\n", pi->x[i].n, pi->x[i].c, -pi->bigM);
+               /* in Q */
+               matrix_foreach_in_col(pi->Q, i, e)
+                       fprintf(out, "    x%d_%d\tcQ%d\t%d\n", pi->x[i].n, pi->x[i].c, e->row, e->val);
+               /* in A */
+               matrix_foreach_in_col(pi->A, i, e)
+                       fprintf(out, "    x%d_%d\tcA%d\t%d\n", pi->x[i].n, pi->x[i].c, e->row, e->val);
+               /* in B */
+               matrix_foreach_in_col(pi->B, i, e)
+                       fprintf(out, "    x%d_%d\tcB%d\t%d\n", pi->x[i].n, pi->x[i].c, e->row, e->val);
+               /* in y */
+               fprintf(out, "    x%d_%d\tcy%d\t%d\n", pi->x[i].n, pi->x[i].c, i, 2*pi->bigM);
+       }
+
+#ifdef USE_SOS
+       fprintf(out, "    SOS_%d\t'MARKER'\t'SOSEND'\n", sos_cnt++);
+#endif
+       fprintf(out, "    MARKI1\t'MARKER'\t'INTEND'\n"); /* end of marking */
+
+       /* next the s vars */
+       for (i=0; i<pi->x_dim; ++i) {
+               /* participation in objective */
+               fprintf(out, "    s%d_%d\tobj\t%d\n", pi->x[i].n, pi->x[i].c, 1);
+               /* in Q */
+               fprintf(out, "    s%d_%d\tcQ%d\t%d\n", pi->x[i].n, pi->x[i].c, i, -1);
+       }
+
+       /* next the y vars */
+       for (i=0; i<pi->x_dim; ++i) {
+               /* in Q */
+               fprintf(out, "    y%d_%d\tcQ%d\t%d\n", pi->x[i].n, pi->x[i].c, i, -1);
+               /* in y */
+               fprintf(out, "    y%d_%d\tcy%d\t%d\n", pi->x[i].n, pi->x[i].c, i, 1);
+       }
+
+       fprintf(out, "RHS\n");
+       for (i=0; i<pi->x_dim; ++i)
+               fprintf(out, "    rhs\tcQ%d\t%d\n", i, -pi->bigM);
+       for (i=0; i<pi->A_dim; ++i)
+               fprintf(out, "    rhs\tcA%d\t%d\n", i, 1);
+       for (i=0; i<pi->B_dim; ++i)
+               fprintf(out, "    rhs\tcB%d\t%d\n", i, 1);
+       for (i=0; i<pi->x_dim; ++i)
+               fprintf(out, "    rhs\tcy%d\t%d\n", i, 2*pi->bigM);
+
+       fprintf(out, "ENDATA\n");
+       fclose(out);
+
+       out = ffopen(pi->name, "mst", "wt");
+       fprintf(out, "NAME\n");
+       for (i=0; i<pi->x_dim; ++i) {
+               int val, n, c;
+               n = pi->x[i].n;
+               c = pi->x[i].c;
+               if (get_irn_color(get_irn_for_graph_nr(pi->irg, n)) == c)
+                       val = 1;
+               else
+                       val = 0;
+               fprintf(out, "    x%d_%d\t%d\n", n, c, val);
+       }
+       fprintf(out, "ENDATA\n");
+       fclose(out);
+}
+#endif
+
+#ifdef DO_SOLVE
+/**
+ * Invoke an external solver
+ */
+static void pi_solve_ilp(problem_instance_t *pi) {
+       FILE *out;
+
+       /* write command file for CPLEX */
+       out = ffopen(pi->name, "cmd", "wt");
+       fprintf(out, "read %s.mps\n", pi->name);
+       fprintf(out, "read %s.mst\n", pi->name);
+       fprintf(out, "set mip strategy mipstart 1\n");
+       fprintf(out, "optimize\n");
+       fprintf(out, "set logfile %s.sol\n", pi->name);
+       fprintf(out, "display solution variables 1-%d\n", pi->x_dim);
+       fprintf(out, "set logfile cplex.log\n");
+       fprintf(out, "quit\n");
+       fclose(out);
+
+       /* write expect-file for copying problem to RZ */
+       out = ffopen(EXPECT_FILENAME, "exp", "wt");
+       fprintf(out, "#! /usr/bin/expect\n");
+       fprintf(out, "spawn scp %s.mps %s.mst %s.cmd %s:\n", pi->name, pi->name, pi->name, SSH_USER_HOST_PATH);
+       fprintf(out, "expect \":\"\n");
+       fprintf(out, "send \"%s\\n\"\n", SSH_PASSWD);
+       fprintf(out, "interact\n");
+
+       fprintf(out, "spawn ssh %s \"./cplex90 < %s.cmd\"\n", SSH_USER_HOST_PATH, pi->name);
+       fprintf(out, "expect \":\"\n");
+       fprintf(out, "send \"%s\\n\"\n", SSH_PASSWD);
+       fprintf(out, "interact\n");
+
+       fprintf(out, "spawn scp %s:%s.sol .\n", SSH_USER_HOST_PATH, pi->name);
+       fprintf(out, "expect \":\"\n");
+       fprintf(out, "send \"%s\\n\"\n", SSH_PASSWD);
+       fprintf(out, "interact\n");
+       fclose(out);
+
+       /* call the expect script */
+       chmod(EXPECT_FILENAME ".exp", 0700);
+       system(EXPECT_FILENAME ".exp");
+}
+
+/**
+ * Sets the colors of irns according to the values of variables found in the
+ * output file of the solver.
+ */
+static void pi_apply_solution(problem_instance_t *pi) {
+       FILE *in = ffopen(pi->name, "sol", "rt");
+
+       if (!in)
+               return;
+       DBG((dbg, LEVEL_1, "Applying solution...\n"));
+       while (!feof(in)) {
+               char buf[1024];
+               int num = -1, col = -1, val = -1;
+               if (fscanf(in, "x%d_%d %d.%s\n", &num, &col, &val, buf) != 3) {
+                       while(fscanf(in, "%1020s\n", buf) != 1);
+                       continue;
+               }
+               if (val == 1) {
+                       DBG((dbg, LEVEL_1, "x%d_%d = %d\n", num, col, val));
+                       set_irn_color(get_irn_for_graph_nr(pi->irg, num), col);
+               }
+       }
+       fclose(in);
+}
+#endif /* DO_SOLVE */
+
+#ifdef DELETE_FILES
+static void pi_delete_files(problem_instance_t *pi) {
+       char buf[1024];
+       int end = snprintf(buf, sizeof(buf), "%s", pi->name);
+#ifdef DUMP_MATRICES
+       snprintf(buf+end, sizeof(buf)-end, ".matrix");
+       remove(buf);
+#endif
+#ifdef DUMP_MPS
+       snprintf(buf+end, sizeof(buf)-end, ".mps");
+       remove(buf);
+       snprintf(buf+end, sizeof(buf)-end, ".mst");
+       remove(buf);
+       snprintf(buf+end, sizeof(buf)-end, ".cmd");
+       remove(buf);
+       remove(EXPECT_FILENAME ".exp");
+#endif
+#ifdef DUMP_LP
+       snprintf(buf+end, sizeof(buf)-end, ".lp");
+       remove(buf);
+#endif
+}
+#endif
+
+/**
+ * Collects all irns in currently processed register class
+ */
+static void pi_collect_x_names(ir_node *block, void *env) {
+       problem_instance_t *pi = env;
+       struct list_head *head = &get_ra_block_info(block)->border_head;
+       border_t *curr;
+
+       list_for_each_entry_reverse(border_t, curr, head, list)
+               if (curr->is_def && curr->is_real) {
+                       x_name_t xx;
+                       pi->A_dim++;                    /* one knapsack constraint for each node */
+
+                       xx.n = get_irn_graph_nr(curr->irn);
+                       pi_set_first_pos(pi, xx.n, pi->x_dim);
+                       //TODO iterate over all possible colors !!MUST BE IN ORDER!!
+                       for (xx.c=0; xx.c<MAX_COLORS; ++xx.c) {
+                               if (!is_possible_color(irn, xx.c))
+                                       continue;
+                               DBG((dbg, LEVEL_2, "Adding %n %d\n", curr->irn, xx.c));
+                               obstack_grow(&pi->ob, &xx, sizeof(xx));
+                               pi->x_dim++;            /* one x variable for each node and color */
+                       }
+               }
+}
+
+/**
+ * Checks if all nodes in living are live_out in block block.
+ */
+static INLINE int all_live_out(ir_node *block, pset *living) {
+       ir_node *n;
+       for (n = pset_first(living); n; n = pset_next(living))
+               if (!is_live_out(block, n)) {
+                       pset_break(living);
+                       return 0;
+               }
+       return 1;
+}
+
+/**
+ * Finds cliques in the interference graph, considering only nodes
+ * for which the color pi->curr_color is possible. Finds only 'maximal-cliques',
+ * viz cliques which are not conatained in another one.
+ * This is used for the matrix B.
+ */
+static void pi_clique_finder(ir_node *block, void *env) {
+       problem_instance_t *pi = env;
+       enum phase_t {growing, shrinking} phase = growing;
+       struct list_head *head = &get_ra_block_info(block)->border_head;
+       border_t *b;
+       pset *living = pset_new_ptr(SLOTS_LIVING);
+
+       list_for_each_entry_reverse(border_t, b, head, list) {
+               const ir_node *irn = b->irn;
+               if (!is_possible_color(n, pi->curr_col))
+                       continue;
+
+               if (b->is_def) {
+                       DBG((dbg, LEVEL_2, "Def %n\n", irn));
+                       pset_insert_ptr(living, irn);
+                       phase = growing;
+               } else { /* is_use */
+                       DBG((dbg, LEVEL_2, "Use %n\n", irn));
+
+                       /* before shrinking the set, store the current 'maximum' clique;
+                        * do NOT if clique is a single node
+                        * do NOT if all values are live_out */
+                       if (phase == growing && pset_count(living) >= 2 && !all_live_out(block, living)) {
+                               ir_node *n;
+                               for (n = pset_first(living); n; n = pset_next(living)) {
+                                       int pos = pi_get_pos(pi, get_irn_graph_nr(n), pi->curr_color);
+                                       matrix_set(pi->B, pi->curr_row, pos, 1);
+                                       DBG((dbg, LEVEL_2, "B[%d, %d] := %d\n", pi->curr_row, pos, 1));
+                               }
+                               pi->curr_row++;
+                       }
+                       pset_remove_ptr(living, irn);
+                       phase = shrinking;
+               }
+       }
+
+       del_pset(living);
+}
+
+/**
+ * Generate the initial problem matrices and vectors.
+ */
+static problem_instance_t *new_pi(const copy_opt_t *co) {
+       DBG((dbg, LEVEL_1, "Generating new instance...\n"));
+       problem_instance_t *pi = calloc(1, sizeof(*pi));
+       pi->irg = co->irg;
+       pi->name =      get_entity_name(get_irg_entity(co->irg));
+       pi->num2pos = new_set(set_cmp_num2pos, SLOTS_NUM2POS);
+       pi->bigM = 1;
+
+       /* Vector x
+        * one entry per node and possible color */
+       obstack_init(&pi->ob);
+       dom_tree_walk_irg(co->irg, pi_collect_x_names, NULL, &pi->ob);
+       pi->x = obstack_finish(&pi->ob);
+
+       /* Matrix Q
+        * weights for the 'same-color-optimization' target */
+       {
+               unit_t *curr;
+               pi->Q = new_matrix(pi->x_dim, pi->x_dim);
+
+               list_for_each_entry(unit_t, curr, &co->units, units) {
+                       const ir_node *root, *arg;
+                       int rootnr, argnr;
+                       unsigned rootpos, argpos;
+                       int i;
+
+                       root = curr->nodes[0];
+                       rootnr = get_irn_graph_nr(root);
+                       rootpos = pi_get_first_pos(pi, rootnr);
+                       for (i = 1; i < curr->node_count; ++i) {
+                               int weight = -get_weight(root, arg);
+                               arg = curr->nodes[i];
+                               argnr = get_irn_graph_nr(arg);
+                               argpos = pi_get_first_pos(pi, argnr);
+
+                               DBG((dbg, LEVEL_2, "Q[%n, %n] := %d\n", root, arg, weight));
+                               /* for all colors root and arg have in common, set the weight for
+                                * this pair in the objective function matrix Q */
+                               while (rootpos < pi->x_dim && argpos < pi->x_dim &&
+                                               pi->x[rootpos].n == rootnr && pi->x[argpos].n == argnr) {
+                                       if (pi->x[rootpos].c < pi->x[argpos].c)
+                                               ++rootpos;
+                                       else if (pi->x[rootpos].c > pi->x[argpos].c)
+                                               ++argpos;
+                                       else {
+                                               matrix_set(pi->Q, rootpos++, argpos++, weight);
+
+                                               if (weight < pi->minQij) {
+                                                       DBG((dbg, LEVEL_2, "minQij = %d\n", weight));
+                                                       pi->minQij = weight;
+                                               }
+                                               if (weight > pi->maxQij) {
+                                                       DBG((dbg, LEVEL_2, "maxQij = %d\n", weight));
+                                                       pi->maxQij = weight;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /* Matrix A
+        * knapsack constraint for each node */
+       {
+               int row = 0, col = 0;
+               pi->A = new_matrix(pi->A_dim, pi->x_dim);
+               while (col < pi->x_dim) {
+                       int curr_n = pi->x[col].n;
+                       while (col < pi->x_dim && pi->x[col].n == curr_n) {
+                               DBG((dbg, LEVEL_2, "A[%d, %d] := %d\n", row, col, 1));
+                               matrix_set(pi->A, row, col++, 1);
+                       }
+                       ++row;
+               }
+               assert(row == pi->A_dim);
+       }
+
+       /* Matrix B
+        * interference constraints using exactly those cliques not contained in others. */
+       {
+               int color, expected_clipques = pi->A_dim/3 * MAX_COLORS;
+               pi->B = new_matrix(expected_clipques, pi->x_dim);
+               for (color = 0; color < MAX_COLORS; ++color) {
+                       pi->curr_color = color;
+                       dom_tree_walk_irg(pi->irg, pi_clique_finder, NULL, pi);
+               }
+               pi->B_dim = matrix_get_rowcount(pi->B);
+       }
+
+       return pi;
+}
+
+/**
+ * clean the problem instance
+ */
+static void free_pi(problem_instance_t *pi) {
+       del_matrix(pi->Q);
+       del_matrix(pi->A);
+       del_matrix(pi->B);
+       del_set(pi->num2pos);
+       obstack_free(&pi->ob, NULL);
+       free(pi);
+}
+
+void co_ilp_opt(copy_opt_t *co) {
+       dbg = firm_dbg_register("ir.be.copyoptilp");
+       firm_dbg_set_mask(dbg, DEBUG_LVL);
+
+       problem_instance_t *pi = new_pi(co);
+
+#ifdef DUMP_MATRICES
+       pi_dump_matrices(pi);
+#endif
+
+#ifdef DUMP_LP
+       pi_dump_lp(pi);
+#endif
+
+#ifdef DUMP_MPS
+       pi_dump_mps(pi);
+#endif
+
+#ifdef DO_SOLVE
+       pi_solve_ilp(pi);
+       pi_apply_solution(pi);
+#endif
+
+#ifdef DELETE_FILES
+       pi_delete_files(pi);
+#endif
+
+       free_pi(pi);
+}
diff --git a/ir/be/becopyopt.c b/ir/be/becopyopt.c
new file mode 100644 (file)
index 0000000..bbc5702
--- /dev/null
@@ -0,0 +1,112 @@
+/**
+ * @author Daniel Grund
+ * @date 12.04.2005
+ */
+
+#include "becopyopt.h"
+
+#define DEBUG_LVL SET_LEVEL_1
+static firm_dbg_module_t *dbg = NULL;
+
+//TODO
+#define is_optimizable(irn) (is_Phi(irn) || 0)
+
+/**
+ * Builds an optimization unit for a given optimizable irn (root).
+ * This opt-unit is inserted in the main structure co.
+ * If an arg of root itself is optimizable process this arg before with a
+ * recursive call. For handling this situation and loops co->root is used
+ * to remember all roots.
+ */
+static void co_append_unit(copy_opt_t *co, const ir_node *root) {
+       int i, arity;
+       unit_t *unit;
+       DBG((dbg, LEVEL_1, "Root: %n\n", root));
+       /* check if we encountered this root earlier */
+       if (pset_find_ptr(co->roots, root))
+               return;
+       pset_insert_ptr(co->roots, root);
+
+       /* init unit */
+       arity = get_irn_arity(root);
+       unit = malloc(sizeof(*unit));
+       unit->interf = 0;
+       unit->node_count = 1;
+       unit->nodes = malloc((arity+1) * sizeof(*unit->nodes));
+       unit->nodes[0] = root;
+       INIT_LIST_HEAD(&unit->queue);
+
+       /* check all args */
+       for (i=0; i<arity; ++i) {
+               ir_node *arg = get_irn_n(root, i);
+               if (!values_interfere(root, arg)) {
+                       if (arg != root) {
+                               DBG((dbg, LEVEL_1, "Member: %n\n", arg));
+                               if (is_optimizable(arg))
+                                       co_append_unit(co, arg);
+                               unit->nodes[unit->node_count++] = arg;
+                       }
+               } else
+                       unit->interf++;
+       }
+
+       if (unit->node_count > 1) {
+               unit->nodes = realloc(unit->nodes, unit->node_count * sizeof(*unit->nodes));
+               list_add_tail(&unit->units, &co->units);
+       } else {
+               free(unit->nodes);
+               free(unit);
+       }
+}
+
+static void co_collect_in_block(ir_node *block, void *env) {
+       copy_opt_t *co = env;
+       struct list_head *head = &get_ra_block_info(block)->border_head;
+       border_t *curr;
+
+       list_for_each_entry_reverse(border_t, curr, head, list)
+               if (curr->is_def && curr->is_real && is_optimizable(curr->irn))
+                       co_append_unit(co, curr->irn);
+}
+
+static void co_collect_units(copy_opt_t *co) {
+       co->roots = pset_new_ptr(64);
+       dom_tree_walk_irg(co->irg, co_collect_in_block, NULL, co);
+       del_pset(co->roots);
+}
+
+copy_opt_t *new_copy_opt(ir_graph *irg) {
+       dbg = firm_dbg_register("ir.be.copyopt");
+       firm_dbg_set_mask(dbg, DEBUG_LVL);
+
+       copy_opt_t *co = calloc(1, sizeof(*co));
+       co->irg = irg;
+       INIT_LIST_HEAD(&co->units);
+       co_collect_units(co);
+       return co;
+}
+
+void free_copy_opt(copy_opt_t *co) {
+       unit_t *curr;
+       list_for_each_entry(unit_t, curr, &co->units, units) {
+               free(curr->nodes);
+               free(curr);
+       }
+}
+
+int co_get_lower_bound(copy_opt_t *co) {
+       //TODO Think if copy counting is this easy!
+       int res = 0;
+       unit_t *curr;
+       list_for_each_entry(unit_t, curr, &co->units, units)
+               res += curr->interf + curr->node_count - curr->mis_size;
+       return res;
+}
+
+int co_get_interferer_count(copy_opt_t *co) {
+       int res = 0;
+       unit_t *curr;
+       list_for_each_entry(unit_t, curr, &co->units, units)
+               res += curr->interf;
+       return res;
+}
diff --git a/ir/be/becopyopt.h b/ir/be/becopyopt.h
new file mode 100644 (file)
index 0000000..4b9401b
--- /dev/null
@@ -0,0 +1,107 @@
+/**
+ * Header for copy optimization problem. Analysis and set up of the problem.
+ * @author Daniel Grund
+ * @date 12.04.2005
+ */
+
+#ifndef _BECOPYOPT_H
+#define _BECOPYOPT_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <alloca.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "debug.h"
+#include "obst.h"
+#include "list.h"
+#include "set.h"
+#include "pset.h"
+#include "bitset.h"
+#include "sp_matrix.h"
+
+#include "irgraph.h"
+#include "irgwalk.h"
+#include "irnode.h"
+#include "irdom.h"
+#include "irouts.h"
+
+#include "benumb_t.h"
+#include "belive_t.h"
+#include "bera_t.h"
+#include "bechordal_t.h"
+
+/**
+ * TODO THIS EXTERNAL THINGS
+ * define get_weight to sth representing the _gain_ if node n and m
+ * have the same color. Must return values MIN_WEIGHT <= . <= MAX_WEIGHT.
+ */
+#define get_weight(n,m) 1
+#define is_possible_color(irn, col) 1
+#define MAX_COLORS 32
+
+/**
+ * A single unit of optimization. Lots of these form a copy-opt problem
+ */
+typedef struct _unit_t {
+       struct list_head units;         /**< chain for all units */
+       int interf;                                     /**< number of nodes dropped due to interference */
+       int node_count;                         /**< size of the nodes array */
+       const ir_node **nodes;          /**< [0] is the root-node, others are non interfering args of it. */
+
+       /* for heuristic */
+       int mis_size;                           /**< size of a mis considering only ifg (not coloring conflicts) */
+       struct list_head queue;         /**< list of (mis/color) sorted by size of mis */
+} unit_t;
+
+/**
+ * Data representing the problem of copy minimization.
+ */
+typedef struct _copy_opt_t {
+       ir_graph *irg;                          /**< the irg which is processed */
+       struct list_head units;         /**< all units to optimize in right oreder */
+       pset *roots;                            /**< used only temporary for detecting multiple appends */
+
+       /* for heuristic */
+       pset *pinned_global;            /**< optimized nodes should not be altered any more */
+} copy_opt_t;
+
+
+/**
+ * Generate the problem. Collect all infos and optimizable nodes.
+ */
+copy_opt_t *new_copy_opt(ir_graph *irg);
+
+/**
+ * Free the space...
+ */
+void free_copy_opt(copy_opt_t *co);
+
+/**
+ * Returns a lower bound for the number of copies needed based on interfering
+ * arguments and the size of a max indep. set (only ifg-edges) of the other args.
+ */
+int co_get_lower_bound(copy_opt_t *co);
+
+/**
+ * Returns the number of arguments interfering with their root node. This also
+ * is a (worse) lower bound for the number of copies needed.
+ */
+int co_get_interferer_count(copy_opt_t *co);
+
+/**
+ * Solves the problem using a heuristic approach
+ */
+void co_heur_opt(copy_opt_t *co);
+
+/**
+ * Solves the problem using mixed integer programming
+ */
+void co_ilp_opt(copy_opt_t *co);
+
+#endif
diff --git a/ir/be/becopyoptmain.c b/ir/be/becopyoptmain.c
new file mode 100644 (file)
index 0000000..463dd95
--- /dev/null
@@ -0,0 +1,105 @@
+/**
+ * Main file for the optimization reducing the copies needed for:
+ * - phi coalescing
+ * - register-constrained nodes
+ *
+ * Contains a simple checker for this optimization.
+ * By request some statistics are collected too.
+ *
+ * @author Daniel Grund
+ * @date 11.04.2005
+ */
+
+#include "debug.h"
+#include "list.h"
+#include "obst.h"
+#include "irgraph.h"
+#include "irnode.h"
+#include "irgwalk.h"
+
+#include "bera_t.h"
+#include "becopyoptmain.h"
+#include "becopyopt.h"
+#include "becopystat.h"
+
+#define DO_HEUR
+#define DO_ILP
+#undef DO_STAT
+
+#define DEBUG_LVL SET_LEVEL_1
+static firm_dbg_module_t *dbg = NULL;
+
+/**
+ * Needed for result checking
+ */
+static void allocatable_collector(ir_node *node, void *env) {
+       struct obstack *obst = env;
+       if (!is_Block(node) && is_allocatable_irn(node))
+               obstack_ptr_grow(obst, node);
+}
+
+/**
+ * This O(n^2) checker checks, if two ifg-connected nodes have the same color.
+ */
+static void check_results(ir_graph *irg) {
+       struct obstack ob;
+       ir_node **nodes, *n1, *n2;
+       int i, o;
+
+       obstack_init(&ob);
+       irg_walk_graph(irg, allocatable_collector, NULL, &ob);
+       obstack_ptr_grow(&ob, NULL);
+       nodes = (ir_node **) obstack_finish(&ob);
+       for (i = 0, n1 = nodes[i]; n1; n1 = nodes[++i]) {
+               assert(! (is_allocatable_irn(n1) && get_irn_color(n1) == NO_COLOR));
+               for (o = i+1, n2 = nodes[o]; n2; n2 = nodes[++o])
+                       if (phi_ops_interfere(n1, n2) && get_irn_color(n1) == get_irn_color(n2)) {
+                               DBG((dbg, 0, "Error: %n in %n  and  %n in %n\n", n1, get_nodes_block(n1), n2, get_nodes_block(n2)));
+                               assert(0 && "Interfering values have the same color!");
+                       }
+       }
+       obstack_free(&ob, NULL);
+}
+
+void be_copy_opt_init(void) {
+       dbg = firm_dbg_register("ir.be.copyopt");
+       firm_dbg_set_mask(dbg, DEBUG_LVL);
+}
+
+void be_copy_opt(ir_graph* irg) {
+       copy_opt_t *co;
+
+       check_results(irg);
+       co = new_copy_opt(irg);
+
+#ifdef DO_STAT
+       irg_stat_t *stats = new_irg_stat(co);
+       irg_stat_count(stats, co, 0);
+#endif
+
+#ifdef DO_HEUR
+       co_heur_opt(co);
+       check_results(irg);
+#ifdef DO_STAT
+       irg_stat_count(stats, co, 1);
+#endif
+#endif
+
+#ifdef DO_ILP
+       co_ilp_opt(co);
+       check_results(irg);
+#ifdef DO_STAT
+       irg_stat_count(stats, co, 2);
+#endif
+#endif
+
+#ifdef DO_STAT
+       irg_stat_print(stats);
+       all_stat_dump();
+#endif
+
+       free_copy_opt(co);
+}
+
+void be_copy_opt_done(ir_graph* irg) {
+}
diff --git a/ir/be/becopyoptmain.h b/ir/be/becopyoptmain.h
new file mode 100644 (file)
index 0000000..671379d
--- /dev/null
@@ -0,0 +1,22 @@
+/**
+ * Main header for the optimization reducing the copies needed for:
+ * - phi coalescing
+ * - register-constrained nodes
+ *
+ * Checker included.
+ * By request some statistics are collected too.
+ *
+ * @author Daniel Grund
+ * @date 11.04.2005
+ */
+
+#ifndef _BECOPYOPTMAIN_H
+#define _BECOPYOPTMAIN_H
+
+#include "irgraph.h"
+
+void be_copy_opt_init(void);
+void be_copy_opt(ir_graph* irg);
+void be_copy_opt_done(ir_graph* irg);
+
+#endif
diff --git a/ir/be/becopystat.c b/ir/be/becopystat.c
new file mode 100644 (file)
index 0000000..f5e41c5
--- /dev/null
@@ -0,0 +1,106 @@
+/**
+ * @author Daniel Grund
+ * @date 19.04.2005
+ */
+#include "beutil.h"
+#include "becopystat.h"
+#include "list.h"
+
+struct _irg_stat_t {
+       struct list_head chain;
+       ir_graph *irg;
+       const char *irg_name;
+       int interferers, lb, max;
+       int copies[3];
+};
+
+typedef struct _all_stat_t {
+       char *unit_name;
+       struct list_head irgs;
+} all_stat_t;
+
+static all_stat_t *all_stats = NULL;
+
+#define irg_list_entry(lh) list_entry(lh, irg_stat_t, chain)
+
+irg_stat_t *new_irg_stat(copy_opt_t *co) {
+       irg_stat_t *is, *curr;
+
+       if (!all_stats) {
+               all_stats = calloc(1, sizeof(*all_stats));
+               //TODO all_stats->unit_name = ??? */
+               INIT_LIST_HEAD(&all_stats->irgs);
+               is = calloc(1, sizeof(*is));
+               is->irg_name = "CUMULATIVE";
+               list_add_tail(&is->chain, &all_stats->irgs);
+       }
+
+       /* look if we had this irg already */
+       list_for_each_entry(irg_stat_t, curr, &all_stats->irgs, chain)
+               if (curr->irg == co->irg)
+                       return curr;
+
+       /* else create a new entry */
+       is = calloc(1, sizeof(*is));
+       is->irg = co->irg;
+       is->irg_name = get_entity_name(get_irg_entity(co->irg));
+       list_add_tail(&is->chain, &all_stats->irgs);
+       return is;
+}
+
+void irg_stat_count(irg_stat_t *is, copy_opt_t *co, int phase) {
+       unit_t *curr;
+       int max = 0, copies = 0;
+
+       list_for_each_entry(unit_t, curr, &co->units, units) {
+               int i;
+               max += curr->interf + curr->node_count - 1;
+               const ir_node *root = curr->nodes[0];
+               int root_color = get_irn_color(root);
+               copies += curr->interf;
+               for (i=1; i<curr->node_count; ++i) {
+                       const ir_node *arg = curr->nodes[i];
+                       if (root_color != get_irn_color(arg))
+                               copies++;
+               }
+       }
+
+       is->copies[phase] += copies;
+       if (phase == 0)
+               is->max += max;
+       if (phase == 1) {
+               is->interferers += co_get_interferer_count(co);
+               is->lb += co_get_lower_bound(co);
+       }
+}
+
+void irg_stat_print(irg_stat_t *is) {
+       printf("Irg %s: %3d %3d %3d %3d %3d %3d", is->irg_name, is->interferers, is->lb, is->copies[0], is->copies[1], is->copies[2], is->max);
+}
+
+void all_stat_dump(void) {
+       FILE *out;
+       irg_stat_t *cuml, *curr;
+       /* Compute cumulative values */
+       cuml = irg_list_entry(all_stats->irgs.next);
+       cuml->interferers = 0;
+       cuml->lb = 0;
+       cuml->max = 0;
+       cuml->copies[0] = 0;
+       cuml->copies[1] = 0;
+       cuml->copies[2] = 0;
+       list_for_each_entry(irg_stat_t, curr, &all_stats->irgs, chain) {
+               int i = 0;
+               cuml->interferers += curr->interferers;
+               cuml->lb += curr->lb;
+               cuml->max += curr->max;
+               for (i=0; i<3; ++i)
+                       cuml->copies[i] += curr->copies[i];
+       }
+
+       /* dump to file */
+       out = ffopen(all_stats->unit_name, "stats", "wt");
+       list_for_each_entry(irg_stat_t, curr, &all_stats->irgs, chain)
+               fprintf(out, "%15s  %3d %3d %3d %3d %3d %3d", curr->irg_name, curr->interferers, curr->lb, curr->copies[0], curr->copies[1], curr->copies[2], curr->max);
+       fclose(out);
+}
diff --git a/ir/be/becopystat.h b/ir/be/becopystat.h
new file mode 100644 (file)
index 0000000..15fde49
--- /dev/null
@@ -0,0 +1,19 @@
+/**
+ * @author Daniel Grund
+ * @date 11.04.2005
+ */
+
+//TODO
+#ifndef _BECOPYSTAT_H
+#define _BECOPYSTAT_H
+
+#include "becopyopt.h"
+
+typedef struct _irg_stat_t irg_stat_t;
+
+irg_stat_t *new_irg_stat(copy_opt_t *co);
+void irg_stat_count(irg_stat_t *is, copy_opt_t *co, int phase);
+void irg_stat_print(irg_stat_t *is);
+void all_stat_dump(void);
+
+#endif
index 372e695..d6f13e6 100644 (file)
@@ -25,7 +25,7 @@
 #include "beutil.h"
 #include "bechordal.h"
 #include "bechordal.h"
-#include "bephiopt.h"
+#include "becopyoptmain.h"
 #include "phistat.h"
 
 #include "beasm_dump_globals.h"
@@ -103,7 +103,7 @@ void be_init(void)
        be_numbering_init();
        be_ra_init();
        be_ra_chordal_init();
-       be_phi_opt_init();
+       be_copy_opt_init();
 }
 
 extern void be_ra_chordal(ir_graph *irg);
@@ -128,7 +128,7 @@ static void be_main_loop(void)
 #ifdef DUMP_ALLOCATED
                dump_allocated_irg(irg, "");
 #endif
-               be_phi_opt(irg);
+               be_copy_opt(irg);
 
                be_ra_chordal_done(irg);
                be_numbering_done(irg);
diff --git a/ir/be/bephicoal.c b/ir/be/bephicoal.c
deleted file mode 100644 (file)
index a596553..0000000
+++ /dev/null
@@ -1,745 +0,0 @@
-/**
- * @author Daniel Grund
- * @date 04.01.2005
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-
-#include "obst.h"
-#include "set.h"
-#include "pset.h"
-#include "bitset.h"
-#include "debug.h"
-#include "irouts.h"
-#include "irdom.h"
-
-#include "bechordal.h"
-#include "belive_t.h"
-#include "bera_t.h"
-#include "phiclass_t.h"
-#include "bephicoal_t.h"
-
-#define DEBUG_LVL 0 //SET_LEVEL_2
-#define MAX_COLORS 32
-
-#define INITIAL_SLOTS_PINNED_GLOBAL 256
-#define INITIAL_SLOTS_CHANGED_NODES 32
-
-/* some things for readable code */
-#define CHANGE_SAVE NULL
-#define CHANGE_IMPOSSIBLE (ir_node *)1
-#define CHANGE_NYI (ir_node *)2
-#define is_conflicting_node(n) (((int)n) > 2)
-
-/**
- * Models conflicts between nodes. These may be life range conflicts or
- * pinning conflicts, which may occur while changing colors
- */
-typedef struct _conflict_t {
-       ir_node *n1, *n2;
-} conflict_t;
-
-/**
- * If an irn is changed, the changes first get stored in a node_stat_t,
- * to allow undo of changes in case of conflicts.
- */
-typedef struct _node_stat_t {
-       ir_node *irn;
-       int color;
-       int undo_color;
-       char status;            /**< Bit 0: pinned, Bit 1: removed */
-} node_stat_t;
-
-#define _set_pinned(nodestat)    nodestat->status |= 1
-#define _set_removed(nodestat)   nodestat->status |= 2
-#define _clear_pinned(nodestat)  nodestat->status &= 255 ^ 1
-#define _clear_removed(nodestat) nodestat->status &= 255 ^ 2
-#define _is_pinned(nodestat)     (nodestat->status & 1)
-#define _is_removed(nodestat)    (nodestat->status & 2)
-
-/**
- * Central data structure. Contains infos needed during coalescing of the
- * corresponding phi class.
- */
-typedef struct _phi_unit_t {
-       unsigned char node_count;                       /**< size of the nodes-array */
-       unsigned char conflict_count;           /**< size of the conflicts-array */
-       unsigned char conflict_count_org;       /**< initial size of the conflicts-array */
-       ir_node **nodes;                                        /**< [0] is the phi node. [1..node_count-1] the arguments of the phi not interfering with it */
-       conflict_t *conflicts;                          /**< pairs of conflicting ir_nodes. */
-       set *changed_nodes;                                     /**< contains node_stat_t's. */
-} phi_unit_t;
-
-static firm_dbg_module_t *dbgphi = NULL;
-
-/**
- * Contains already optimized ir_nodes of phi-units fully processed.
- * So one can perform a check not to switch them twice or more.
- */
-static pset *pinned_global = NULL;
-
-static int set_cmp_node_stat_t(const void *x, const void *y, size_t size) {
-       return ((node_stat_t *)x)->irn != ((node_stat_t *)y)->irn;
-}
-
-/**
- * Finds a node status entry of a node if existent.
- */
-static INLINE node_stat_t *pu_find_node(phi_unit_t *pu, ir_node *irn) {
-       node_stat_t find;
-       find.irn = irn;
-       return set_find(pu->changed_nodes, &find, sizeof(find), HASH_PTR(irn));
-}
-
-/**
- * Finds a node status entry of a node if existent. Otherwise it will return
- * an initialized new entry for this node.
- */
-static INLINE node_stat_t *pu_find_or_insert_node(phi_unit_t *pu, ir_node *irn) {
-       node_stat_t find;
-       find.irn = irn;
-       find.color = NO_COLOR;
-       find.undo_color = NO_COLOR;
-       find.status = 0;
-       return set_insert(pu->changed_nodes, &find, sizeof(find), HASH_PTR(irn));
-}
-
-/**
- * @return The virtual color of a node, if set before, else just the real color.
- */
-static INLINE int pu_get_new_color(phi_unit_t *pu, ir_node *irn) {
-       node_stat_t *found = pu_find_node(pu, irn);
-       if (found)
-               return found->color;
-       else
-               return get_irn_color(irn);
-}
-
-/**
- * Sets the virtual color of a node.
- */
-static INLINE void pu_set_new_color(phi_unit_t *pu, ir_node *irn, int color) {
-       node_stat_t *found = pu_find_or_insert_node(pu, irn);
-       found->undo_color = found->color;
-       found->color = color;
-       DBG((dbgphi, LEVEL_4, "%n %d\n", irn, color));
-}
-
-/**
- * Sets the virtual color of a node to the color it had,
- * before the last call to pu_set_new_color
- */
-static INLINE void pu_undo_color(phi_unit_t *pu, ir_node *irn) {
-       node_stat_t *ns = pu_find_node(pu, irn);
-       assert(ns && "Nodes whose colors are undone must be in pu->changed_nodes");
-       ns->color = ns->undo_color;
-       DBG((dbgphi, LEVEL_3, "\t\tUndo: col(%n) := %d\n", irn, ns->undo_color));
-}
-
-/**
- * Checks if a node is removed from consideration respectively building
- * a maximum independent set.
- */
-static INLINE int pu_is_node_removed(phi_unit_t *pu, ir_node *irn) {
-       node_stat_t *found = pu_find_node(pu, irn);
-       if (found)
-               return _is_removed(found);
-       else
-               return 0;
-}
-
-/**
- * Removes a node from the base set, out of which a maximum independet
- * set gets build from.
- */
-static INLINE void pu_remove_node(phi_unit_t *pu, ir_node *irn) {
-       node_stat_t *found = pu_find_or_insert_node(pu, irn);
-       _set_removed(found);
-       DBG((dbgphi, LEVEL_4, "%n\n", irn));
-}
-
-/**
- * Checks if a node is local pinned; i.e. it belongs to the same phi unit and
- * has been optimized before the current processed one.
- */
-static INLINE int pu_is_node_pinned(phi_unit_t *pu, ir_node *irn) {
-       node_stat_t *found = pu_find_node(pu, irn);
-       if (found)
-               return _is_pinned(found);
-       else
-               return 0;
-}
-
-/**
- * Local-pins a node, so optimizations of further nodes of the same phi unit
- * can handle situations in which a color change would undo prior optimizations.
- */
-static INLINE void pu_pin_node(phi_unit_t *pu, ir_node *irn) {
-       node_stat_t *found = pu_find_or_insert_node(pu, irn);
-       _set_pinned(found);
-       DBG((dbgphi, LEVEL_4, "%n\n", irn));
-}
-
-/**
- * If a local pinned conflict occurs, a new edge in the conflict graph is added.
- * The next maximum independent set build, will regard it.
- */
-static INLINE void pu_add_conflict(phi_unit_t *pu, ir_node *n1, ir_node *n2) {
-       int count = pu->conflict_count;
-
-       DBG((dbgphi, LEVEL_3, "\t    %n -- %n\n", n1, n2));
-       assert(count != 255 && "Too much conflicts. Can hold max 255 entries");
-       if ((count & 15) == 0)
-               pu->conflicts = realloc(pu->conflicts, (count + 16)*sizeof(*pu->conflicts));
-
-       if ((int)n1 < (int)n2) {
-               pu->conflicts[count].n1 = n1;
-               pu->conflicts[count].n2 = n2;
-       } else {
-               pu->conflicts[count].n1 = n2;
-               pu->conflicts[count].n2 = n1;
-       }
-
-       pu->conflict_count++;
-}
-
-/**
- * Checks if two nodes are in a conflict.
- */
-static INLINE int pu_are_conflicting(phi_unit_t *pu, ir_node *n1, ir_node *n2) {
-       const ir_node *o1, *o2;
-       int i;
-
-       if ((int)n1 < (int)n2) {
-               o1 = n1;
-               o2 = n2;
-       } else {
-               o1 = n2;
-               o2 = n1;
-       }
-
-       for (i = 0; i < pu->conflict_count; ++i)
-               if (pu->conflicts[i].n1 == o1 && pu->conflicts[i].n2 == o2)
-                       return 1;
-       return 0;
-}
-
-/**
- * Checks if a node is a member of a phi unit.
- * Other nodes should not be pinned global.
- */
-static INLINE int pu_is_global_pinnable(phi_unit_t *pu, ir_node *irn) {
-       int i;
-       for (i = 0; i < pu->node_count; ++i)
-               if (pu->nodes[i] == irn)
-                       return 1;
-       return 0;
-}
-
-/**
- * Determines a maximum independent set with respect to the conflict edges
- * in pu->conflicts and the nodes beeing all non-removed nodes of pu->nodes.
- * TODO: make this 'un-greedy'
- * ATTENTION: be aware that phi nodes find their way into the set. For 1 phi
- *                       in greedy version this is no prob, cause it comes first at [0].
- */
-static int pu_get_mis(phi_unit_t *pu, struct obstack *res) {
-       int i, o, size = 0;
-       ir_node **mis;
-
-       DBG((dbgphi, LEVEL_2, "\t    Max indep set:\n"));
-       for (i = 0; i < pu->node_count; ++i) {
-               int intf_det = 0;
-               if (pu_is_node_removed(pu, pu->nodes[i]))
-                       continue;
-               mis = (ir_node**) obstack_base(res);
-               for (o = 0; o < size; ++o)
-                       if (pu_are_conflicting(pu, pu->nodes[i], mis[o])) {
-                               intf_det = 1;
-                               break;
-                       }
-
-               if (!intf_det) {
-                       DBG((dbgphi, LEVEL_2, "\t\t%n\n", pu->nodes[i]));
-                       obstack_ptr_grow(res, pu->nodes[i]);
-                       size++;
-               }
-       }
-       return size;
-}
-
-/**
- * Performs virtual re-coloring of node @p n to color @p col. Virtual colors of
- * other nodes are changed too, as required to preserve correctness. Function is
- * aware of local and global pinning. Recursive.
- * @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
- * @param  changed_nodes An obstack on which all ir_nodes get growed on, which are changed
- * @return CHANGE_SAVE iff setting the color is possible, with all transiteve effects.
- *         CHANGE_IMPOSSIBLE iff conflicts with reg-constraintsis occured.
- *         CHANGE_NYI iff an unhandled situation occurs.
- *         Else the first conflicting ir_node encountered is returned.
- *
- * ASSUMPTION: Assumes that a life range of a single value can't be spilt into
- *                        several smaller intervals where other values can live in between.
- *             This should be true in SSA.
- */
-static ir_node *_pu_color_irn(phi_unit_t *pu, ir_node *irn, int col, const ir_node *trigger, struct obstack *changed_nodes) {
-       ir_node *res;
-       struct obstack confl_ob;
-       ir_node **confl, *cn;
-       int i, irn_col;
-
-       DBG((dbgphi, LEVEL_3, "\t\t%n \tcaused col(%n) \t%2d --> %2d\n", trigger, irn, pu_get_new_color(pu, irn), col));
-       obstack_init(&confl_ob);
-       irn_col = pu_get_new_color(pu, irn);
-
-       if (irn_col == col)
-               goto ret_save;
-       if (pset_find_ptr(pinned_global, irn) || pu_is_node_pinned(pu, irn)) {
-               res = irn;
-               goto ret_confl;
-       }
-
-       /* get 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 = get_live_in(irn_bl);
-                       for (n = pset_first(live_ins); n; n = pset_next(live_ins))
-                               if (is_allocatable_irn(n) && n != trigger && pu_get_new_color(pu, n) == col && phi_ops_interfere(irn, n)) {
-                                       DBG((dbgphi, LEVEL_4, "\t\t    %n\ttroubles\n", n));
-                                       obstack_ptr_grow(&confl_ob, n);
-                                       pset_break(live_ins);
-                                       break;
-                               }
-               }
-
-               /* 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);
-                               if (is_allocatable_irn(n) && n != trigger && pu_get_new_color(pu, n) == col && phi_ops_interfere(irn, n)) {
-                                       DBG((dbgphi, LEVEL_4, "\t\t    %n\ttroubles\n", n));
-                                       obstack_ptr_grow(&confl_ob, n);
-                               }
-                       }
-
-                       /* 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 = _pu_color_irn(pu, cn, irn_col, irn, changed_nodes);
-               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((dbgphi, LEVEL_3, "\t\t%n save\n", irn));
-       obstack_free(&confl_ob, NULL);
-       pu_set_new_color(pu, irn, col);
-       obstack_ptr_grow(changed_nodes, irn);
-       return CHANGE_SAVE;
-
-ret_confl:
-       DBG((dbgphi, LEVEL_3, "\t\t%n conflicting\n", irn));
-       obstack_free(&confl_ob, NULL);
-       return res;
-}
-
-static ir_node *pu_color_irn(phi_unit_t *pu, ir_node *irn, int col) {
-       ir_node *res;
-       struct obstack ob_undo;
-
-       obstack_init(&ob_undo);
-       res = _pu_color_irn(pu, irn, col, irn, &ob_undo);
-
-       if (res != CHANGE_SAVE) { /* undo virtual changes caused by the last call */
-               int i;
-               ir_node *undo_node, **undo_nodes;
-
-               obstack_ptr_grow(&ob_undo, NULL);
-               undo_nodes = obstack_finish(&ob_undo);
-               for (i = 0, undo_node = undo_nodes[0]; undo_node; undo_node = undo_nodes[++i])
-                       pu_undo_color(pu, undo_node);
-       }
-
-       obstack_free(&ob_undo, NULL);
-       return res;
-}
-
-/**
- * Tries to set as much members of a phi unit as possible to color @p col.
- * All changes taken together are guaranteed to be conflict free.
- */
-static int pu_try_color(phi_unit_t *pu, int col, int b_size) {
-       struct obstack ob_mis;
-       int i, redo, mis_size;
-       ir_node **mis;
-
-       obstack_init(&ob_mis);
-       redo = 1;
-       while (redo) {
-               redo = 0;
-               /* get a max independent set regarding current conflicts */
-               mis_size = pu_get_mis(pu, &ob_mis);
-               mis = obstack_finish(&ob_mis);
-
-               /* shortcut: if mis size is worse than best, then mis won't be better. */
-               if (mis_size < b_size)
-                       goto ret;
-
-               /* check if its possible to set the color for all members of the maximum set*/
-               for (i = 0; i < mis_size; ++i) {
-                       ir_node *test_node, *confl_node;
-
-                       test_node = mis[i];
-                       DBG((dbgphi, LEVEL_2, "\t    Testing %n\n", test_node));
-                       confl_node = pu_color_irn(pu, test_node, col);
-
-                       if (confl_node == CHANGE_SAVE) {
-                               DBG((dbgphi, LEVEL_2, "\t    Save\n"));
-                               pu_pin_node(pu, test_node);
-                       } else if (confl_node == CHANGE_NYI) {
-                               DBG((dbgphi, 0, "\t    NYI\n"));
-                       } else if (confl_node == CHANGE_IMPOSSIBLE) {
-                               /* TODO: this may happen due to reg constraints --> remove from set ?? */
-                       } else {
-                               DBG((dbgphi, LEVEL_2, "\t    Conflicting\n"));
-                               assert(is_conflicting_node(confl_node));
-
-                               if (pu_is_node_pinned(pu, confl_node)) {
-                                       /* changing test_node would change back a node of current phi unit */
-                                       pu_add_conflict(pu, confl_node, test_node);
-                                       redo = 1;
-                               }
-                               if (pset_find_ptr(pinned_global, confl_node)) {
-                                       /* changing test_node would change back a node of a prior phi unit */
-                                       pu_remove_node(pu, test_node);
-                                       redo = 1;
-                               }
-                       }
-
-                       if (confl_node != CHANGE_SAVE) {
-                               /* shortcut: color not possible for phi node (phi comes first) ==> exit */
-                               if (i == 0) {
-                                       mis_size = 0;
-                                       goto ret;
-                               }
-                               /* break iteration over current mis, because it will change */
-                               break;
-                       }
-               }
-               obstack_free(&ob_mis, mis);
-       }
-
-ret:
-       obstack_free(&ob_mis, NULL);
-       return mis_size;
-}
-
-/**
- * Tries to re-allocate colors of nodes in this phi unit, to achieve a lower
- * number of copy instructions placed during phi destruction. Optimized version.
- * Works only for phi-classes/phi-units with exactly 1 phi node, which is the
- * case for approximately 80% of all phi classes. All other phi classes are
- * reduced to this case.
- */
-static void pu_coal_1_phi(phi_unit_t *pu) {
-       int size, col, b_size, b_color;
-       set *b_changes;
-
-       /* init best search result */
-       b_changes = NULL;
-       b_size = 0;
-       b_color = NO_COLOR;
-
-       /* find optimum of all colors */
-       for (col = MAX_COLORS-1; col >= 0; --col) {
-               DBG((dbgphi, 1, "\tTrying color %d\n", col));
-               size = pu_try_color(pu, col, b_size);
-
-               /* did we find a better max ind. set? */
-               if (size > b_size) {
-                       DBG((dbgphi, 1, "\tBetter size: %d\n", size));
-                       if (b_changes)
-                               del_set(b_changes);
-                       b_changes = pu->changed_nodes;
-                       b_size = size;
-                       b_color = col;
-               } else {
-                       del_set(pu->changed_nodes);
-               }
-
-               /* reset the phi unit to original state for next color */
-               pu->changed_nodes = new_set(set_cmp_node_stat_t, INITIAL_SLOTS_CHANGED_NODES);
-               pu->conflict_count = pu->conflict_count_org;
-
-               /* shortcut: if all members can be colored we are (very) happy */
-               if (b_size == pu->node_count)
-                       break;
-       }
-
-       /* now apply the found optimum */
-       if (b_changes) {
-               node_stat_t *ns;
-               DBG((dbgphi, 1, "\tBest color: %d  Copies: %d/%d\n", b_color, pu->node_count-b_size, pu->node_count-1));
-               for (ns = set_first(b_changes); ns; ns = set_next(b_changes)) {
-                       /* NO_COLOR is possible, if we had an undo; so the irn stays in the
-                        * pu->changed_nodes with new color set to NO_COLOR. */
-                       if (ns->color != NO_COLOR) {
-                               DBG((dbgphi, 1, "\t    color(%n) := %d\n", ns->irn, ns->color));
-                               set_irn_color(ns->irn, ns->color);
-                               if (pu_is_global_pinnable(pu, ns->irn) && ns->color == pu_get_new_color(pu, pu->nodes[0]))
-                                       pset_insert_ptr(pinned_global, ns->irn);
-                       }
-               }
-               free(b_changes);
-       } else {
-               DBG((dbgphi, 1, "\tBest color: none\n"));
-       }
-}
-
-
-/**
- * Prepares a phi class for further processing as one or more phi units.
- * Calls the worker-functions for all units.
- * @param pc The phi class to process.
- * @param root_phi In case of recursive call this is the phi node not beeing
- *                                an argument in the phi1unit.
- *                                Else this has to be NULL.
- */
-static void coal_phi_class(pset *pc, ir_node *root_phi) {
-       int phi_count = 0;
-       ir_node *n, *phi = NULL;
-
-       /* unfortunately there _can_ be >1 phi nodes in a phi1unit,
-        * so we have an if... */
-       if (root_phi) {
-               phi = root_phi;
-               phi_count = 1;
-       } else {
-               /* get the phi count of this class. May result in phi_count == 1 */
-               for (n = pset_first(pc); n; n = pset_next(pc))
-                       if (is_Phi(n)) {
-                               phi = n;
-                               phi_count++;
-                       }
-       }
-
-       /* the 'simple' case */
-       if (phi_count == 1) {
-               phi_unit_t *pu;
-               ir_node **tmp;
-               struct obstack ob;
-               int i, o;
-
-               obstack_init(&ob);
-
-               DBG((dbgphi, 1, "\tPhi-1 unit:\n"));
-               pu = calloc(1, sizeof(*pu));
-
-               /* build member set not containing phi interferers */
-               DBG((dbgphi, 1, "\t    %n\n", phi));
-               obstack_ptr_grow(&ob, phi);
-               pu->node_count = 1;
-
-               for (n = pset_first(pc); n; n = pset_next(pc)) {
-                       if (n == phi)
-                               continue;
-                       if (!phi_ops_interfere(phi, n)) {
-                               DBG((dbgphi, 1, "\t    %n\n", n));
-                               obstack_ptr_grow(&ob, n);
-                               pu->node_count++;
-                       } else {
-                               DBG((dbgphi, 1, "\t    %n \tdropped\n", n));
-                       }
-               }
-               tmp = obstack_finish(&ob);
-               pu->nodes = malloc(pu->node_count * sizeof(*pu->nodes));
-               memcpy(&pu->nodes[0], tmp, pu->node_count * sizeof(*tmp));
-               obstack_free(&ob, NULL);
-
-               /* init conlict graph to life range interference */
-               DBG((dbgphi, 1, "\tInitial conflicts:\n"));
-               for (i = 0; i < pu->node_count; ++i)
-                       for (o = i+1; o < pu->node_count; ++o)
-                               if (phi_ops_interfere(pu->nodes[i], pu->nodes[o]))
-                                       pu_add_conflict(pu, pu->nodes[i], pu->nodes[o]);
-               pu->conflict_count_org = pu->conflict_count;
-
-               /* init changed nodes */
-               pu->changed_nodes = new_set(set_cmp_node_stat_t, INITIAL_SLOTS_CHANGED_NODES);
-
-               pu_coal_1_phi(pu);
-
-               free(pu->nodes);
-               free(pu->changed_nodes);
-               if (pu->conflicts)
-                       free(pu->conflicts);
-       } else {        /* the 'not so easy' case */
-               DBG((dbgphi, 1, "\tPhi-n unit:\n"));
-
-               /* copy pc into big_pc... */
-               pset *copy = pset_new_ptr(32);
-               for (n = pset_first(pc); n; n = pset_next(pc)) {
-                       DBG((dbgphi, 1, "\t    %n\n", n));
-                       pset_insert_ptr(copy, n);
-               }
-
-               /* ... because we want to build small 'connected graphs' and
-                * delete their members from the copy */
-               while (pset_count(copy) > 0) {
-                       /* build all connected sets from the copy */
-                       int last = 0, first = 0;
-                       ir_node **queue = calloc(pset_count(copy), sizeof(*queue));
-
-                       /* pick some node out of copy, place into queue */
-                       n = pset_first(copy);
-                       pset_break(copy);
-                       pset_remove_ptr(copy, n);
-                       queue[last++] = n;
-
-                       DBG((dbgphi, 1, "\tConnected:\n"));
-                       pset *connected = pset_new_ptr(8);
-                       while (first < last) {
-                               /* pick n out of the queue into connected set */
-                               n = queue[first++];
-                               pset_insert_ptr(connected, n);
-                               DBG((dbgphi, 1, "\t    %n\n", n));
-
-
-                               /* check if pre/successors are 'connected' with n */
-                               {
-                                       ir_node *other;
-                                       int i;
-                                       /* insert all args of n, which are in the phi class to the queue */
-                                       for(i=0; i < get_irn_arity(n); ++i) {
-                                               other = get_irn_n(n, i);
-                                               if (pset_find_ptr(copy, other) && !values_interfere(n, other)) {
-                                                       queue[last++] = other;
-                                                       pset_remove_ptr(copy, other);
-                                               }
-                                       }
-                                       /* same for outs of n */
-                                       for(i=0; i < get_irn_n_outs(n); ++i) {
-                                               other = get_irn_out(n, i);
-                                               if (pset_find_ptr(copy, other) && !values_interfere(n, other)) {
-                                                       queue[last++] = other;
-                                                       pset_remove_ptr(copy, other);
-                                               }
-                                       }
-                               }
-                       }
-
-                       /* Now we have a "connected graph" build from copy==pc.
-                        * Remove 1-phi-units from the connected set for
-                        * passing to optimizer */
-                       while (pset_count(connected) > 0) {
-                               pset *phi1unit;
-                               ir_node *phi = NULL;
-                               int i;
-                               /* search a phi node */
-                               for (n = pset_first(connected); n; n = pset_next(connected))
-                                       if (is_Phi(n)) {
-                                               phi = n;
-                                               break;
-                                       }
-                               pset_break(connected);
-
-                               /* if there are only non-phi nodes left quit */
-                               if (!phi)
-                                       break;
-
-                               /* Build a 1-phi-unit with this phi */
-                               DBG((dbgphi, 1, "\t    Phi-1-unit:\n"));
-                               phi1unit = pset_new_ptr(8);
-                               pset_insert_ptr(phi1unit, phi);
-                               pset_remove_ptr(connected, phi);
-                               DBG((dbgphi, 1, "\t\t%n\n", phi));
-                               /* insert all arguments of phi, which are in the connected set
-                                * to the 1-phi-unit */
-                               for(i=0; i < get_irn_arity(phi); ++i) {
-                                       ir_node *arg = get_irn_n(phi, i);
-                                       if (pset_find_ptr(connected, arg)) {
-                                               DBG((dbgphi, 1, "\t\t%n\n", arg));
-                                               pset_insert_ptr(phi1unit, arg);
-                                               pset_remove_ptr(connected, arg);
-                                       }
-                               }
-
-                               /* finally the call for coalescing the 1-phi-unit */
-                               if (pset_count(phi1unit) > 1) /* ==1 can happen if the connected set contains only a single phi node */
-                                       coal_phi_class(phi1unit, phi);
-
-                               del_pset(phi1unit);
-                       }
-                       del_pset(connected);
-                       free(queue);
-               }
-               del_pset(copy);
-       }
-}
-
-
-void be_phi_coalesce(pset *all_phi_classes) {
-       pset *pc;
-
-       pinned_global = pset_new_ptr(INITIAL_SLOTS_PINNED_GLOBAL);
-
-       for (pc = pset_first(all_phi_classes); pc; pc = pset_next(all_phi_classes))
-               coal_phi_class(pc, NULL);
-
-       del_pset(pinned_global);
-}
-
-
-void be_phi_coal_init(void) {
-       dbgphi = firm_dbg_register("ir.be.phicoal");
-       firm_dbg_set_mask(dbgphi, DEBUG_LVL);
-}
diff --git a/ir/be/bephicoal_t.h b/ir/be/bephicoal_t.h
deleted file mode 100644 (file)
index ded5505..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * @author Daniel Grund
- * @date 04.01.2005
- */
-
-#ifndef _BEPHICOAL_T_H
-#define _BEPHICOAL_T_H
-
-#include "pset.h"
-
-void be_phi_coal_init(void);
-void be_phi_coalesce(pset *all_phi_classes);
-
-#endif
diff --git a/ir/be/bephicoalilp.c b/ir/be/bephicoalilp.c
deleted file mode 100644 (file)
index 9bcba75..0000000
+++ /dev/null
@@ -1,846 +0,0 @@
-/**
- * @author Daniel Grund
- * @date 10.03.2005
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-#define __USE_BSD
-#include <string.h>
-
-#include "obst.h"
-#include "set.h"
-#include "pset.h"
-#include "list.h"
-#include "debug.h"
-
-#include "irdom.h"
-#include "irouts.h"
-#include "bephicoalilp_t.h"
-#include "benumb_t.h"
-#include "bera_t.h"
-#include "belive_t.h"
-#include "bechordal_t.h"
-
-
-#define MAX_COLORS 32
-
-/**
- * define get_weight to sth representing the _gain_ if node n and m
- * have the same color. Must return values MIN_WEIGHT <= . <= MAX_WEIGHT.
- */
-#define get_weight(n,m) 1
-#define MAX_WEIGHT 127
-#define MIN_WEIGHT 0
-
-/** define this to sth which returns 0 iff c is NOT a possible color for node n */
-#define is_possible_color(n,c) 1
-
-/** define this to sth which returns 1 iff not all colors can be assigned to node n */
-#define is_constrained(n) 0
-
-#undef DUMP_MATRICES
-#define DUMP_MPS
-#undef DUMP_LPO
-#undef DUMP_LPP
-#define DO_SOLVE
-#define DELETE_FILES
-#undef USE_SOS
-#define SSH_USER_HOST "kb61@sp-smp.rz.uni-karlsruhe.de"
-
-/* The overhead stuff */
-#define DEBUG_LVL SET_LEVEL_1
-#define SET_LIVING_INIT 32
-#define MAX_Q_INIT 0
-#define MIN_Q_INIT 0
-
-static firm_dbg_module_t *dbgphi = NULL;
-
-static INLINE FILE *ffopen(const char *base, const char *ext, const char *mode) {
-       FILE *out;
-       char buf[1024];
-
-       snprintf(buf, sizeof(buf), "%s.%s", base, ext);
-       if (! (out = fopen(buf, mode))) {
-               fprintf(stderr, "Cannot open file %s in mode %s\n", buf, mode);
-               return NULL;
-       }
-       return out;
-}
-
-/** A type storing names of the x variables in the form x[NUMBER]_[COLOR] */
-typedef struct _x_vec_t {
-       int n, c;
-} x_vec_t;
-
-/**
- * A type storing the unmodified '0-1 quadratic program' of the form
- * min f = xQx
- * udN:  Ax  = e
- *       Bx <= e
- *        x \in {0, 1}
- *
- * This problem is called the original problem
- */
-typedef struct _problem_instance_t {
-       ir_graph* irg;
-       const char *name;
-       int x_dim, A_dim, B_dim;
-       char *Q, *A, *B;
-       x_vec_t *x;                             /**< stores the names of the x variables. Sorted first by node-num then by color. */
-
-       /* needed only for linearizations */
-       int bigM, maxQij, minQij, correction;
-
-       /* overhead needed to build this */
-       set *num2pos;
-       struct obstack ob;
-       int curr_col;
-       int curr_row;
-} problem_instance_t;
-
-/**
- * For each node taking part in the opt-problem its position in the
- * x-variable-vector is stored in a set. This set maps the node-nr (given by
- * benumb) to  the position in the vector.
- */
-typedef struct _num2pos_t {
-       int num, pos;
-} num2pos_t;
-
-/* Nodes have consecutive numbers so... */
-#define HASH_NUM(num) num
-
-static int pi_num2pos_cmp(const void *x, const void *y, size_t size) {
-       return ((num2pos_t *)x)->num != ((num2pos_t *)y)->num;
-}
-
-/**
- * Sets the first position of node with number num to pos.
- * See x_vec_t *x in _problem_instance_t.
- */
-static INLINE void pi_set_first_pos(problem_instance_t *pi, int num, int pos) {
-       num2pos_t find;
-       find.num = num;
-       find.pos = pos;
-       set_insert(pi->num2pos, &find, sizeof(find), HASH_NUM(num));
-}
-
-/**
- * Get position by number. (First possible color)
- * returns -1 if not found.
- */
-static INLINE int pi_get_first_pos(problem_instance_t *pi, int num) {
-       num2pos_t find, *found;
-       find.num = num;
-       found = set_find(pi->num2pos, &find, sizeof(find), HASH_NUM(num));
-       if (found) {
-               assert(pi->x[found->pos].n == num && (found->pos == 0 || pi->x[found->pos-1].n != num) && "pi->num2pos is broken!");
-               return found->pos;
-       } else
-               return -1;
-}
-
-/**
- * Get position by number and color.
- * returns -1 if not found.
- */
-static INLINE int pi_get_pos(problem_instance_t *pi, int num, int col) {
-       num2pos_t find, *found;
-       find.num = num;
-       int pos;
-       found = set_find(pi->num2pos, &find, sizeof(find), HASH_NUM(num));
-       if (!found)
-               return -1;
-       pos = found->pos;
-       while (pos < pi->x_dim && pi->x[pos].n == num && pi->x[pos].c < col)
-               pos++;
-
-       if (pi->x[pos].n == num && pi->x[pos].c == col)
-               return pos;
-       else
-               return -1;
-}
-
-/**
- * Checks if all nodes in living are live_out in block block.
- */
-static INLINE int all_live_out(ir_node *block, pset *living) {
-       ir_node *n;
-       for (n = pset_first(living); n; n = pset_next(living))
-               if (!is_live_out(block, n)) {
-                       pset_break(living);
-                       return 0;
-               }
-       return 1;
-}
-
-/**
- * Finds all cliques in the interference graph, which are not conatained in
- * another one (or at least an approximation of that).
- * This is used for the matrix B.
- */
-static void pi_clique_finder(ir_node *block, void *env) {
-       enum phase_t {growing, shrinking} phase = growing;
-       problem_instance_t *pi = env;
-       struct list_head *head = &get_ra_block_info(block)->border_head;
-       border_t *b;
-       pset *living = pset_new_ptr(SET_LIVING_INIT);
-
-       list_for_each_entry_reverse(border_t, b, head, list) {
-               const ir_node *irn = b->irn;
-               if (!is_possible_color(n, pi->curr_col))
-                       continue;
-
-               if (b->is_def) {
-                       DBG((dbgphi, LEVEL_2, "Def %n\n", irn));
-                       pset_insert_ptr(living, irn);
-                       phase = growing;
-               } else { /* is_use */
-                       DBG((dbgphi, LEVEL_2, "Use %n\n", irn));
-
-                       /* before shrinking the set store the current 'maximum' clique;
-                        * do NOT if clique is a single node
-                        * do NOT if all values are live_out */
-                       if (phase == growing && pset_count(living) >= 2 && !all_live_out(block, living)) {
-                               ir_node *n;
-                               for (n = pset_first(living); n; n = pset_next(living)) {
-                                       int pos = pi_get_pos(pi, get_irn_graph_nr(n), pi->curr_col);
-                                       pi->B[pi->curr_row*pi->x_dim + pos] = 1;
-                                       DBG((dbgphi, LEVEL_2, "B[%d, %d] := %d\n", pi->curr_row, pos, 1));
-                               }
-                               pi->curr_row++;
-                       }
-                       pset_remove_ptr(living, irn);
-                       phase = shrinking;
-               }
-       }
-
-       del_pset(living);
-}
-
-#ifdef DUMP_MATRICES
-/**
- * Dump the raw matrices of the problem to a file for debugging.
- */
-static void pi_dump_matrices(problem_instance_t *pi) {
-       int i, o;
-       FILE *out = ffopen(pi->name, "matrix", "wt");
-
-       DBG((dbgphi, LEVEL_1, "Dumping raw...\n"));
-       fprintf(out, "\n\nx-names =\n");
-       for (i=0; i<pi->x_dim; ++i)
-               fprintf(out, "%5d %2d\n", pi->x[i].n, pi->x[i].c);
-
-       fprintf(out, "\n\n-Q =\n");
-       for (i=0; i<pi->x_dim; ++i) {
-               for (o=0; o<pi->x_dim; ++o)
-                       fprintf(out, "%d", -pi->Q[i*pi->x_dim + o]);
-               fprintf(out, "\n");
-       }
-
-       fprintf(out, "\n\nA =\n");
-       for (i=0; i<pi->A_dim; ++i) {
-               for (o=0; o<pi->x_dim; ++o)
-                       fprintf(out, "%d", pi->A[i*pi->x_dim + o]);
-               fprintf(out, "\n");
-       }
-
-       fprintf(out, "\n\nB =\n");
-       for (i=0; i<pi->B_dim; ++i) {
-               for (o=0; o<pi->x_dim; ++o)
-                       fprintf(out, "%d", pi->B[i*pi->x_dim + o]);
-               fprintf(out, "\n");
-       }
-       fclose(out);
-}
-#endif
-
-#ifdef DUMP_MPS
-/**
- * Dumps an mps file representing the problem. This is NOT the old-style,
- * fixed-column format. Spaces are separators, MARKER-lines are used in
- * COLUMN section to define binaries.
- */
-static void pi_dump_mps(problem_instance_t *pi) {
-       int i, o, max_abs_Qij;
-       FILE *out = ffopen(pi->name, "mps", "wt");
-
-       DBG((dbgphi, LEVEL_1, "Dumping mps...\n"));
-       max_abs_Qij = pi->maxQij;
-       if (-pi->minQij > max_abs_Qij)
-               max_abs_Qij = -pi->minQij;
-       pi->bigM = pi->A_dim * max_abs_Qij;
-       DBG((dbgphi, LEVEL_2, "BigM = %d\n", pi->bigM));
-
-       fprintf(out, "NAME %s\n", pi->name);
-
-       fprintf(out, "ROWS\n");
-       fprintf(out, " N obj\n");
-       for (i=0; i<pi->x_dim; ++i)
-               fprintf(out, " E cQ%d\n", i);
-       for (i=0; i<pi->A_dim; ++i)
-               fprintf(out, " E cA%d\n", i);
-       for (i=0; i<pi->B_dim; ++i)
-               fprintf(out, " L cB%d\n", i);
-       for (i=0; i<pi->x_dim; ++i)
-               fprintf(out, " L cy%d\n", i);
-
-       fprintf(out, "COLUMNS\n");
-       /* the x vars come first */
-       /* mark them as binaries */
-       fprintf(out, "    MARKI0\t'MARKER'\t'INTORG'\n");
-#ifdef USE_SOS
-       int sos_cnt = 0;
-       fprintf(out, " S1 SOS_%d\t'MARKER'\t'SOSORG'\n", sos_cnt++);
-#endif
-       for (i=0; i<pi->x_dim; ++i) {
-#ifdef USE_SOS
-               if (i>0 && pi->x[i].n != pi->x[i-1].n) {
-                       fprintf(out, "    SOS_%d\t'MARKER'\t'SOSEND'\n", sos_cnt++);
-                       fprintf(out, " S1 SOS_%d\t'MARKER'\t'SOSORG'\n", sos_cnt++);
-               }
-#endif
-               /* participation in objective */
-               fprintf(out, "    x%d_%d\tobj\t%d\n", pi->x[i].n, pi->x[i].c, -pi->bigM);
-               /* in Q */
-               for (o=0; o<pi->x_dim; ++o) {
-                       int Qoi = pi->Q[o*pi->x_dim + i];
-                       if (Qoi)
-                               fprintf(out, "    x%d_%d\tcQ%d\t%d\n", pi->x[i].n, pi->x[i].c, o, Qoi);
-               }
-               /* in A */
-               for (o=0; o<pi->A_dim; ++o) {
-                       int Aoi = pi->A[o*pi->x_dim + i];
-                       if (Aoi)
-                               fprintf(out, "    x%d_%d\tcA%d\t%d\n", pi->x[i].n, pi->x[i].c, o, Aoi);
-               }
-               /* in B */
-               for (o=0; o<pi->B_dim; ++o) {
-                       int Boi = pi->B[o*pi->x_dim + i];
-                       if (Boi)
-                               fprintf(out, "    x%d_%d\tcB%d\t%d\n", pi->x[i].n, pi->x[i].c, o, Boi);
-               }
-               /* in y */
-               fprintf(out, "    x%d_%d\tcy%d\t%d\n", pi->x[i].n, pi->x[i].c, i, 2*pi->bigM);
-       }
-#ifdef USE_SOS
-       fprintf(out, "    SOS_%d\t'MARKER'\t'SOSEND'\n", sos_cnt++);
-#endif
-       fprintf(out, "    MARKI1\t'MARKER'\t'INTEND'\n"); /* end of marking */
-
-       /* next the s vars */
-       for (i=0; i<pi->x_dim; ++i) {
-               /* participation in objective */
-               fprintf(out, "    s%d_%d\tobj\t%d\n", pi->x[i].n, pi->x[i].c, 1);
-               /* in Q */
-               fprintf(out, "    s%d_%d\tcQ%d\t%d\n", pi->x[i].n, pi->x[i].c, i, -1);
-       }
-
-       /* next the y vars */
-       for (i=0; i<pi->x_dim; ++i) {
-               /* in Q */
-               fprintf(out, "    y%d_%d\tcQ%d\t%d\n", pi->x[i].n, pi->x[i].c, i, -1);
-               /* in y */
-               fprintf(out, "    y%d_%d\tcy%d\t%d\n", pi->x[i].n, pi->x[i].c, i, 1);
-       }
-
-       fprintf(out, "RHS\n");
-       for (i=0; i<pi->x_dim; ++i)
-               fprintf(out, "    rhs\tcQ%d\t%d\n", i, -pi->bigM);
-       for (i=0; i<pi->A_dim; ++i)
-               fprintf(out, "    rhs\tcA%d\t%d\n", i, 1);
-       for (i=0; i<pi->B_dim; ++i)
-               fprintf(out, "    rhs\tcB%d\t%d\n", i, 1);
-       for (i=0; i<pi->x_dim; ++i)
-               fprintf(out, "    rhs\tcy%d\t%d\n", i, 2*pi->bigM);
-
-       fprintf(out, "ENDATA\n");
-       fclose(out);
-
-       out = ffopen(pi->name, "mst", "wt");
-       fprintf(out, "NAME\n");
-       for (i=0; i<pi->x_dim; ++i) {
-               int val, n, c;
-               n = pi->x[i].n;
-               c = pi->x[i].c;
-               if (get_irn_color(get_irn_for_graph_nr(pi->irg, n)) == c)
-                       val = 1;
-               else
-                       val = 0;
-               fprintf(out, "    x%d_%d\t%d\n", n, c, val);
-       }
-       fprintf(out, "ENDATA\n");
-       fclose(out);
-}
-#endif
-
-#if defined(DUMP_LPO) || defined(DUMP_LPP)
-/**
- * Dumps constraints used by both linearizations
- */
-static void pi_dump_lp_common_constraints(problem_instance_t *pi, FILE *out) {
-       int i, o;
-       /* knapsack constraints */
-       for (i=0; i<pi->A_dim; ++i)     {
-               for (o=0; o<pi->x_dim; ++o)
-                       if (pi->A[i*pi->x_dim + o])
-                               fprintf(out, "+x%d_%d ", pi->x[o].n, pi->x[o].c);
-               fprintf(out, " = 1;\n");
-       }
-       fprintf(out, "\n\n");
-
-       /* interference graph constraints */
-       for (i=0; i<pi->B_dim; ++i)     {
-               for (o=0; o<pi->x_dim; ++o)
-                       if (pi->B[i*pi->x_dim + o])
-                               fprintf(out, "+x%d_%d ", pi->x[o].n, pi->x[o].c);
-               fprintf(out, " <= 1;\n");
-       }
-       fprintf(out, "\n\n");
-
-       /* integer constraints */
-       fprintf(out, "int x%d_%d", pi->x[0].n, pi->x[0].c);
-       for (i=1; i<pi->x_dim; ++i)
-               fprintf(out, ", x%d_%d", pi->x[i].n, pi->x[i].c);
-       fprintf(out, ";\n");
-}
-#endif
-
-#ifdef DUMP_LPO
-/**
- * Dumps the problem instance as a MILP. The original problem is transformed into:
- * min f = es - Mex
- * udN:  Qx -y -s +Me = 0
- *       Ax  = e
- *       Bx <= e
- *        y <= 2M(e-x)
- *        x \in N   y, s >= 0
- *
- * with M >= max sum Q'ij * x_j
- *            i   j
- */
-static void pi_dump_lp_org(problem_instance_t *pi) {
-       int i, o, max_abs_Qij;
-       FILE *out = ffopen(pi->name, "lpo", "wt");
-
-       DBG((dbgphi, LEVEL_1, "Dumping lp_org...\n"));
-       /* calc the big M for Q */
-       max_abs_Qij = pi->maxQij;
-       if (-pi->minQij > max_abs_Qij)
-               max_abs_Qij = -pi->minQij;
-       pi->bigM = pi->A_dim * max_abs_Qij;
-       DBG((dbgphi, LEVEL_2, "BigM = %d\n", pi->bigM));
-
-       /* generate objective function */
-       fprintf(out, "min: ");
-       for (i=0; i<pi->x_dim; ++i)
-               fprintf(out, "+s%d_%d -%dx%d_%d ", pi->x[i].n, pi->x[i].c, pi->bigM, pi->x[i].n, pi->x[i].c);
-       fprintf(out, ";\n\n");
-
-       /* constraints for former objective function */
-       for (i=0; i<pi->x_dim; ++i)     {
-               for (o=0; o<pi->x_dim; ++o) {
-                       int Qio = pi->Q[i*pi->x_dim + o];
-                       if (Qio) {
-                               if (Qio == 1)
-                                       fprintf(out, "+x%d_%d ", pi->x[o].n, pi->x[o].c);
-                               else if(Qio == -1)
-                                       fprintf(out, "-x%d_%d ", pi->x[o].n, pi->x[o].c);
-                               else
-                                       fprintf(out, "%+dx%d_%d ", Qio, pi->x[o].n, pi->x[o].c);
-                       }
-               }
-               fprintf(out, "-y%d_%d -s%d_%d +%d= 0;\n", pi->x[i].n, pi->x[i].c, pi->x[i].n, pi->x[i].c, pi->bigM);
-       }
-       fprintf(out, "\n\n");
-
-       /* constraints for (special) complementary condition */
-       for (i=0; i<pi->x_dim; ++i)
-               fprintf(out, "y%d_%d <= %d - %dx%d_%d;\n", pi->x[i].n, pi->x[i].c, 2*pi->bigM, 2*pi->bigM, pi->x[i].n, pi->x[i].c);
-       fprintf(out, "\n\n");
-
-       pi_dump_lp_common_constraints(pi, out);
-       fclose(out);
-}
-#endif
-
-#ifdef DUMP_LPP
-/**
- * Dumps the problem instance as a MILP. The original problem is transformed into:
- * min f = es
- * udN:  Q'x -y -s = 0
- *       Ax  = e
- *       Bx <= e
- *        y <= M(e-x)
- *        x \in N   y, s >= 0
- *
- * with Q' = (q'_ij) := q_ij - minQij
- * and M >= max sum Q'ij * x_j
- *           i   j
- */
-static void pi_dump_lp_pos(problem_instance_t *pi) {
-       int i, o;
-       FILE *out = ffopen(pi->name, "lpp", "wt");
-
-       DBG((dbgphi, LEVEL_1, "Dumping lp_pos...\n"));
-       /* Norm the Matrix: Qij >=0 and \exists i,j Qij=0 */
-       for (i=0; i<pi->x_dim; ++i)
-               for (o=0; o<pi->x_dim; ++o)
-                       pi->Q[i*pi->x_dim + o] -= pi->minQij;
-       /* now Q' is stored in Q */
-
-       /* calc the big M for Q'
-        * maxQ'ij = maxQij-minQij
-        * #nodes = A_dim
-        * So max sum Q'ij * x_j <= A_dim * maxQ'ij
-        *     i   j
-        */
-       pi->bigM = pi->A_dim * (pi->maxQij - pi->minQij);
-       DBG((dbgphi, LEVEL_2, "BigM = %d\n", pi->bigM));
-
-       /* clac the correction term for the obj func
-        * xQx = xQ'x + minQij * k^2
-        * where k, in general, is the knapsack size of wx = k.
-        * Here w=1 and so 1x = #nodes = A_dim
-        */
-       pi->correction = pi->minQij * pi->A_dim * pi->A_dim;
-       DBG((dbgphi, LEVEL_2, "Correction = %d\n", pi->correction));
-
-       /* generate objective function */
-       fprintf(out, "min: ");
-       for (i=0; i<pi->x_dim; ++i)
-               fprintf(out, "+s%d_%d ", pi->x[i].n, pi->x[i].c);
-       fprintf(out, "+ correction\n");
-       fprintf(out, "correction = %d ", pi->correction);
-       fprintf(out, ";\n\n");
-
-       /* constraints for former objective function */
-       for (i=0; i<pi->x_dim; ++i)     {
-               for (o=0; o<pi->x_dim; ++o) {
-                       int Qio = pi->Q[i*pi->x_dim + o];
-                       if (Qio) {
-                               if (Qio != 1)
-                                       fprintf(out, "+%d", Qio);
-                               fprintf(out, "+x%d_%d ", pi->x[o].n, pi->x[o].c);
-                       }
-               }
-               fprintf(out, "-y%d_%d -s%d_%d = 0;\n", pi->x[i].n, pi->x[i].c, pi->x[i].n, pi->x[i].c);
-       }
-       fprintf(out, "\n\n");
-
-       /* constraints for (special) complementary condition */
-       for (i=0; i<pi->x_dim; ++i)
-               fprintf(out, "y%d_%d<=%d-%dx%d_%d;\n", pi->x[i].n, pi->x[i].c, pi->bigM, pi->bigM, pi->x[i].n, pi->x[i].c);
-       fprintf(out, "\n\n");
-
-       pi_dump_lp_common_constraints(pi, out);
-       fclose(out);
-}
-#endif
-
-#ifdef DO_SOLVE
-/**
- * Invoke an external solver
- */
-static void pi_solve_ilp(problem_instance_t *pi) {
-       FILE *out;
-       char buf[1024];
-
-       /* write command file for CPLEX */
-       out = ffopen(pi->name, "cmd", "wt");
-       fprintf(out, "read %s.mps\n", pi->name);
-       fprintf(out, "read %s.mst\n", pi->name);
-       fprintf(out, "set mip strategy mipstart 1\n");
-       fprintf(out, "optimize\n");
-       fprintf(out, "set logfile %s.sol\n", pi->name);
-       fprintf(out, "display solution variables 1-%d\n", pi->x_dim);
-       fprintf(out, "set logfile cplex.log\n");
-       fprintf(out, "quit\n");
-       fclose(out);
-
-       snprintf(buf, sizeof(buf), "scp %s.mps %s.mst %s.cmd %s:", pi->name, pi->name, pi->name, SSH_USER_HOST);
-       system(buf);
-       snprintf(buf, sizeof(buf), "ssh %s \"./cplex90 < %s.cmd\"", SSH_USER_HOST, pi->name);
-       system(buf);
-       snprintf(buf, sizeof(buf), "scp %s:%s.sol .", SSH_USER_HOST, pi->name);
-       system(buf);
-}
-
-/**
- * Sets the colors of irns according to the values of variables found in the
- * output file of the solver.
- */
-static void pi_apply_solution(problem_instance_t *pi) {
-       FILE *in = ffopen(pi->name, "sol", "rt");
-
-       DBG((dbgphi, LEVEL_1, "Applying solution...\n"));
-       while (!feof(in)) {
-               char buf[1024];
-               int num = -1, col = -1, val = -1;
-               if (fscanf(in, "x%d_%d %d.%s\n", &num, &col, &val, buf) != 3) {
-                       while(fscanf(in, "%1020s\n", buf) != 1);
-                       continue;
-               }
-               if (val == 1) {
-                       DBG((dbgphi, LEVEL_1, "x%d_%d = %d\n", num, col, val));
-                       set_irn_color(get_irn_for_graph_nr(pi->irg, num), col);
-               }
-       }
-       fclose(in);
-}
-#endif /* DO_SOLVE */
-
-#ifdef DELETE_FILES
-static void pi_delete_files(problem_instance_t *pi) {
-       char buf[1024];
-       int end = snprintf(buf, sizeof(buf), "%s", pi->name);
-#ifdef DUMP_MATRICES
-       snprintf(buf+end, sizeof(buf)-end, ".matrix");
-       remove(buf);
-#endif
-#ifdef DUMP_MPS
-       snprintf(buf+end, sizeof(buf)-end, ".mps");
-       remove(buf);
-       snprintf(buf+end, sizeof(buf)-end, ".mst");
-       remove(buf);
-       snprintf(buf+end, sizeof(buf)-end, ".cmd");
-       remove(buf);
-#endif
-#ifdef DUMP_LPO
-       snprintf(buf+end, sizeof(buf)-end, ".lpo");
-       remove(buf);
-#endif
-#ifdef DUMP_LPP
-       snprintf(buf+end, sizeof(buf)-end, ".lpp");
-       remove(buf);
-#endif
-}
-#endif
-
-/**
- * Let N be minimal so that the copy-minimization-problem resticted to
- * N possible colors has the same result as the original copy-min-prob with
- * MAX_COLORS possible colors.
- * It is assumed (not proven) that this is true, if for each phi and phi-arg
- * an extra register would be available. Constrained registers count an additinal
- * register too.
- * TODO Prove the above.
- *
- * This function returns M in env, where N <= M <= MAX_COLROS
- */
-static void pi_colors_upper_bound(ir_node *block, void *env) {
-       int *res = env;
-       int i, max, max_pressure, special_cnt;
-       if (*res == MAX_COLORS)
-               return;
-
-       /* get maximal register pressure */
-       {
-               struct list_head *head = &get_ra_block_info(block)->border_head;
-               border_t *b;
-               max_pressure = 0;
-               list_for_each_entry(border_t, b, head, list)
-                       if (b->pressure > max_pressure) {
-                               max_pressure = b->pressure;
-                       }
-       }
-
-       /* count special nodes */
-       special_cnt = 0;
-       for (i = 0, max = get_irn_n_outs(block); i < max; ++i) {
-               ir_node *n = get_irn_out(block, i);
-               if (get_nodes_block(n) != block)
-                       continue;
-               if (is_Phi(n) || is_phi_operand(n) || is_constrained(n))
-                       special_cnt++;
-       }
-
-       /* new max? */
-       if (*res < max_pressure + special_cnt)
-               *res = max_pressure + special_cnt;
-       if (*res > MAX_COLORS)
-               *res = MAX_COLORS;
-}
-
-/**
- * Generate the initial problem matrices and vectors.
- */
-static problem_instance_t *new_pi(ir_graph *irg, pset *all_phi_nodes) {
-       int max_needed_cols;
-       problem_instance_t *pi = calloc(1, sizeof(problem_instance_t));
-       pi->irg = irg;
-       pi->name =      get_entity_name(get_irg_entity(irg));
-       pi->bigM = 1;
-       pi->minQij = MIN_Q_INIT;
-       pi->maxQij = MAX_Q_INIT;
-       obstack_init(&pi->ob);
-
-       DBG((dbgphi, LEVEL_1, "Generating new instance...\n"));
-       pi->num2pos = new_set(pi_num2pos_cmp, 128);
-
-       //TODO move pi_colors_upper_bound in "super-class" to fix issue with
-       //invalid mst-values
-       /* get max_needed_cols */
-       max_needed_cols = 0;
-       dom_tree_walk_irg(irg, pi_colors_upper_bound, NULL, &max_needed_cols);
-       //TODO remove
-       max_needed_cols = MAX_COLORS;
-       DBG((dbgphi, LEVEL_1, "max_needed_cols: %d\n", max_needed_cols));
-
-       /* Vector x
-        * one entry per node and possible color */
-       {
-               x_vec_t xx;
-               for (xx.n=0; xx.n<get_graph_node_count(irg); ++xx.n) {
-                       ir_node *irn = get_irn_for_graph_nr(irg, xx.n);
-
-                       if (!is_allocatable_irn(irn))
-                               continue;
-                       DBG((dbgphi, LEVEL_2, "pi->num2pos %4d --> %4d\n", xx.n, pi->x_dim));
-                       pi_set_first_pos(pi, xx.n, pi->x_dim);
-
-                       pi->A_dim++;                    /* one knapsack constraint for each node */
-                       for (xx.c=0; xx.c<max_needed_cols; ++xx.c) {
-                               if (!is_possible_color(irn, xx.c))
-                                       continue;
-                               DBG((dbgphi, LEVEL_2, "Adding %n %d\n", irn, xx.c));
-                               obstack_grow(&pi->ob, &xx, sizeof(xx));
-                               pi->x_dim++;            /* one x variable for each node and color */
-                       }
-               }
-               pi->x = obstack_finish(&pi->ob);
-       }
-
-       /* Matrix Q
-        * weights for the 'same-color-optimization' target */
-       {
-               ir_node *phi, *arg;
-               pi->Q = calloc(pi->x_dim*pi->x_dim, sizeof(pi->Q[0]));
-               for (phi = pset_first(all_phi_nodes); phi; phi = pset_next(all_phi_nodes)) {
-                       unsigned phipos, argpos;
-                       int phinr, argnr;
-                       int i, max;
-
-                       for (i = 0, max = get_irn_arity(phi); i < max; ++i) {
-                               int weight;
-                               arg = get_irn_n(phi, i);
-                               if (phi_ops_interfere(phi, arg))
-                                       continue;
-                               phinr = get_irn_graph_nr(phi);
-                               argnr = get_irn_graph_nr(arg);
-                               phipos = pi_get_first_pos(pi, phinr);
-                               argpos = pi_get_first_pos(pi, argnr);
-                               weight = -get_weight(phi, arg);
-
-                               DBG((dbgphi, LEVEL_2, "Q[%n, %n] := %d\n", phi, arg, weight));
-                               /* for all colors phi and arg have in common, set the weight for
-                                * this pair in the objective function matrix Q */
-                               while (phipos < pi->x_dim && argpos < pi->x_dim &&
-                                               pi->x[phipos].n == phinr && pi->x[argpos].n == argnr) {
-                                       if (pi->x[phipos].c < pi->x[argpos].c)
-                                               ++phipos;
-                                       else if (pi->x[phipos].c > pi->x[argpos].c)
-                                               ++argpos;
-                                       else {
-                                               pi->Q[(phipos++)*pi->x_dim + argpos++] = weight;
-
-                                               if (weight < pi->minQij) {
-                                                       DBG((dbgphi, LEVEL_2, "minQij = %d\n", weight));
-                                                       pi->minQij = weight;
-                                               }
-                                               if (weight > pi->maxQij) {
-                                                       DBG((dbgphi, LEVEL_2, "maxQij = %d\n", weight));
-                                                       pi->maxQij = weight;
-                                               }
-                                       }
-                               }
-                       }
-               }
-       }
-
-       /* Matrix A
-        * knapsack constraint for each node */
-       {
-               int row = 0, col = 0;
-               pi->A = calloc(pi->A_dim*pi->x_dim, sizeof(pi->A[0]));
-               while (col < pi->x_dim) {
-                       int curr_n = pi->x[col].n;
-                       while (col < pi->x_dim && pi->x[col].n == curr_n) {
-                               DBG((dbgphi, LEVEL_2, "A[%d, %d] := %d\n", row, col, 1));
-                               pi->A[row*pi->x_dim + col++] = 1;
-                       }
-                       ++row;
-               }
-               assert(row == pi->A_dim);
-       }
-
-       /* Matrix B
-        * interference constraints using exactly those cliques not contained in others. */
-       {
-               int col;
-               pi->B_dim = set_count(be_ra_get_ifg(irg))*max_needed_cols;  /* this is an upper bound, see realloc below */
-               pi->B = calloc(pi->B_dim*pi->x_dim, sizeof(pi->B[0]));
-
-               for (col = 0; col < max_needed_cols; ++col) {
-                       pi->curr_col = col;
-                       dom_tree_walk_irg(irg, pi_clique_finder, NULL, pi);
-               }
-
-               pi->B_dim = pi->curr_row;
-               pi->B = realloc(pi->B, pi->B_dim*pi->x_dim*sizeof(pi->B[0]));
-       }
-
-       return pi;
-}
-
-/**
- * clean the problem instance
- */
-static void free_pi(problem_instance_t *pi) {
-       free(pi->Q);
-       free(pi->A);
-       free(pi->B);
-       del_set(pi->num2pos);
-       obstack_free(&pi->ob, NULL);
-       free(pi);
-}
-
-void be_phi_coalesce_ilp(ir_graph *irg, pset *all_phi_nodes) {
-       problem_instance_t *pi = new_pi(irg, all_phi_nodes);
-
-#ifdef DUMP_MATRICES
-       pi_dump_matrices(pi);
-#endif
-
-#ifdef DUMP_MPS
-       pi_dump_mps(pi);
-#endif
-
-#ifdef DUMP_LPO
-       pi_dump_lp_org(pi);
-#endif
-
-#ifdef DUMP_LPP
-       pi_dump_lp_pos(pi);
-#endif
-
-#ifdef DO_SOLVE
-       pi_solve_ilp(pi);
-       pi_apply_solution(pi);
-#endif
-
-#ifdef DELETE_FILES
-       pi_delete_files(pi);
-#endif
-
-       free_pi(pi);
-}
-
-void be_phi_coal_ilp_init(void) {
-       dbgphi = firm_dbg_register("ir.be.phicoalilp");
-       firm_dbg_set_mask(dbgphi, DEBUG_LVL);
-}
diff --git a/ir/be/bephicoalilp_t.h b/ir/be/bephicoalilp_t.h
deleted file mode 100644 (file)
index a6567e5..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/**
- * @author Daniel Grund
- * @date 11.03.2005
- */
-
-#ifndef _BEPHICOALILP_T_H
-#define _BEPHICOALILP_T_H
-
-#include "irgraph.h"
-#include "pset.h"
-
-void be_phi_coal_ilp_init(void);
-void be_phi_coalesce_ilp(ir_graph *irg, pset *all_phi_nodes);
-
-#endif
diff --git a/ir/be/bephiopt.c b/ir/be/bephiopt.c
deleted file mode 100644 (file)
index 8201302..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-/**
- * @author Daniel Grund
- * @date 04.01.2005
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "pset.h"
-#include "obst.h"
-#include "irgraph.h"
-#include "irnode.h"
-#include "irgwalk.h"
-#include "irouts.h"
-#include "irdom.h"
-
-#include "beutil.h"
-#include "benumb_t.h"
-#include "bera_t.h"
-#include "bephiopt.h"
-#include "phiclass_t.h"
-#include "bephicoal_t.h"
-#include "bephicoalilp_t.h"
-#include "phistat.h"
-
-#define DO_HEURISTIC
-#undef DO_OPTIMAL
-
-#define DEBUG_LVL SET_LEVEL_1
-
-/** checks if two interfering nodes have the same color */
-#define CHECK_RESULTS
-/** counts the copies needed before and after optimization */
-#define COUNT_COPY_SAVINGS
-/** dumps 2 allocated graphs; before and after opt. */
-#undef DUMP_OPT_DIFF
-
-#undef DO_PHI_STATISTICS
-#define DUMP_IRG_PHI_STAT
-#define DUMP_DIR_PHI_STAT
-#define DUMP_ALL_PHI_STAT
-
-#define PHI_STAT_FILE "dir.phistat"
-#define ENV_PHI_STAT "PHI_STAT"
-
-static firm_dbg_module_t *dbgphi = NULL;
-
-typedef struct _copies_t {
-       int lb, ub;
-       int count[3]; /* before, after heuristics, after optimality */
-} copies_t;
-
-
-static void phi_node_walker(ir_node *node, void *env) {
-       if (is_Phi(node) && mode_is_datab(get_irn_mode(node)))
-               pset_insert_ptr((pset *)env, node);
-}
-
-
-static void node_collector(ir_node *node, void *env) {
-       struct obstack *obst = env;
-       if (!is_Block(node) && is_allocatable_irn(node))
-               obstack_ptr_grow(obst, node);
-}
-
-
-static void check_result(ir_graph *irg) {
-       struct obstack ob;
-       ir_node **nodes, *n1, *n2;
-       int i, o;
-
-       obstack_init(&ob);
-       irg_walk_graph(irg, node_collector, NULL, &ob);
-       obstack_ptr_grow(&ob, NULL);
-       nodes = (ir_node **) obstack_finish(&ob);
-       for (i = 0, n1 = nodes[i]; n1; n1 = nodes[++i]) {
-               assert(! (is_allocatable_irn(n1) && get_irn_color(n1) == NO_COLOR));
-               for (o = i+1, n2 = nodes[o]; n2; n2 = nodes[++o])
-                       if (phi_ops_interfere(n1, n2) && get_irn_color(n1) == get_irn_color(n2)) {
-                               DBG((dbgphi, 1, "Ouch!\n   %n[%d]in %n\n   %n[%d] in %n\n", n1, get_irn_graph_nr(n1), get_nodes_block(n1), n2, get_irn_graph_nr(n2), get_nodes_block(n2)));
-                               assert(0 && "Interfering values have the same color!");
-                       }
-       }
-
-       obstack_free(&ob, NULL);
-}
-
-
-/**
- * Init the copies struct lower and upper bound
- */
-static void init_copies(copies_t *c, pset *all_phi_nodes) {
-       ir_node *phi;
-
-       c->count[0] = c->count[1] = c->count[2] = -1;
-       c->ub = c->lb = 0;
-
-       for (phi = pset_first(all_phi_nodes); phi; phi = pset_next(all_phi_nodes)) {
-               /* upper bound: each argument of a phi node is a potential copy */
-               int i, max = get_irn_arity(phi);
-               c->ub += max;
-               /* lower bound: at least all interfering pairs */
-               for (i = 0; i < max; ++i) {
-                       ir_node *arg = get_irn_n(phi, i);
-                       if (phi_ops_interfere(phi, arg))
-                               c->lb++;
-               }
-       }
-}
-
-
-/**
- * Count the copies needed with current coloring
- */
-static void count_copies(copies_t *c, pset *all_phi_nodes, int stage) {
-       int i, max, phi_color;
-       ir_node *phi;
-
-       c->count[stage] = 0;
-
-       for (phi = pset_first(all_phi_nodes); phi; phi = pset_next(all_phi_nodes)) {
-               phi_color = get_irn_color(phi);
-               for (i = 0, max = get_irn_arity(phi); i < max; ++i) {
-                       ir_node *arg = get_irn_n(phi, i);
-                       if (phi_color != get_irn_color(arg)) {
-                               c->count[stage]++;
-                               DBG((dbgphi, LEVEL_2, "Copy: %n %n\n", phi, arg));
-                       }
-               }
-       }
-}
-
-
-void be_phi_opt(ir_graph* irg) {
-       pset *all_phi_nodes, *all_phi_classes;
-       copies_t *copies;
-
-       DBG((dbgphi, 1, "\n\n=======================> IRG: %s\n\n", get_entity_name(get_irg_entity(irg))));
-
-
-       /* get all phi nodes */
-       DBG((dbgphi, 1, "-----------------------> Collecting phi nodes <-----------------------\n"));
-       all_phi_nodes = pset_new_ptr(64);
-       irg_walk_graph(irg, phi_node_walker, NULL, all_phi_nodes);
-
-
-       /* get all phi congruence classes */
-       DBG((dbgphi, 1, "-----------------------> Collecting phi classes <---------------------\n"));
-       all_phi_classes = phi_class_compute_by_phis(all_phi_nodes);
-
-
-       /* do some statistics */
-#ifdef DO_PHI_STATISTICS
-       DBG((dbgphi, 1, "-----------------------> Collecting phi stats <-----------------------\n"));
-       phi_stat_reset();
-       phi_stat_collect(irg, all_phi_nodes, all_phi_classes);
-#ifdef DUMP_IRG_PHI_STAT
-               char buf[1024];
-               snprintf(buf, sizeof(buf), "%s.phistat", get_entity_name(get_irg_entity(irg)));
-               /*phi_stat_dump(buf);*/
-               phi_stat_dump_pretty(buf);
-#endif
-#ifdef DUMP_DIR_PHI_STAT
-               phi_stat_update(PHI_STAT_FILE);
-#endif
-#ifdef DUMP_ALL_PHI_STAT
-               phi_stat_update(getenv(ENV_PHI_STAT));
-#endif
-#endif
-
-
-       /* try to coalesce the colors of each phi class */
-       DBG((dbgphi, 1, "-----------------------> Coalescing <---------------------------------\n"));
-       compute_outs(irg);
-       compute_doms(irg);
-
-
-#ifdef DUMP_OPT_DIFF
-       dump_allocated_irg(irg, "-before");
-#endif
-#ifdef CHECK_RESULTS
-       check_result(irg);
-#endif
-#ifdef COUNT_COPY_SAVINGS
-       copies = malloc(sizeof(*copies));
-       init_copies(copies, all_phi_nodes);
-       DBG((dbgphi, 0, "Copy bounds  : %3d < . < %3d\n", copies->lb, copies->ub));
-       count_copies(copies, all_phi_nodes, 0);
-#endif
-
-
-
-#ifdef DO_HEURISTIC
-       be_phi_coalesce(all_phi_classes);
-#ifdef DUMP_OPT_DIFF
-       dump_allocated_irg(irg, "-heur");
-#endif
-#ifdef CHECK_RESULTS
-       check_result(irg);
-#endif
-#ifdef COUNT_COPY_SAVINGS
-       count_copies(copies, all_phi_nodes, 1);
-#endif
-#endif /* DO_HEURISTIC */
-
-
-       if (copies->count[1] == -1 || copies->count[1] > copies->lb) {
-#ifdef DO_OPTIMAL
-               be_phi_coalesce_ilp(irg, all_phi_nodes);
-#ifdef DUMP_OPT_DIFF
-               dump_allocated_irg(irg, "-opt");
-#endif
-#ifdef CHECK_RESULTS
-               check_result(irg);
-#endif
-#ifdef COUNT_COPY_SAVINGS
-               count_copies(copies, all_phi_nodes, 2);
-#endif
-#endif /* DO_OPTIMAL */
-       }
-#ifdef COUNT_COPY_SAVINGS
-       DBG((dbgphi, 0, "Copies before/heur/opt: %3d / %3d / %3d\n", copies->count[0], copies->count[1], copies->count[2]));
-#endif
-       free_dom_and_peace(irg);
-}
-
-
-void be_phi_opt_init(void) {
-       dbgphi = firm_dbg_register("ir.be.phiopt");
-       firm_dbg_set_mask(dbgphi, DEBUG_LVL);
-
-       phi_class_init();
-#ifdef DO_HEURISTIC
-       be_phi_coal_init();
-#endif
-#ifdef DO_OPTIMAL
-       be_phi_coal_ilp_init();
-#endif
-}
diff --git a/ir/be/bephiopt.h b/ir/be/bephiopt.h
deleted file mode 100644 (file)
index 40ef637..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-/**
- * @author Daniel Grund
- * @date 04.01.2005
- */
-
-#ifndef _BEPHIOPT_H
-#define _BEPHIOPT_H
-
-#include "debug.h"
-#include "irgraph.h"
-
-void be_phi_opt_init(void);
-void be_phi_opt(ir_graph* irg);
-
-#endif