+ edge = get_block_succ_next(block, edge);
+ /* next block can only contain phis, if this is a merge edge */
+ if(edge) return;
+
+ ir_snprintf(buf, sizeof(buf), "copyreg_%N", block);
+ copyreg = lpp_add_var(si->lpp, buf, lpp_binary, 0.0);
+
+ ir_snprintf(buf, sizeof(buf), "check_copyreg_%N", block);
+ cst = lpp_add_cst(si->lpp, buf, lpp_less, si->n_regs);
+
+ pset_foreach(live, tmp) {
+ spill_t *spill;
+#if 0
+ op_t *op = get_irn_link(irn);
+ lpp_set_factor_fast(si->lpp, cst, op->attr.live_range.ilp, 1.0);
+#endif
+ spill = set_find_spill(spill_bb->ilp, tmp);
+ assert(spill);
+
+ lpp_set_factor_fast(si->lpp, cst, spill->reg_out, 1.0);
+ }
+ lpp_set_factor_fast(si->lpp, cst, copyreg, 1.0);
+
+ sched_foreach(succ, phi) {
+ const ir_node *to_copy;
+ op_t *to_copy_op;
+ spill_t *to_copy_spill;
+ op_t *phi_op = get_irn_link(phi);
+ ilp_var_t reload = ILP_UNDEF;
+
+
+ if(!is_Phi(phi)) break;
+ if(!has_reg_class(si, phi)) continue;
+
+ to_copy = get_irn_n(phi, pos);
+
+ to_copy_op = get_irn_link(to_copy);
+
+ to_copy_spill = set_find_spill(spill_bb->ilp, to_copy);
+ assert(to_copy_spill);
+
+ if(spill_bb->reloads) {
+ keyval_t *keyval = set_find_keyval(spill_bb->reloads, to_copy);
+
+ if(keyval) {
+ reload = PTR_TO_INT(keyval->val);
+ }
+ }
+
+ ir_snprintf(buf, sizeof(buf), "req_copy_%N_%N", block, to_copy);
+ cst = lpp_add_cst(si->lpp, buf, lpp_less, 0.0);
+
+ /* copy - reg_out - reload - remat - live_range <= 0 */
+ lpp_set_factor_fast(si->lpp, cst, phi_op->attr.live_range.args.copies[pos], 1.0);
+ lpp_set_factor_fast(si->lpp, cst, to_copy_spill->reg_out, -1.0);
+ if(reload != ILP_UNDEF) lpp_set_factor_fast(si->lpp, cst, reload, -1.0);
+ lpp_set_factor_fast(si->lpp, cst, to_copy_op->attr.live_range.ilp, -1.0);
+ foreach_pre_remat(si, block, tmp) {
+ op_t *remat_op = get_irn_link(tmp);
+ if(remat_op->attr.remat.remat->value == to_copy) {
+ lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, -1.0);
+ }
+ }
+
+ ir_snprintf(buf, sizeof(buf), "copyreg_%N_%N", block, to_copy);
+ cst = lpp_add_cst(si->lpp, buf, lpp_less, 0.0);
+
+ /* copy - reg_out - copyreg <= 0 */
+ lpp_set_factor_fast(si->lpp, cst, phi_op->attr.live_range.args.copies[pos], 1.0);
+ lpp_set_factor_fast(si->lpp, cst, to_copy_spill->reg_out, -1.0);
+ lpp_set_factor_fast(si->lpp, cst, copyreg, -1.0);
+ }
+}
+
+
+/**
+ * Walk all irg blocks and emit this ILP
+ */
+static void
+luke_blockwalker(ir_node * bb, void * data)
+{
+ spill_ilp_t *si = (spill_ilp_t*)data;
+ ir_node *irn;
+ pset *live;
+ char buf[256];
+ ilp_cst_t cst;
+ spill_bb_t *spill_bb = get_irn_link(bb);
+ ir_node *tmp;
+ spill_t *spill;
+ pset *defs = pset_new_ptr_default();
+
+
+ live = pset_new_ptr_default();
+
+ /****************************************
+ * B A S I C B L O C K E N D
+ ***************************************/
+
+
+ /* init live values at end of block */
+ get_live_end(si, bb, live);
+
+ pset_foreach(live, irn) {
+ op_t *op;
+ ilp_var_t reload = ILP_UNDEF;
+
+ spill = set_find_spill(spill_bb->ilp, irn);
+ assert(spill);
+
+ if(spill_bb->reloads) {
+ keyval_t *keyval = set_find_keyval(spill_bb->reloads, irn);
+
+ if(keyval) {
+ reload = PTR_TO_INT(keyval->val);
+ }
+ }
+
+ op = get_irn_link(irn);
+ assert(!op->is_remat);
+
+ ir_snprintf(buf, sizeof(buf), "lr_%N_%N", irn, bb);
+ op->attr.live_range.ilp = lpp_add_var(si->lpp, buf, lpp_binary, 0.0);
+ op->attr.live_range.op = bb;
+
+ ir_snprintf(buf, sizeof(buf), "reg_out_%N_%N", bb, irn);
+ cst = lpp_add_cst(si->lpp, buf, lpp_less, 0.0);
+
+ /* reg_out - reload - remat - live_range <= 0 */
+ lpp_set_factor_fast(si->lpp, cst, spill->reg_out, 1.0);
+ if(reload != ILP_UNDEF) lpp_set_factor_fast(si->lpp, cst, reload, -1.0);
+ lpp_set_factor_fast(si->lpp, cst, op->attr.live_range.ilp, -1.0);
+ foreach_pre_remat(si, 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);
+ }
+ }
+ /* maybe we should also assure that reg_out >= live_range etc. */
+ }
+
+#ifndef NO_MEMCOPIES
+ insert_mem_copy_position(si, live, bb);
+#endif
+
+ /*
+ * start new live ranges for values used by remats at end of block
+ * and assure the remat args are available
+ */
+ foreach_pre_remat(si, bb, tmp) {
+ op_t *remat_op = get_irn_link(tmp);
+ int n;
+
+ for (n=get_irn_arity(tmp)-1; n>=0; --n) {
+ ir_node *remat_arg = get_irn_n(tmp, n);
+ op_t *arg_op = get_irn_link(remat_arg);
+ ilp_var_t prev_lr;
+
+ if(!has_reg_class(si, remat_arg)) continue;
+
+ /* if value is becoming live through use by remat */
+ if(!pset_find_ptr(live, remat_arg)) {
+ ir_snprintf(buf, sizeof(buf), "lr_%N_end%N", remat_arg, bb);
+ prev_lr = lpp_add_var(si->lpp, buf, lpp_binary, 0.0);
+
+ arg_op->attr.live_range.ilp = prev_lr;
+ arg_op->attr.live_range.op = bb;
+
+ DBG((si->dbg, LEVEL_4, " value %+F becoming live through use by remat at end of block %+F\n", remat_arg, tmp));
+
+ pset_insert_ptr(live, remat_arg);
+ add_to_spill_bb(si, bb, remat_arg);
+ }
+
+ /* remat <= live_rang(remat_arg) [ + reload(remat_arg) ] */
+ ir_snprintf(buf, sizeof(buf), "req_remat_%N_arg_%N", tmp, remat_arg);
+ cst = lpp_add_cst(si->lpp, buf, lpp_less, 0.0);
+
+ lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, 1.0);
+ lpp_set_factor_fast(si->lpp, cst, arg_op->attr.live_range.ilp, -1.0);
+
+ /* use reload placed for this argument */
+ if(spill_bb->reloads) {
+ keyval_t *keyval = set_find_keyval(spill_bb->reloads, remat_arg);
+
+ if(keyval) {
+ ilp_var_t reload = PTR_TO_INT(keyval->val);
+
+ lpp_set_factor_fast(si->lpp, cst, reload, -1.0);
+ }
+ }
+ }
+ }
+ DBG((si->dbg, LEVEL_4, "\t %d values live at end of block %+F\n", pset_count(live), bb));
+
+
+
+
+ /**************************************
+ * B A S I C B L O C K B O D Y
+ **************************************/
+
+ sched_foreach_reverse_from(sched_block_last_noncf(si, bb), irn) {