* Date: 28.02.2006
* Copyright: (c) Universitaet Karlsruhe
* Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
- * $Id$
*
* Common stuff used by all ILP fomulations.
*
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef WITH_ILP
-
#include "becopyilp_t.h"
#include "beifg_t.h"
while (redo) {
redo = 0;
be_ifg_foreach_node(ifg, iter, irn) {
- if (!sr_is_removed(sr, irn) && !co_is_optimizable_root(sr->co, irn) && !co_is_optimizable_arg(sr->co, irn)) {
+ arch_register_req_t req;
+
+ arch_get_register_req(sr->co->aenv, &req, irn, -1);
+
+ if (!arch_register_req_is(&req, limited) && !sr_is_removed(sr, irn) && !co_gs_is_optimizable(sr->co, irn)) {
if (sr_is_simplicial(sr, irn)) {
coloring_suffix_t *cs = obstack_alloc(&sr->ob, sizeof(*cs));
*****************************************************************************/
+#include <stdio.h>
+
ilp_env_t *new_ilp_env(copy_opt_t *co, ilp_callback build, ilp_callback apply, void *env) {
ilp_env_t *res = malloc(sizeof(*res));
assert(res);
}
lpp_sol_state_t ilp_go(ilp_env_t *ienv) {
+ FILE *f;
+ char buf[256];
+
sr_remove(ienv->sr);
ienv->build(ienv);
lpp_solve_cplex(ienv->lp);
#endif
+ snprintf(buf, sizeof(buf), "%s.ilp", ienv->co->name);
+ f = fopen(buf, "wt");
+ lpp_dump_plain(ienv->lp, f);
+ fclose(f);
+
ienv->apply(ienv);
sr_reinsert(ienv->sr);
free_lpp(ienv->lp);
free(ienv);
}
-
-#else /* WITH_ILP */
-
-static void only_that_you_can_compile_without_WITH_ILP_defined(void) {
-}
-
-#endif /* WITH_ILP */
#ifdef WITH_ILP
-#include "becopyilp_t.h"
-#include "benumb_t.h"
-#include "belive_t.h"
-#include "irdom_t.h"
-#include "irgwalk.h"
-#include "xmalloc.h"
-#include "pset.h"
-#include "irprog.h"
-#include "irdom_t.h"
-#include "iredges_t.h"
-
-#include "becopystat.h"
-#include "besched_t.h"
-#include "phiclass.h"
-
-#if 0 //temporary
-
-#define PATH_CONSTRAINTS_FOR_CLASSES
-
-typedef struct _problem_instance_t {
- const copy_opt_t *co; /**< the copy opt problem */
- size_red_t *sr; /**< problem size reduction. removes simple nodes */
- lpp_t *lp; /**< the linear programming problem */
-
- /* Helpers for maintaining indices and finding variables */
- int first_nnc_var_idx; /**< the first index of a constraint belonging to no-null-colors stuff*/
- int cst_counter, first_x_var, last_x_var;
- char buf[32];
- pset *done;
-} problem_instance_t;
-
-#define is_color_possible(irn,color) arch_reg_is_allocatable(pi->co->aenv, irn, -1, arch_register_for_index(pi->co->cls, color))
-
-/*
- * Some stuff for variable name handling.
- */
-#define mangle_cst(buf, prefix, nr) \
- snprintf((buf), sizeof(buf), "%c%d", (prefix), (nr))
-
-#define mangle_var1(buf, prefix, color) \
- snprintf((buf), sizeof(buf), "%c%d", (prefix), (color))
-
-#define mangle_var2(buf, prefix, node_nr, color) \
- snprintf((buf), sizeof(buf), "%c%d_%d", (prefix), (node_nr), (color))
-
-#define mangle_var3(buf, prefix, n1, n2, col) \
- snprintf((buf), sizeof(buf), "%c%d_%d_%d", (prefix), (n1), (n2), (col))
-
-#define mangle_var_irn(buf, prefix, irn, color) \
- mangle_var2((buf), (prefix), get_irn_graph_nr(irn), (color))
-
-#define split_var(var, nnr, col) \
- sscanf(var, "x%d_%d", (nnr), (col))
-
-
-#ifndef PATH_CONSTRAINTS_FOR_CLASSES
-/**
- * Matrix P: Path contraints.
- * If 2 nodes interfere and there is a path of equal-color-edges
- * connecting them, then at least one of those equal-color-edges
- * will break and cause some costs.
- */
-static void pi_add_path_cstr(problem_instance_t *pi) {
- unit_t *curr;
- int cst_counter = 0;
- DBG((dbg, LEVEL_2, "Adding path constraints...\n"));
-
- /* for all optimization units (only phis) */
- list_for_each_entry(unit_t, curr, &pi->co->units, units) {
- int i, o, rootnr;
-
- if (curr->min_nodes_costs == 0)
- continue;
-
- rootnr = get_irn_graph_nr(curr->nodes[0]);
- /* check all argument pairs for interference */
- for (i=1; i<curr->node_count; ++i) {
- const ir_node *arg1 = curr->nodes[i];
- int arg1nr = get_irn_graph_nr(arg1);
- for (o=i+1; o<curr->node_count; ++o) {
- const ir_node *arg2 = curr->nodes[o];
- int arg2nr = get_irn_graph_nr(arg2);
- if (nodes_interfere(pi->co->cenv, arg1, arg2)) {
- int cst_idx, y_idx;
- char buf[32];
-
- mangle_cst(buf, 'P', cst_counter++);
- cst_idx = lpp_add_cst(pi->curr_lp, buf, lpp_greater, 1);
-
- mangle_var2(buf, 'y', rootnr, arg1nr);
- y_idx = lpp_get_var_idx(pi->curr_lp, buf);
- lpp_set_factor_fast(pi->curr_lp, cst_idx, y_idx, 1);
-
- mangle_var2(buf, 'y', rootnr, arg2nr);
- y_idx = lpp_get_var_idx(pi->curr_lp, buf);
- lpp_set_factor_fast(pi->curr_lp, cst_idx, y_idx, 1);
- }
- }
- }
- }
-}
-#endif
-
-#ifdef PATH_CONSTRAINTS_FOR_CLASSES
-static INLINE int get_y_var_idx(problem_instance_t *pi, int nnr1, int nnr2) {
- int res;
- char buf[30];
-
- mangle_var2(buf, 'y', nnr1, nnr2);
- if ((res = lpp_get_var_idx(pi->curr_lp, buf)) != -1)
- return res;
-
- mangle_var2(buf, 'y', nnr2, nnr1);
- if ((res = lpp_get_var_idx(pi->curr_lp, buf)) != -1)
- return res;
-
- assert(0 && "One of them must work");
- return -1;
-}
-
-static void check_ecc_and_add_cut(problem_instance_t *pi, ir_node **path, int length, pset *remain, ir_node *tgt) {
- if (path[length-1] == tgt) { /* we found a path */
- int cst_idx, var_idx, i, nnr1, nnr2;
- char buf[30];
-
- /* add cut to ilp */
- mangle_cst(buf, 'Q', pi->cst_counter++);
- cst_idx = lpp_add_cst(pi->curr_lp, buf, lpp_greater, 1);
-
- /* add all vars along the path */
- nnr2 = get_irn_graph_nr(path[0]);
- for (i=1; i<length; ++i) {
- nnr1 = nnr2;
- nnr2 = get_irn_graph_nr(path[i]);
- var_idx = get_y_var_idx(pi, nnr1, nnr2);
- lpp_set_factor_fast(pi->curr_lp, cst_idx, var_idx, 1);
- }
- } else { /* try to extend the path */
- be_chordal_env_t *cenv = pi->co->cenv;
- const ir_edge_t *edge;
- ir_node *end = path[length-1];
- ir_node **next = alloca(pset_count(remain) * sizeof(*next));
- int i, o, max, next_pos = 0;
- pset *done = pset_new_ptr_default();
-
- /* find all potential next nodes on path */
- /* args of phis */
- if (is_Phi(end))
- for(i=0, max=get_irn_arity(end); i<max; ++i) {
- ir_node *arg = get_irn_n(end, i);
- if (!pset_find_ptr(done, arg) && pset_find_ptr(remain, arg)) {
- next[next_pos++] = arg;
- pset_insert_ptr(done, arg);
- }
- }
- /* outs of phis and other nodes */
- foreach_out_edge(end, edge) {
- ir_node *user = edge->src;
- if (is_Phi(user) && !pset_find_ptr(done, user) && pset_find_ptr(remain, user)) {
- next[next_pos++] = user;
- pset_insert_ptr(done, user);
- }
- }
- del_pset(done);
-
-
- /* delete all potential nodes with interferences to other nodes in the path */
- for (i=0; i<next_pos; ++i) {
- ir_node *nn = next[i];
-
- /* if next is the tgt, it may interfere with path[0],
- * so skip the first check */
- o = (nn == tgt && length > 1) ? 1 : 0;
-
- for(; o<length; ++o)
- if (nodes_interfere(cenv, nn, path[o])) {
- next[i] = NULL;
- break;
- }
- }
- /* now we have all possible nodes in next; impossibles are NULL */
-
- /* try to finish path with all possible nodes */
- for (i=0; i<next_pos; ++i) {
- if (!next[i]) /* this was an impossible node */
- continue;
-
- path[length] = next[i];
- pset_remove_ptr(remain, next[i]);
- check_ecc_and_add_cut(pi, path, length+1, remain, tgt);
- pset_insert_ptr(remain, next[i]);
- }
- }
-}
-
-static void path_cstr_for_classes_walker(ir_node *irn, void *env) {
- problem_instance_t *pi = env;
- be_chordal_env_t *cenv;
- int i, o, max;
- ir_node *m, **cls;
- pset *class = get_phi_class(irn);
- if (!class || pset_find_ptr(pi->done, class))
- return;
-
- pset_insert_ptr(pi->done, class);
-
- /* pset to array */
- max = pset_count(class);
- cls = alloca(max * sizeof(*cls));
- for(i=0, m = pset_first(class); m; i++, m = pset_next(class)) {
- DBG((dbg, LEVEL_1, " class member: %+F\n", m));
- cls[i] = m;
- }
-
- cenv = pi->co->cenv;
- for(i=0; i<max; ++i) {
- ir_node **path = alloca(max * sizeof(*path));
- pset *remain = pset_new_ptr(8);
- pset_insert_pset_ptr(remain, class);
-
- /* add cls[i] to path and remove it from remainder */
- path[0] = cls[i];
- pset_remove_ptr(remain, cls[i]);
-
- for(o=i+1; o<max; ++o)
- if (nodes_interfere(cenv, cls[i], cls[o]))
- check_ecc_and_add_cut(pi, path, 1, remain, cls[o]);
-
- /* insert back into remainder */
- pset_insert_ptr(remain, cls[i]);
- }
-}
-
-
-/**
- * Matrix P: Path contraints.
- * If 2 nodes interfere and there is a path of equal-color-edges
- * connecting them, then at least one of those equal-color-edges
- * will break and cause some costs.
- */
-static void pi_add_path_cstr_for_classes(problem_instance_t *pi) {
- DBG((dbg, LEVEL_2, "Adding path constraints for phi classes...\n"));
- pi->cst_counter = 0;
- pi->done = pset_new_ptr_default();
- irg_walk_graph(pi->co->irg, path_cstr_for_classes_walker, NULL, pi);
- del_pset(pi->done);
-}
-#endif
-
-static void pi_construct(problem_instance_t *pi) {
- pi_add_path_cstr_for_classes(pi);
- pi_add_path_cstr(pi);
- pi_add_clique_path_cstr(pi);
-}
-#endif
-
#include "becopyilp_t.h"
#define DEBUG_LVL 1
#ifdef WITH_ILP
+#include <bitset.h>
+#include "pdeq.h"
+
#include "irtools.h"
#include "irgwalk.h"
#include "becopyilp_t.h"
/* for each maximal clique */
be_ifg_foreach_clique(ifg, iter, clique, &size) {
+ int realsize = 0;
+
+ for (i=0; i<size; ++i)
+ if (!sr_is_removed(ienv->sr, clique[i]))
+ ++realsize;
- if (size < 2)
+ if (realsize < 2)
continue;
/* for all colors */
lpp_set_factor_fast(ienv->lp, cst_idx, root_idx, 1.0);
lpp_set_factor_fast(ienv->lp, cst_idx, arg_idx, -1.0);
- lpp_set_factor_fast(ienv->lp, cst_idx, root_idx, -1.0);
+ lpp_set_factor_fast(ienv->lp, cst_idx, y_idx, -1.0);
}
}
}
new_edge.n1 = n2;
new_edge.n2 = n1;
}
- *counter++;
+ (*counter)++;
return set_insert(edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge));
}
if (e) {
e->n1 = NULL;
e->n2 = NULL;
- *counter--;
+ (*counter)--;
}
}
* At most 1 node of the clique can be colored equally with the external node.
*/
static void build_clique_star_cstr(ilp_env_t *ienv) {
- node_t *node;
+ affinity_t *aff;
/* for each node with affinity edges */
- co_gs_foreach_node(ienv->co, node) {
+ co_gs_foreach_aff_node(ienv->co, aff) {
struct obstack ob;
neighb_t *nbr;
- ir_node *center = node->irn;
+ ir_node *center = aff->irn;
ir_node **nodes;
set *edges;
int i, o, n_nodes, n_edges;
/* get all affinity neighbours */
n_nodes = 0;
- co_gs_foreach_neighb(node, nbr) {
+ co_gs_foreach_neighb(aff, nbr) {
obstack_ptr_grow(&ob, nbr->irn);
++n_nodes;
}
for (e=set_first(edges); !e->n1; e=set_next(edges))
/*nothing*/ ;
- remove_edge(edges, e->n1, e->n2, &n_edges);
pset_insert_ptr(clique, e->n1);
pset_insert_ptr(clique, e->n2);
+ remove_edge(edges, e->n1, e->n2, &n_edges);
/* while the clique is growing */
do {
}
}
+
+static void extend_path(ilp_env_t *ienv, pdeq *path, ir_node *irn) {
+ be_ifg_t *ifg = ienv->co->cenv->ifg;
+ int i, len;
+ ir_node **curr_path;
+ affinity_t *aff;
+ neighb_t *nbr;
+
+ /* do not walk backwards or in circles */
+ if (pdeq_contains(path, irn))
+ return;
+
+ /* insert the new irn */
+ pdeq_putr(path, irn);
+
+
+
+ /* check for forbidden interferences */
+ len = pdeq_len(path);
+ curr_path = alloca(len * sizeof(*curr_path));
+ pdeq_copyl(path, curr_path);
+
+ for (i=1; i<len; ++i)
+ if (be_ifg_connected(ifg, irn, curr_path[i]))
+ goto end;
+
+
+
+ /* check for terminating interference */
+ if (be_ifg_connected(ifg, 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);
+ for (i=1; i<len; ++i) {
+ char buf[16];
+ int nr_1 = get_irn_node_nr(curr_path[i-1]);
+ int nr_2 = get_irn_node_nr(curr_path[i]);
+ int var_idx = lpp_get_var_idx(ienv->lp, name_cdd_sorted(buf, 'y', nr_1, nr_2));
+ lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1.0);
+ }
+ }
+
+ /* this path cannot be extended anymore */
+ goto end;
+ }
+
+
+
+ /* recursively extend the path */
+ aff = get_affinity_info(ienv->co, irn);
+ 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.
*/
static void build_path_cstr(ilp_env_t *ienv) {
+ affinity_t *aff_info;
+
+ /* for each node with affinity edges */
+ co_gs_foreach_aff_node(ienv->co, aff_info) {
+ pdeq *path = new_pdeq();
+ extend_path(ienv, path, aff_info->irn);
+
+ del_pdeq(path);
+ }
}
static void ilp2_build(ilp_env_t *ienv) {
lpp_sol_state_t state;
int i, count;
- count = lenv->last_x_var - lenv->first_x_var + 1;
- sol = xmalloc(count * sizeof(sol[0]));
- state = lpp_get_solution(ienv->lp, sol, lenv->first_x_var, lenv->last_x_var);
- 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!");
- }
+ /* first check if there was sth. to optimize */
+ if (lenv->first_x_var >= 0) {
+
+ count = lenv->last_x_var - lenv->first_x_var + 1;
+ sol = xmalloc(count * sizeof(sol[0]));
+ state = lpp_get_solution(ienv->lp, sol, lenv->first_x_var, lenv->last_x_var);
+ 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!");
+ }
- for (i=0; i<count; ++i) {
- int nodenr, color;
- char var_name[16];
+ 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 (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");
+ 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");
+ set_irn_col(ienv->co, irn, color);
+ } else
+ assert(0 && "This should be a x-var");
+ }
}
}
int co_is_optimizable_arg(const copy_opt_t *co, ir_node *irn) {
const ir_edge_t *edge;
+ assert(0 && "Is buggy and obsolete. Do not use");
+
if (arch_irn_is_ignore(co->aenv, irn))
return 0;
|_| |___/
******************************************************************************/
-static int compare_node_t(const void *k1, const void *k2, size_t size) {
- const node_t *n1 = k1;
- const node_t *n2 = k2;
+static int compare_affinity_t(const void *k1, const void *k2, size_t size) {
+ const affinity_t *n1 = k1;
+ const affinity_t *n2 = k2;
return (n1->irn != n2->irn);
}
static void add_edge(copy_opt_t *co, ir_node *n1, ir_node *n2, int costs) {
- node_t new_node, *node;
+ affinity_t new_node, *node;
neighb_t new_nbr, *nbr;
int allocnew;
new_node.irn = n1;
new_node.count = 0;
new_node.neighbours = NULL;
- node = set_insert(co->nodes, new_node.irn, sizeof(new_node), HASH_PTR(new_node.irn));
+ node = set_insert(co->nodes, &new_node, sizeof(new_node), HASH_PTR(new_node.irn));
allocnew = 1;
for (nbr = node->neighbours; nbr; nbr = nbr->next)
void co_build_graph_structure(copy_opt_t *co) {
obstack_init(&co->obst);
- co->nodes = new_set(compare_node_t, 32);
+ co->nodes = new_set(compare_affinity_t, 32);
irg_walk_graph(co->irg, build_graph_walker, NULL, co);
}
/* co_solve_ilp1() co_solve_ilp2() are implemented in becopyilpX.c */
int co_gs_is_optimizable(copy_opt_t *co, ir_node *irn) {
- node_t new_node, *n;
+ affinity_t new_node, *n;
new_node.irn = irn;
- n = set_find(co->nodes, new_node.irn, sizeof(new_node), HASH_PTR(new_node.irn));
+ n = set_find(co->nodes, &new_node, sizeof(new_node), HASH_PTR(new_node.irn));
if (n) {
return (n->count > 0);
} else
******************************************************************************/
typedef struct _neighb_t neighb_t;
-typedef struct _node_t node_t;
+typedef struct _affinity_t affinity_t;
struct _neighb_t {
int costs; /** the costs of the edge (node_t->irn, neighb_t->irn) */
};
-struct _node_t {
+struct _affinity_t {
ir_node *irn; /** a node with affinity edges */
int count; /** number of affinity edges in the linked list below */
neighb_t *neighbours; /** a linked list of all affinity neighbours */
};
+
+static INLINE affinity_t *get_affinity_info(const copy_opt_t *co, ir_node *irn) {
+ affinity_t find;
+
+ find.irn = irn;
+ return set_find(co->nodes, &find, sizeof(find), HASH_PTR(irn));
+}
+
#define co_gs_nodes_begin(co) set_first((co)->nodes)
#define co_gs_nodes_next(co) set_next((co)->nodes)
#define co_gs_nodes_break(co) set_break((co)->nodes)
-#define co_gs_foreach_node(co, node) for (node = co_gs_nodes_begin(co); node; node = co_gs_nodes_next(co))
+#define co_gs_foreach_aff_node(co, aff_node) for (aff_node = co_gs_nodes_begin(co); aff_node; aff_node = co_gs_nodes_next(co))
-#define co_gs_foreach_neighb(node, neighb) for (neighb = node->neighbours; neighb; neighb = neighb->next)
+#define co_gs_foreach_neighb(aff_node, neighb) for (neighb = aff_node->neighbours; neighb; neighb = neighb->next)
#endif
ir_graph *irg = cenv->irg;
arch_env_t *aenv = cenv->birg->main_env->arch_env;
- if (last_irg != irg) {
- copystat_reset();
- copystat_collect_irg(irg, aenv);
- }
+ copystat_reset();
+ copystat_collect_irg(irg, aenv);
for (n = pset_first(all_phi_nodes); n; n = pset_next(all_phi_nodes))
if (arch_get_irn_reg_class(aenv, n, -1) == cenv->cls)
int costs_inevit, costs_init, costs_heur, costs_ilp1, costs_ilp2, lower_bound;
phi_class_compute(chordal_env->irg);
+ copystat_collect_cls(chordal_env);
co = new_copy_opt(chordal_env, co_get_costs_loop_depth);
co_build_ou_structure(co);
saver.chordal_env = chordal_env;
saver.saved_colors = pmap_create();
save_colors(&saver);
+ be_ra_chordal_check(co->cenv);
/* initial values */
costs_inevit = co_get_inevit_copy_costs(co);
co_solve_heuristic(co);
lc_timer_stop(timer);
+
+ be_ra_chordal_check(co->cenv);
costs_heur = co_get_copy_costs(co);
DBG((dbg, LEVEL_1, "HEUR costs: %3d\n", costs_heur));
copystat_add_heur_time(lc_timer_elapsed_msec(timer));
co_solve_ilp2(co, 60.0);
+ be_ra_chordal_check(co->cenv);
costs_ilp2 = co_get_copy_costs(co);
DBG((dbg, LEVEL_1, "ILP2 costs: %3d\n", costs_ilp2));
copystat_add_opt_costs(costs_ilp2); /*TODO ADAPT */