+ if(op->attr.live_range.ilp != ILP_UNDEF) {
+
+ spill = set_find_spill(spill_bb->ilp, irn);
+ assert(spill && spill->irn == irn);
+
+ ir_snprintf(buf, sizeof(buf), "first_lr_%N_%N", irn, bb);
+ cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
+ lpp_set_factor_fast(si->lpp, cst, op->attr.live_range.ilp, 1.0);
+ lpp_set_factor_fast(si->lpp, cst, spill->reg_in, -1.0);
+
+ foreach_post_remat(bb, tmp) {
+ op_t *remat_op = get_irn_link(tmp);
+
+ if(remat_op->attr.remat.remat->value == irn) {
+ lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, -1.0);
+ }
+ }
+ }
+ }
+
+ /* walk forward now and compute constraints for placing spills */
+ /* this must only be done for values that are not defined in this block */
+ pset_foreach(live, irn) {
+ /*
+ * if value is defined in this block we can anways place the spill directly after the def
+ * -> no constraint necessary
+ */
+ if(!is_Phi(irn) && get_nodes_block(irn) == bb) {
+ assert(0);
+ }
+
+
+ spill = set_find_spill(spill_bb->ilp, irn);
+ assert(spill);
+
+ ir_snprintf(buf, sizeof(buf), "req_spill_%N_%N", irn, bb);
+ cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
+
+ lpp_set_factor_fast(si->lpp, cst, spill->spill, 1.0);
+ if(is_diverge_edge(bb)) lpp_set_factor_fast(si->lpp, cst, spill->reg_in, -1.0);
+
+ if(!is_Phi(irn)) {
+ sched_foreach_op(bb, tmp) {
+ op_t *op = get_irn_link(tmp);
+
+ if(is_Phi(tmp)) continue;
+ assert(!is_Proj(tmp));
+
+ if(op->is_remat) {
+ const ir_node *value = op->attr.remat.remat->value;
+
+ if(value == irn) {
+ /* only collect remats up to the first real use of a value */
+ lpp_set_factor_fast(si->lpp, cst, op->attr.remat.ilp, -1.0);
+ }
+ } else {
+ int n;
+
+ for (n=get_irn_arity(tmp)-1; n>=0; --n) {
+ ir_node *arg = get_irn_n(tmp, n);
+
+ if(arg == irn) {
+ /* if a value is used stop collecting remats */
+ goto next_live;
+ }
+ }
+ }
+ }
+ }
+next_live: ;
+ }
+
+ del_pset(live);
+}
+
+typedef struct _irnlist_t {
+ struct list_head list;
+ ir_node *irn;
+} irnlist_t;
+
+typedef struct _interference_t {
+ struct list_head blocklist;
+ ir_node *a;
+ ir_node *b;
+} interference_t;
+
+static int
+cmp_interference(const void *a, const void *b, size_t size)
+{
+ const interference_t *p = a;
+ const interference_t *q = b;
+ (void) size;
+
+ return !(p->a == q->a && p->b == q->b);
+}
+
+static interference_t *
+set_find_interference(set * set, ir_node * a, ir_node * b)
+{
+ interference_t query;
+
+ query.a = (a>b)?a:b;
+ query.b = (a>b)?b:a;
+
+ return set_find(set, &query, sizeof(query), HASH_PTR(PTR_TO_INT(a) ^ PTR_TO_INT(b)));
+}
+
+static interference_t *
+set_insert_interference(spill_ilp_t * si, set * set, ir_node * a, ir_node * b, ir_node * bb)
+{
+ interference_t query,
+ *result;
+ irnlist_t *list = obstack_alloc(si->obst, sizeof(*list));
+
+ list->irn = bb;
+
+ result = set_find_interference(set, a, b);
+ if(result) {
+
+ list_add(&list->list, &result->blocklist);
+ return result;
+ }
+
+ query.a = (a>b)?a:b;
+ query.b = (a>b)?b:a;
+
+ result = set_insert(set, &query, sizeof(query), HASH_PTR(PTR_TO_INT(a) ^ PTR_TO_INT(b)));
+
+ INIT_LIST_HEAD(&result->blocklist);
+ list_add(&list->list, &result->blocklist);
+
+ return result;
+}
+
+static
+int values_interfere_in_block(const spill_ilp_t *si, const ir_node *bb, const ir_node *a, const ir_node *b)
+{
+ const ir_edge_t *edge;
+
+ if (get_nodes_block(a) != bb && get_nodes_block(b) != bb) {
+ /* both values are live in, so they interfere */
+ return 1;
+ }
+
+ /* ensure a dominates b */
+ if (value_dominates(b, a)) {
+ const ir_node *t;
+ t = b;
+ b = a;
+ a = t;
+ }
+ assert(get_nodes_block(b) == bb && "at least b should be defined here in this block");
+
+
+ /* the following code is stolen from bera.c */
+ if (be_is_live_end(si->lv, bb, a))
+ return 1;
+
+ foreach_out_edge(a, edge) {
+ const ir_node *user = edge->src;
+ if (get_nodes_block(user) == bb
+ && ! is_Phi(user)
+ && b != user
+ && ! pset_find_ptr(si->inverse_ops, user)
+ && value_dominates(b, user))
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Walk all irg blocks and collect interfering values inside of phi classes
+ */
+static void
+luke_interferencewalker(ir_node * bb, void * data)
+{
+ spill_ilp_t *si = (spill_ilp_t*)data;
+ int l1, l2;
+
+ be_lv_foreach(si->lv, bb, be_lv_state_end | be_lv_state_out | be_lv_state_in, l1) {
+ ir_node *a = be_lv_get_irn(si->lv, bb, l1);
+ op_t *a_op = get_irn_link(a);
+
+
+ /* a is only interesting if it is in my register class and if it is inside a phi class */
+ if (has_reg_class(si, a) && get_phi_class(si->pc, a)) {
+ if (a_op->is_remat || pset_find_ptr(si->inverse_ops, a))
+ continue;
+
+ for (l2 = _be_lv_next_irn(si->lv, bb, 0xff, l1 + 1); l2 >= 0; l2 = _be_lv_next_irn(si->lv, bb, 0xff, l2 + 1)) {
+ ir_node *b = be_lv_get_irn(si->lv, bb, l2);
+ op_t *b_op = get_irn_link(b);
+
+ /* a and b are only interesting if they are in the same phi class */
+ if (has_reg_class(si, b) && get_phi_class(si->pc, a) == get_phi_class(si->pc, b)) {
+ if (b_op->is_remat || pset_find_ptr(si->inverse_ops, b))
+ continue;
+
+ if (values_interfere_in_block(si, bb, a, b)) {
+ DBG((si->dbg, LEVEL_4, "\tvalues interfere in %+F: %+F, %+F\n", bb, a, b));
+ set_insert_interference(si, si->interferences, a, b, bb);
+ }
+ }
+ }
+ }