simplify and cleanup execfreq API
[libfirm] / ir / be / becopyilp2.c
index 8b51a31..32a0395 100644 (file)
@@ -64,6 +64,17 @@ typedef struct local_env_t {
        const unsigned *allocatable_colors;
 } local_env_t;
 
+static unsigned check_alignment_constraints(ir_node *node)
+{
+       const arch_register_req_t *req = arch_get_irn_register_req(node);
+       // For larger than 1 variables, support only aligned constraints
+       assert(((!(req->type & arch_register_req_type_aligned)
+                        && req->width == 1)
+                       || (req->type & arch_register_req_type_aligned))
+                  && "Unaligned large (width > 1) variables not supported");
+       return (req->type & arch_register_req_type_aligned) && req->width > 1;
+}
+
 static void make_color_var_name(char *buf, size_t buf_size,
                                 const ir_node *node, unsigned color)
 {
@@ -73,7 +84,7 @@ static void make_color_var_name(char *buf, size_t buf_size,
 
 static void build_coloring_cstr(ilp_env_t *ienv)
 {
-       local_env_t    *lenv   = ienv->env;
+       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;
@@ -89,10 +100,13 @@ static void build_coloring_cstr(ilp_env_t *ienv)
                unsigned                   col;
                int                        cst_idx;
                unsigned                   curr_node_color;
+               unsigned                   has_alignment_cstr;
 
                if (sr_is_removed(ienv->sr, irn))
                        continue;
 
+               has_alignment_cstr = check_alignment_constraints(irn);
+
                req = arch_get_irn_register_req(irn);
 
                /* get assignable colors */
@@ -109,7 +123,8 @@ static void build_coloring_cstr(ilp_env_t *ienv)
                for (col = 0; col < n_regs; ++col) {
                        int    var_idx;
                        double val;
-                       if (!rbitset_is_set(colors, col))
+                       if (!rbitset_is_set(colors, col)
+                               || (has_alignment_cstr && ((col % req->width) != 0)))
                                continue;
 
                        make_color_var_name(buf, sizeof(buf), irn, col);
@@ -128,7 +143,9 @@ static void build_coloring_cstr(ilp_env_t *ienv)
                for (col = 0; col < n_regs; ++col) {
                        int cst_idx;
                        int var_idx;
-                       if (rbitset_is_set(colors, col))
+                       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);
@@ -145,7 +162,7 @@ static void build_coloring_cstr(ilp_env_t *ienv)
 static void build_interference_cstr(ilp_env_t *ienv)
 {
        lpp_t          *lpp      = ienv->lp;
-       local_env_t    *lenv     = ienv->env;
+       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);
@@ -180,11 +197,21 @@ static void build_interference_cstr(ilp_env_t *ienv)
                                ir_node *irn = clique[i];
                                char     buf[32];
                                int      var_idx;
+                               unsigned aligment_offset = 0;
 
                                if (sr_is_removed(ienv->sr, irn))
                                        continue;
 
-                               make_color_var_name(buf, sizeof(buf), irn, col);
+                               // 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);
                        }
@@ -213,7 +240,6 @@ static void make_affinity_var_name(char *buf, size_t buf_size,
 static void build_affinity_cstr(ilp_env_t *ienv)
 {
        unsigned  n_colors = arch_register_class_n_regs(ienv->co->cls);
-       unit_t   *curr;
 
        /* for all optimization units */
        list_for_each_entry(unit_t, curr, &ienv->co->units, units) {
@@ -264,8 +290,8 @@ typedef struct 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);
@@ -285,7 +311,7 @@ static inline edge_t *add_edge(set *edges, ir_node *n1, ir_node *n2, size_t *cou
                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)
@@ -299,7 +325,7 @@ 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, size_t *counter)
@@ -313,7 +339,7 @@ static inline void remove_edge(set *edges, ir_node *n1, ir_node *n2, size_t *cou
                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;
@@ -321,7 +347,7 @@ static inline void remove_edge(set *edges, ir_node *n1, ir_node *n2, size_t *cou
        }
 }
 
-#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
@@ -330,12 +356,9 @@ static inline void remove_edge(set *edges, ir_node *n1, ir_node *n2, size_t *cou
  */
 static void build_clique_star_cstr(ilp_env_t *ienv)
 {
-       affinity_node_t *aff;
-
        /* for each node with affinity edges */
        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;
@@ -356,7 +379,7 @@ 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;
@@ -374,8 +397,7 @@ static void build_clique_star_cstr(ilp_env_t *ienv)
                        bool    growed;
 
                        /* get 2 starting nodes to form a clique */
-                       for (e=set_first(edges); !e->n1; e=set_next(edges)) {
-                       }
+                       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);
@@ -391,7 +413,6 @@ static void build_clique_star_cstr(ilp_env_t *ienv)
                                /* search for a candidate to extend the clique */
                                for (i=0; i<n_nodes; ++i) {
                                        ir_node *cand = nodes[i];
-                                       ir_node *member;
                                        bool     is_cand;
 
                                        /* if its already in the clique try the next */
@@ -424,10 +445,9 @@ 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;
-                               int      cst_idx;
-                               char     buf[32];
+                               int  var_idx;
+                               int  cst_idx;
+                               char buf[32];
 
                                cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_greater_equal, pset_count(clique)-1);
 
@@ -452,7 +472,6 @@ static void extend_path(ilp_env_t *ienv, pdeq *path, const ir_node *irn)
        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))
@@ -514,8 +533,6 @@ end:
  */
 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();
@@ -543,7 +560,7 @@ static void ilp2_build(ilp_env_t *ienv)
 
 static void ilp2_apply(ilp_env_t *ienv)
 {
-       local_env_t *lenv = ienv->env;
+       local_env_t *lenv = (local_env_t*)ienv->env;
        ir_graph    *irg  = ienv->co->irg;
 
        /* first check if there was sth. to optimize */