bearch: Disallow passing Projs to get_irn_ops().
[libfirm] / ir / be / becopyilp2.c
index e9de21a..455fa1a 100644 (file)
@@ -1,20 +1,6 @@
 /*
- * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
- *
  * This file is part of libFirm.
- *
- * This file may be distributed and/or modified under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * Licensees holding valid libFirm Professional Edition licenses may use
- * this file in accordance with the libFirm Commercial License.
- * Agreement provided with the Software.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE.
+ * Copyright (C) 2012 University of Karlsruhe.
  */
 
 /**
@@ -22,7 +8,6 @@
  * @brief       ILP based copy minimization.
  * @author      Daniel Grund
  * @date        28.02.2006
- * @version     $Id$
  *
  * ILP formalization using G=(V, E, Q):
  *  - 2 class of variables: coloring vars x_ic   and   equal color vars y_ij
  */
 #include "config.h"
 
-#ifdef WITH_ILP
-
+#include "be_t.h"
+#include "beintlive_t.h"
+#include "beirg.h"
 #include "bitset.h"
+#include "error.h"
 #include "raw_bitset.h"
 #include "pdeq.h"
 
-#include "irtools.h"
+#include "util.h"
 #include "irgwalk.h"
 #include "becopyilp_t.h"
 #include "beifg.h"
 #include "besched.h"
 #include "bemodule.h"
 
-#define DEBUG_LVL 1
+DEBUG_ONLY(static firm_dbg_module_t *dbg;)
 
 typedef struct local_env_t {
-       double time_limit;
-       int first_x_var, last_x_var;
-       int n_colors;
-       bitset_t *normal_colors;
-       pmap *nr_2_irn;
-       DEBUG_ONLY(firm_dbg_module_t *dbg;)
+       int             first_x_var;
+       int             last_x_var;
+       const unsigned *allocatable_colors;
 } local_env_t;
 
-static void build_coloring_cstr(ilp_env_t *ienv)
+static unsigned check_alignment_constraints(ir_node *node)
 {
-       be_ifg_t *ifg     = ienv->co->cenv->ifg;
-       nodes_iter_t iter;
-       bitset_t *colors;
-       ir_node *irn;
-       char buf[16];
+       const arch_register_req_t *req = arch_get_irn_register_req(node);
+       // For larger than 1 variables, support only aligned constraints
+       assert((arch_register_req_is(req, aligned) || req->width == 1) && "Unaligned large (width > 1) variables not supported");
+       return arch_register_req_is(req, aligned) && req->width > 1;
+}
 
-       colors = bitset_alloca(arch_register_class_n_regs(ienv->co->cls));
+static void make_color_var_name(char *buf, size_t buf_size,
+                                const ir_node *node, unsigned color)
+{
+       unsigned node_idx = get_irn_idx(node);
+       snprintf(buf, buf_size, "x_%u_%u", node_idx, color);
+}
 
-       be_ifg_foreach_node(ifg, &iter, irn)
-               if (!sr_is_removed(ienv->sr, irn)) {
-                       unsigned col;
-                       int cst_idx;
-                       const arch_register_req_t *req;
-                       int curr_node_color = get_irn_col(irn);
-                       int node_nr = (int)get_irn_idx(irn);
-                       local_env_t *lenv = ienv->env;
+static void build_coloring_cstr(ilp_env_t *ienv)
+{
+       local_env_t    *lenv   = (local_env_t*)ienv->env;
+       be_ifg_t       *ifg    = ienv->co->cenv->ifg;
+       unsigned        n_regs = arch_register_class_n_regs(ienv->co->cls);
+       const unsigned *allocatable_colors = lenv->allocatable_colors;
+       char            buf[32];
+
+       unsigned *const colors = rbitset_alloca(n_regs);
+       be_ifg_foreach_node(ifg, irn) {
+               const arch_register_req_t *req;
+               unsigned                   col;
+               int                        cst_idx;
+               unsigned                   curr_node_color;
+               unsigned                   has_alignment_cstr;
+
+               if (sr_is_removed(ienv, irn))
+                       continue;
 
-                       pmap_insert(lenv->nr_2_irn, INT_TO_PTR(node_nr), irn);
+               has_alignment_cstr = check_alignment_constraints(irn);
 
-                       req = arch_get_register_req_out(irn);
+               req = arch_get_irn_register_req(irn);
 
-                       bitset_clear_all(colors);
+               /* get assignable colors */
+               if (arch_register_req_is(req, limited)) {
+                       rbitset_copy(colors, req->limited, n_regs);
+               } else {
+                       rbitset_copy(colors, allocatable_colors, n_regs);
+               }
 
-                       /* get assignable colors */
-                       if (arch_register_req_is(req, limited)) {
-                               rbitset_copy_to_bitset(req->limited, colors);
-                       } else {
-                               bitset_copy(colors, lenv->normal_colors);
-                       }
+               /* add the coloring constraint */
+               cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_equal, 1.0);
 
-                       /* add the coloring constraint */
-                       cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_equal, 1.0);
+               curr_node_color = get_irn_col(irn);
+               for (col = 0; col < n_regs; ++col) {
+                       int    var_idx;
+                       double val;
+                       if (!rbitset_is_set(colors, col)
+                               || (has_alignment_cstr && ((col % req->width) != 0)))
+                               continue;
 
-                       bitset_foreach(colors, col) {
-                               int var_idx = lpp_add_var(ienv->lp, name_cdd(buf, 'x', node_nr, col), lpp_binary, 0.0);
-                               lpp_set_start_value(ienv->lp, var_idx, (col == (unsigned) curr_node_color) ? 1.0 : 0.0);
-                               lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1);
+                       make_color_var_name(buf, sizeof(buf), irn, col);
+                       var_idx = lpp_add_var(ienv->lp, buf, lpp_binary, 0.0);
+                       lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1);
 
-                               lenv->last_x_var = var_idx;
-                               if (lenv->first_x_var == -1)
-                                       lenv->first_x_var = var_idx;
-                       }
+                       val = (col == curr_node_color) ? 1.0 : 0.0;
+                       lpp_set_start_value(ienv->lp, var_idx, val);
 
-                       /* add register constraint constraints */
-                       bitset_foreach_clear(colors, col) {
-                               int cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_equal, 0.0);
-                               int var_idx = lpp_add_var(ienv->lp, name_cdd(buf, 'x', node_nr, col), lpp_binary, 0.0);
-                               lpp_set_start_value(ienv->lp, var_idx, 0.0);
-                               lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1);
+                       lenv->last_x_var = var_idx;
+                       if (lenv->first_x_var == -1)
+                               lenv->first_x_var = var_idx;
+               }
 
-                               lenv->last_x_var = var_idx;
-                       }
+               /* add register constraint constraints */
+               for (col = 0; col < n_regs; ++col) {
+                       int cst_idx;
+                       int var_idx;
+                       if (rbitset_is_set(colors, col)
+                               // for aligned variable, we set the unaligned part to 0
+                               && (!has_alignment_cstr || ((col % req->width) == 0)))
+                               continue;
+
+                       make_color_var_name(buf, sizeof(buf), irn, col);
+                       cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_equal, 0.0);
+                       var_idx = lpp_add_var(ienv->lp, buf, lpp_binary, 0.0);
+                       lpp_set_start_value(ienv->lp, var_idx, 0.0);
+                       lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1);
+
+                       lenv->last_x_var = var_idx;
                }
+       }
 }
 
 static void build_interference_cstr(ilp_env_t *ienv)
 {
-       lpp_t       *lpp      = ienv->lp;
-       local_env_t *lenv     = ienv->env;
-       be_ifg_t    *ifg      = ienv->co->cenv->ifg;
-       int          n_colors = lenv->n_colors;
+       lpp_t          *lpp      = ienv->lp;
+       local_env_t    *lenv     = (local_env_t*)ienv->env;
+       be_ifg_t       *ifg      = ienv->co->cenv->ifg;
+       unsigned        n_colors = arch_register_class_n_regs(ienv->co->cls);
+       ir_node       **clique   = ALLOCAN(ir_node*, n_colors);
+       const unsigned *allocatable_colors = lenv->allocatable_colors;
        cliques_iter_t iter;
-       ir_node    **clique   = ALLOCAN(ir_node*, n_colors);
-       int          size;
-       int          col;
-       int          i;
-
-       char buf[16];
+       int            size;
+       unsigned       col;
+       int            i;
 
        /* for each maximal clique */
        be_ifg_foreach_clique(ifg, &iter, clique, &size) {
-               int realsize = 0;
+               unsigned realsize = 0;
 
-               for (i=0; i<size; ++i)
-                       if (!sr_is_removed(ienv->sr, clique[i]))
+               for (i=0; i<size; ++i) {
+                       if (!sr_is_removed(ienv, clique[i]))
                                ++realsize;
+               }
 
                if (realsize < 2)
                        continue;
 
                /* for all colors */
                for (col=0; col<n_colors; ++col) {
-                       int cst_idx = lpp_add_cst(lpp, NULL, lpp_less, 1.0);
+                       int cst_idx;
+                       if (!rbitset_is_set(allocatable_colors, col))
+                               continue;
+
+                       cst_idx = lpp_add_cst(lpp, NULL, lpp_less_equal, 1.0);
 
                        /* for each member of this clique */
                        for (i=0; i<size; ++i) {
                                ir_node *irn = clique[i];
-
-                               if (!sr_is_removed(ienv->sr, irn)) {
-                                       int var_idx = lpp_get_var_idx(lpp, name_cdd(buf, 'x', (int)get_irn_idx(irn), col));
-                                       lpp_set_factor_fast(lpp, cst_idx, var_idx, 1);
+                               char     buf[32];
+                               int      var_idx;
+                               unsigned aligment_offset = 0;
+
+                               if (sr_is_removed(ienv, irn))
+                                       continue;
+
+                               // Use the first part of the large registers for all
+                               // interference, since it is the only colorable one.
+                               if (check_alignment_constraints(irn)) {
+                                       const arch_register_req_t *req
+                                               = arch_get_irn_register_req(irn);
+                                       aligment_offset = col % req->width;
                                }
+
+                               make_color_var_name(buf, sizeof(buf), irn,
+                                                                       col - aligment_offset);
+                               var_idx = lpp_get_var_idx(lpp, buf);
+                               lpp_set_factor_fast(lpp, cst_idx, var_idx, 1);
                        }
                }
        }
 }
 
+static void make_affinity_var_name(char *buf, size_t buf_size,
+                                   const ir_node *node1, const ir_node *node2)
+{
+       unsigned n1 = get_irn_idx(node1);
+       unsigned n2 = get_irn_idx(node2);
+       if (n1 < n2) {
+               snprintf(buf, buf_size, "y_%u_%u", n1, n2);
+       } else {
+               snprintf(buf, buf_size, "y_%u_%u", n2, n1);
+       }
+}
+
 
 /**
  * TODO: Remove the dependency of the opt-units data structure
@@ -177,35 +222,38 @@ static void build_interference_cstr(ilp_env_t *ienv)
  */
 static void build_affinity_cstr(ilp_env_t *ienv)
 {
-       local_env_t *lenv = ienv->env;
-       int n_colors      = lenv->n_colors;
-       unit_t *curr;
+       unsigned  n_colors = arch_register_class_n_regs(ienv->co->cls);
 
        /* for all optimization units */
        list_for_each_entry(unit_t, curr, &ienv->co->units, units) {
-               ir_node *root, *arg;
-               int root_nr, arg_nr, i, col, y_idx, root_idx, arg_idx;
-               char buf[16];
-               int root_col, arg_col;
-
-               root = curr->nodes[0];
-               root_nr = (int) get_irn_idx(root);
-               root_col = get_irn_col(root);
+               ir_node *root     = curr->nodes[0];
+               unsigned root_col = get_irn_col(root);
+               int      i;
 
                for (i = 1; i < curr->node_count; ++i) {
-                       arg = curr->nodes[i];
-                       arg_nr = (int) get_irn_idx(arg);
-                       arg_col = get_irn_col(arg);
+                       ir_node *arg     = curr->nodes[i];
+                       unsigned arg_col = get_irn_col(arg);
+                       double   val;
+                       char     buf[32];
+                       unsigned col;
+                       int      y_idx;
 
                        /* add a new affinity variable */
-                       y_idx = lpp_add_var(ienv->lp, name_cdd_sorted(buf, 'y', root_nr, arg_nr), lpp_binary, curr->costs[i]);
-                       lpp_set_start_value(ienv->lp, y_idx, (root_col==arg_col) ? 0.0 : 1.0);
+                       make_affinity_var_name(buf, sizeof(buf), arg, root);
+                       y_idx = lpp_add_var(ienv->lp, buf, lpp_binary, curr->costs[i]);
+                       val   = (root_col == arg_col) ? 0.0 : 1.0;
+                       lpp_set_start_value(ienv->lp, y_idx, val);
 
                        /* add constraints relating the affinity var to the color vars */
                        for (col=0; col<n_colors; ++col) {
-                               int cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_less, 0.0);
-                               root_idx = lpp_get_var_idx(ienv->lp, name_cdd(buf, 'x', root_nr, col));
-                               arg_idx  = lpp_get_var_idx(ienv->lp, name_cdd(buf, 'x', arg_nr,  col));
+                               int cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_less_equal, 0.0);
+                               int root_idx;
+                               int arg_idx;
+
+                               make_color_var_name(buf, sizeof(buf), root, col);
+                               root_idx = lpp_get_var_idx(ienv->lp, buf);
+                               make_color_var_name(buf, sizeof(buf), arg, col);
+                               arg_idx  = lpp_get_var_idx(ienv->lp, buf);
 
                                lpp_set_factor_fast(ienv->lp, cst_idx, root_idx,  1.0);
                                lpp_set_factor_fast(ienv->lp, cst_idx, arg_idx,  -1.0);
@@ -219,21 +267,22 @@ static void build_affinity_cstr(ilp_env_t *ienv)
  * Helping stuff for build_clique_star_cstr
  */
 typedef struct edge_t {
-       ir_node *n1, *n2;
+       ir_node *n1;
+       ir_node *n2;
 } edge_t;
 
 static int compare_edge_t(const void *k1, const void *k2, size_t size)
 {
-       const edge_t *e1 = k1;
-       const edge_t *e2 = k2;
+       const edge_t *e1 = (const edge_t*)k1;
+       const edge_t *e2 = (const edge_t*)k2;
        (void) size;
 
-       return ! (e1->n1 == e2->n1   &&   e1->n2 == e2->n2);
+       return ! (e1->n1 == e2->n1 && e1->n2 == e2->n2);
 }
 
 #define HASH_EDGE(e) (hash_irn((e)->n1) ^ hash_irn((e)->n2))
 
-static inline edge_t *add_edge(set *edges, ir_node *n1, ir_node *n2, int *counter)
+static inline edge_t *add_edge(set *edges, ir_node *n1, ir_node *n2, size_t *counter)
 {
        edge_t new_edge;
 
@@ -245,7 +294,7 @@ static inline edge_t *add_edge(set *edges, ir_node *n1, ir_node *n2, int *counte
                new_edge.n2 = n1;
        }
        (*counter)++;
-       return set_insert(edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge));
+       return set_insert(edge_t, edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge));
 }
 
 static inline edge_t *find_edge(set *edges, ir_node *n1, ir_node *n2)
@@ -259,10 +308,10 @@ static inline edge_t *find_edge(set *edges, ir_node *n1, ir_node *n2)
                new_edge.n1 = n2;
                new_edge.n2 = n1;
        }
-       return set_find(edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge));
+       return set_find(edge_t, edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge));
 }
 
-static inline void remove_edge(set *edges, ir_node *n1, ir_node *n2, int *counter)
+static inline void remove_edge(set *edges, ir_node *n1, ir_node *n2, size_t *counter)
 {
        edge_t new_edge, *e;
 
@@ -273,7 +322,7 @@ static inline void remove_edge(set *edges, ir_node *n1, ir_node *n2, int *counte
                new_edge.n1 = n2;
                new_edge.n2 = n1;
        }
-       e = set_find(edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge));
+       e = set_find(edge_t, edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge));
        if (e) {
                e->n1 = NULL;
                e->n2 = NULL;
@@ -281,7 +330,7 @@ static inline void remove_edge(set *edges, ir_node *n1, ir_node *n2, int *counte
        }
 }
 
-#define pset_foreach(pset, irn)  for (irn=pset_first(pset); irn; irn=pset_next(pset))
+#define pset_foreach(pset, irn) foreach_pset((pset), ir_node, (irn))
 
 /**
  * Search for an interference clique and an external node
@@ -290,16 +339,15 @@ static inline void remove_edge(set *edges, ir_node *n1, ir_node *n2, int *counte
  */
 static void build_clique_star_cstr(ilp_env_t *ienv)
 {
-       affinity_node_t *aff;
-
        /* for each node with affinity edges */
+       be_lv_t *const lv = be_get_irg_liveness(ienv->co->irg);
        co_gs_foreach_aff_node(ienv->co, aff) {
                struct obstack ob;
-               neighb_t *nbr;
                const ir_node *center = aff->irn;
                ir_node **nodes;
                set *edges;
-               int i, o, n_nodes, n_edges;
+               int i, o, n_nodes;
+               size_t n_edges;
 
                if (arch_irn_is_ignore(aff->irn))
                        continue;
@@ -315,24 +363,25 @@ static void build_clique_star_cstr(ilp_env_t *ienv)
                                ++n_nodes;
                        }
                }
-               nodes = obstack_finish(&ob);
+               nodes = (ir_node**)obstack_finish(&ob);
 
                /* get all interference edges between these */
                n_edges = 0;
-               for (i=0; i<n_nodes; ++i)
-                       for (o=0; o<i; ++o)
-                               if (be_ifg_connected(ienv->co->cenv->ifg, nodes[i], nodes[o]))
+               for (i=0; i<n_nodes; ++i) {
+                       for (o=0; o<i; ++o) {
+                               if (be_values_interfere(lv, nodes[i], nodes[o]))
                                        add_edge(edges, nodes[i], nodes[o], &n_edges);
+                       }
+               }
 
                /* cover all these interference edges with maximal cliques */
                while (n_edges) {
                        edge_t *e;
-                       pset *clique = pset_new_ptr(8);
-                       int growed;
+                       pset   *clique = pset_new_ptr(8);
+                       bool    growed;
 
                        /* get 2 starting nodes to form a clique */
-                       for (e=set_first(edges); !e->n1; e=set_next(edges))
-                               /*nothing*/ ;
+                       for (e = set_first(edge_t, edges); !e->n1; e = set_next(edge_t, edges)) {}
 
                        /* we could be stepped out of the loop before the set iterated to the end */
                        set_break(edges);
@@ -343,22 +392,22 @@ static void build_clique_star_cstr(ilp_env_t *ienv)
 
                        /* while the clique is growing */
                        do {
-                               growed = 0;
+                               growed = false;
 
                                /* search for a candidate to extend the clique */
                                for (i=0; i<n_nodes; ++i) {
-                                       ir_node *member, *cand = nodes[i];
-                                       int is_cand;
+                                       ir_node *cand = nodes[i];
+                                       bool     is_cand;
 
                                        /* if its already in the clique try the next */
                                        if (pset_find_ptr(clique, cand))
                                                continue;
 
                                        /* are there all necessary interferences? */
-                                       is_cand = 1;
+                                       is_cand = true;
                                        pset_foreach(clique, member) {
                                                if (!find_edge(edges, cand, member)) {
-                                                       is_cand = 0;
+                                                       is_cand = false;
                                                        pset_break(clique);
                                                        break;
                                                }
@@ -372,7 +421,7 @@ static void build_clique_star_cstr(ilp_env_t *ienv)
 
                                                /* insert into clique */
                                                pset_insert_ptr(clique, cand);
-                                               growed = 1;
+                                               growed = true;
                                                break;
                                        }
                                }
@@ -380,16 +429,15 @@ static void build_clique_star_cstr(ilp_env_t *ienv)
 
                        /* now the clique is maximal. Finally add the constraint */
                        {
-                               ir_node *member;
-                               int var_idx, cst_idx, center_nr, member_nr;
-                               char buf[16];
+                               int  var_idx;
+                               int  cst_idx;
+                               char buf[32];
 
-                               cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_greater, pset_count(clique)-1);
-                               center_nr = get_irn_idx(center);
+                               cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_greater_equal, pset_count(clique)-1);
 
                                pset_foreach(clique, member) {
-                                       member_nr = get_irn_idx(member);
-                                       var_idx = lpp_get_var_idx(ienv->lp, name_cdd_sorted(buf, 'y', center_nr, member_nr));
+                                       make_affinity_var_name(buf, sizeof(buf), center, member);
+                                       var_idx = lpp_get_var_idx(ienv->lp, buf);
                                        lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1.0);
                                }
                        }
@@ -402,14 +450,11 @@ static void build_clique_star_cstr(ilp_env_t *ienv)
        }
 }
 
-
 static void extend_path(ilp_env_t *ienv, pdeq *path, const ir_node *irn)
 {
-       be_ifg_t *ifg = ienv->co->cenv->ifg;
        int i, len;
        ir_node **curr_path;
        affinity_node_t *aff;
-       neighb_t *nbr;
 
        /* do not walk backwards or in circles */
        if (pdeq_contains(path, irn))
@@ -421,32 +466,30 @@ static void extend_path(ilp_env_t *ienv, pdeq *path, const ir_node *irn)
        /* insert the new irn */
        pdeq_putr(path, irn);
 
-
-
        /* check for forbidden interferences */
        len       = pdeq_len(path);
        curr_path = ALLOCAN(ir_node*, len);
        pdeq_copyl(path, (const void **)curr_path);
 
-       for (i=1; i<len; ++i)
-               if (be_ifg_connected(ifg, irn, curr_path[i]))
+       be_lv_t *const lv = be_get_irg_liveness(ienv->co->irg);
+       for (i=1; i<len; ++i) {
+               if (be_values_interfere(lv, irn, curr_path[i]))
                        goto end;
-
-
+       }
 
        /* check for terminating interference */
-       if (be_ifg_connected(ifg, irn, curr_path[0])) {
-
+       if (be_values_interfere(lv, irn, curr_path[0])) {
                /* One node is not a path. */
                /* And a path of length 2 is covered by a clique star constraint. */
                if (len > 2) {
                        /* finally build the constraint */
-                       int cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_greater, 1.0);
+                       int cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_greater_equal, 1.0);
                        for (i=1; i<len; ++i) {
-                               char buf[16];
-                               int nr_1    = get_irn_idx(curr_path[i-1]);
-                               int nr_2    = get_irn_idx(curr_path[i]);
-                               int var_idx = lpp_get_var_idx(ienv->lp, name_cdd_sorted(buf, 'y', nr_1, nr_2));
+                               char buf[32];
+                               int  var_idx;
+
+                               make_affinity_var_name(buf, sizeof(buf), curr_path[i-1], curr_path[i]);
+                               var_idx = lpp_get_var_idx(ienv->lp, buf);
                                lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1.0);
                        }
                }
@@ -455,30 +498,25 @@ static void extend_path(ilp_env_t *ienv, pdeq *path, const ir_node *irn)
                goto end;
        }
 
-
-
        /* recursively extend the path */
        aff = get_affinity_info(ienv->co, irn);
-       co_gs_foreach_neighb(aff, nbr)
+       co_gs_foreach_neighb(aff, nbr) {
                extend_path(ienv, path, nbr->irn);
-
+       }
 
 end:
        /* remove the irn */
        pdeq_getr(path);
-
 }
 
 /**
- *  Search a path of affinity edges, whose ends are connected
- *  by an interference edge and there are no other interference
- *  edges in between.
- *  Then at least one of these affinity edges must break.
+ * Search a path of affinity edges, whose ends are connected
+ * by an interference edge and there are no other interference
+ * edges in between.
+ * Then at least one of these affinity edges must break.
  */
 static void build_path_cstr(ilp_env_t *ienv)
 {
-       affinity_node_t *aff_info;
-
        /* for each node with affinity edges */
        co_gs_foreach_aff_node(ienv->co, aff_info) {
                pdeq *path = new_pdeq();
@@ -491,10 +529,9 @@ static void build_path_cstr(ilp_env_t *ienv)
 
 static void ilp2_build(ilp_env_t *ienv)
 {
-       local_env_t *lenv = ienv->env;
        int lower_bound;
 
-       ienv->lp = new_lpp(ienv->co->name, lpp_minimize);
+       ienv->lp = lpp_new("copyilp", lpp_minimize);
        build_coloring_cstr(ienv);
        build_interference_cstr(ienv);
        build_affinity_cstr(ienv);
@@ -503,39 +540,41 @@ static void ilp2_build(ilp_env_t *ienv)
 
        lower_bound = co_get_lower_bound(ienv->co) - co_get_inevit_copy_costs(ienv->co);
        lpp_set_bound(ienv->lp, lower_bound);
-       lpp_set_time_limit(ienv->lp, lenv->time_limit);
 }
 
 static void ilp2_apply(ilp_env_t *ienv)
 {
-       local_env_t *lenv = ienv->env;
-       int i;
+       local_env_t *lenv = (local_env_t*)ienv->env;
+       ir_graph    *irg  = ienv->co->irg;
 
        /* first check if there was sth. to optimize */
        if (lenv->first_x_var >= 0) {
                int              count = lenv->last_x_var - lenv->first_x_var + 1;
                double          *sol   = XMALLOCN(double, count);
                lpp_sol_state_t  state = lpp_get_solution(ienv->lp, sol, lenv->first_x_var, lenv->last_x_var);
+               int              i;
 
                if (state != lpp_optimal) {
-                       printf("WARNING %s: Solution state is not 'optimal': %d\n", ienv->co->name, state);
-                       assert(state >= lpp_feasible && "The solution should at least be feasible!");
+                       ir_printf("WARNING: Solution state of %F register class %s is not 'optimal': %d\n", ienv->co->irg, ienv->co->cls->name, (int)state);
+                       if (state < lpp_feasible) {
+                               panic("Copy coalescing solution not feasible!");
+                       }
                }
 
                for (i=0; i<count; ++i) {
-                       int nodenr, color;
-                       char var_name[16];
-
-                       if (sol[i] > 1-EPSILON) { /* split variable name into components */
-                               lpp_get_var_name(ienv->lp, lenv->first_x_var+i, var_name, sizeof(var_name));
-
-                               if (sscanf(var_name, "x_%d_%d", &nodenr, &color) == 2) {
-                                       ir_node *irn = pmap_get(lenv->nr_2_irn, INT_TO_PTR(nodenr));
-                                       assert(irn && "This node number must be present in the map");
-
-                                       set_irn_col(ienv->co, irn, color);
-                               } else
-                                       assert(0 && "This should be a x-var");
+                       unsigned nodenr;
+                       unsigned color;
+                       char     var_name[32];
+                       if (sol[i] <= 1-EPSILON)
+                               continue;
+                       /* split variable name into components */
+                       lpp_get_var_name(ienv->lp, lenv->first_x_var+i, var_name, sizeof(var_name));
+
+                       if (sscanf(var_name, "x_%u_%u", &nodenr, &color) == 2) {
+                               ir_node *irn = get_idx_irn(irg, nodenr);
+                               set_irn_col(ienv->co->cls, irn, color);
+                       } else {
+                               panic("This should be a x-var");
                        }
                }
 
@@ -551,50 +590,45 @@ static void ilp2_apply(ilp_env_t *ienv)
 #endif
 }
 
-BE_REGISTER_MODULE_CONSTRUCTOR(be_init_copyilp2);
-void be_init_copyilp2(void)
-{
-       static co_algo_info copyheur = {
-               co_solve_ilp2, 1
-       };
-
-       be_register_copyopt("ilp", &copyheur);
-}
-
-int co_solve_ilp2(copy_opt_t *co)
+/**
+ * Solves the problem using mixed integer programming
+ * @returns 1 iff solution state was optimal
+ * Uses the OU and the GRAPH data structure
+ * Dependency of the OU structure can be removed
+ */
+static int co_solve_ilp2(copy_opt_t *co)
 {
+       unsigned        n_regs = arch_register_class_n_regs(co->cls);
        lpp_sol_state_t sol_state;
-       ilp_env_t *ienv;
-       local_env_t my;
+       ilp_env_t      *ienv;
+       local_env_t     my;
 
        ASSERT_OU_AVAIL(co); //See build_clique_st
        ASSERT_GS_AVAIL(co);
 
-       my.time_limit  = 0;
        my.first_x_var = -1;
        my.last_x_var  = -1;
-       my.nr_2_irn    = pmap_create();
-       FIRM_DBG_REGISTER(my.dbg, "firm.be.coilp2");
+       FIRM_DBG_REGISTER(dbg, "firm.be.coilp2");
 
-       my.normal_colors = bitset_alloca(arch_register_class_n_regs(co->cls));
-       bitset_clear_all(my.normal_colors);
-       arch_put_non_ignore_regs(co->cls, my.normal_colors);
-       my.n_colors = bitset_popcount(my.normal_colors);
+       unsigned *const allocatable_colors = rbitset_alloca(n_regs);
+       be_set_allocatable_regs(co->irg, co->cls, allocatable_colors);
+       my.allocatable_colors = allocatable_colors;
 
        ienv = new_ilp_env(co, ilp2_build, ilp2_apply, &my);
 
        sol_state = ilp_go(ienv);
 
-       pmap_destroy(my.nr_2_irn);
        free_ilp_env(ienv);
 
        return sol_state == lpp_optimal;
 }
 
-#else /* WITH_ILP */
-
-static inline void only_that_you_can_compile_without_WITH_ILP_defined(void)
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_copyilp2)
+void be_init_copyilp2(void)
 {
-}
+       static co_algo_info copyheur = {
+               co_solve_ilp2, 1
+       };
 
-#endif /* WITH_ILP */
+       be_register_copyopt("ilp", &copyheur);
+}