+#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->chordal_env, 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->chordal_env;
+ 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->chordal_env;
+ 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(get_irg(pi->co), path_cstr_for_classes_walker, NULL, pi);
+ del_pset(pi->done);
+}
+#endif
+
+#ifdef PRECOLOR_MAX_CLIQUE
+struct pre_col {
+ problem_instance_t *pi;
+ pset **clique;
+};
+
+#define has_reg_class(pi,irn) \
+ (arch_get_irn_reg_class(pi->co->chordal_env->session_env->main_env->arch_env, \
+ irn, -1) == pi->co->chordal_env->cls)
+
+static void preColoringWalker(ir_node *bl, void *env) {
+ struct pre_col *e = env;
+ pset **clique = e->clique;
+ pset *max_clique = clique ? *clique : NULL;
+ int max = max_clique ? pset_count(max_clique) : 0;
+ problem_instance_t *pi = e->pi;
+
+ int i, n;
+ pset *live = pset_new_ptr_default();
+ ir_node *irn;
+ irn_live_t *li;
+
+ /* as always, bring the live end nodes to life here */
+ live_foreach(bl, li) {
+ if(live_is_end(li) && has_reg_class(pi, li->irn)) {
+ pset_insert_ptr(live, irn);
+ }
+ }
+
+ sched_foreach_reverse(bl, irn) {
+ int pres = pset_count(live);
+
+ if(pres > max) {
+ max = pres;
+ if(max_clique)
+ del_pset(max_clique);
+
+ max_clique = pset_new_ptr_default();
+ pset_insert_pset_ptr(max_clique, live);
+ }
+
+
+
+ if(has_reg_class(pi, irn))
+ pset_remove_ptr(live, irn);
+
+ for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
+ ir_node *op = get_irn_n(irn, i);
+ if(has_reg_class(pi, op) && !is_Phi(irn))
+ pset_insert_ptr(live, op);
+ }
+ }
+
+ del_pset(live);
+ *clique = max_clique;
+}
+
+static void pi_add_constr_preColoring(problem_instance_t *pi) {
+ ir_node *irn;
+ int cst_counter, color;
+ struct pre_col pre_col;
+
+ pre_col.clique = NULL;
+ pre_col.pi = pi;
+
+ dom_tree_walk_irg(get_irg(pi->co), preColoringWalker, NULL, &pre_col);
+
+ color = 0;
+ for (irn = pset_first(*pre_col.clique); irn; irn = pset_next(*pre_col.clique)) {
+ int cst_idx, var_idx, nnr = get_irn_graph_nr(irn);
+ char buf[100];
+
+ mangle_cst(buf, 'K', cst_counter++);
+ cst_idx = lpp_add_cst(pi->curr_lp, buf, lpp_equal, 1);
+
+ mangle_var2(buf, 'x', nnr, color++);
+ var_idx = lpp_get_var_idx(pi->curr_lp, buf);
+ lpp_set_factor_fast(pi->curr_lp, cst_idx, var_idx, 1);
+ }
+}
+#endif
+