+static void
+get_live_end(spill_ilp_t * si, ir_node * bb, pset * live)
+{
+ ir_node *irn;
+ int i;
+
+ be_lv_foreach(si->lv, bb, be_lv_state_end, i) {
+ irn = be_lv_get_irn(si->lv, bb, i);
+
+ if (has_reg_class(si, irn) && !pset_find_ptr(si->all_possible_remats, irn)) {
+ pset_insert_ptr(live, irn);
+ }
+ }
+
+ irn = sched_last(bb);
+
+ /* all values eaten by control flow operations are also live until the end of the block */
+ sched_foreach_reverse(bb, irn) {
+ int i;
+
+ if(!sched_skip_cf_predicator(irn, si->chordal_env->birg->main_env->arch_env)) break;
+
+ for(i=get_irn_arity(irn)-1; i>=0; --i) {
+ ir_node *arg = get_irn_n(irn,i);
+
+ if(has_reg_class(si, arg)) {
+ pset_insert_ptr(live, arg);
+ }
+ }
+ }
+}
+
+/**
+ * Inserts ILP-constraints and variables for memory copying before the given position
+ */
+static void
+insert_mem_copy_position(spill_ilp_t * si, pset * live, const ir_node * block)
+{
+ const ir_node *succ;
+ const ir_edge_t *edge;
+ spill_bb_t *spill_bb = get_irn_link(block);
+ ir_node *phi;
+ int pos;
+ ilp_cst_t cst;
+ ilp_var_t copyreg;
+ char buf[256];
+ ir_node *tmp;
+
+
+ assert(edges_activated(current_ir_graph));
+
+ edge = get_block_succ_first(block);
+ if(!edge) return;
+
+ succ = edge->src;
+ pos = edge->pos;
+
+ 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_default(si->lpp, buf, lpp_binary, 0.0, 1.0);
+
+ ir_snprintf(buf, sizeof(buf), "check_copyreg_%N", block);
+ cst = lpp_add_cst_uniq(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_%N", block, phi, to_copy);
+ cst = lpp_add_cst_uniq(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_%N", block, phi, to_copy);
+ cst = lpp_add_cst_uniq(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);
+ }
+}
+
+