+ /* copies are not for free */
+ ir_snprintf(buf, sizeof(buf), "copy_%N_%N", arg, spill->irn);
+ var = lpp_add_var_default(si->lpp, buf, lpp_binary, opt_cost_spill * freq, 1.0);
+
+ for(m=n; m>=0; --m) {
+ const ir_node *arg2 = get_irn_n(spill->irn, m);
+
+ if(arg==arg2) {
+ op->attr.live_range.args.copies[m] = var;
+ }
+ }
+
+#if 0
+ /* copy <= mem_in */
+ ir_snprintf(buf, sizeof(buf), "nocopy_%N_%N", arg, spill->irn);
+ cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
+ lpp_set_factor_fast(si->lpp, cst, var, 1.0);
+ lpp_set_factor_fast(si->lpp, cst, spill->mem_in, -1.0);
+#endif
+ }
+ }
+ }
+ }
+
+ foreach_post_remat(bb, tmp) {
+ int n;
+
+ for (n=get_irn_arity(tmp)-1; n>=0; --n) {
+ ir_node *remat_arg = get_irn_n(tmp, n);
+
+ if(!has_reg_class(si, remat_arg)) continue;
+
+ /* if value is becoming live through use by remat2 */
+ if(!pset_find_ptr(live, remat_arg)) {
+ op_t *remat_arg_op = get_irn_link(remat_arg);
+ ilp_cst_t nomem;
+
+ DBG((si->dbg, LEVEL_3, " value %+F becoming live through use by remat2 at bb start %+F\n", remat_arg, tmp));
+
+ pset_insert_ptr(live, remat_arg);
+ spill = add_to_spill_bb(si, bb, remat_arg);
+ remat_arg_op->attr.live_range.ilp = ILP_UNDEF;
+
+ /* we need reg_in and mem_in for this value; they will be referenced later */
+ ir_snprintf(buf, sizeof(buf), "reg_in_%N_%N", remat_arg, bb);
+ spill->reg_in = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 0.0);
+ ir_snprintf(buf, sizeof(buf), "mem_in_%N_%N", remat_arg, bb);
+ spill->mem_in = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 1.0);
+
+
+ /* optimization: all memory stuff should be 0, for we do not want to insert reloads for remats */
+ ir_snprintf(buf, sizeof(buf), "nomem_%N_%N", remat_arg, bb);
+ nomem = lpp_add_cst_uniq(si->lpp, buf, lpp_equal, 0.0);
+
+ lpp_set_factor_fast(si->lpp, nomem, spill->spill, 1.0);
+ 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, nomem, reload, 1.0);
+ }
+ }
+ }
+ }
+ }
+
+ /* L\U is empty at bb start */
+ /* arg is live throughout epilog if it is reg_in into this block */
+
+ /* check the register pressure at the beginning of the block
+ * including remats
+ */
+ /* reg_in entspricht post_use */
+
+ ir_snprintf(buf, sizeof(buf), "check_start_%N", bb);
+ cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, si->n_regs);
+
+ pset_foreach(live, irn) {
+ ilp_cst_t nospill;
+
+ spill = set_find_spill(spill_bb->ilp, irn);
+ assert(spill);
+
+ ir_snprintf(buf, sizeof(buf), "reg_in_%N_%N", irn, bb);
+ spill->reg_in = lpp_add_var_default(si->lpp, buf, lpp_binary, 0.0, 0.0);
+
+ lpp_set_factor_fast(si->lpp, cst, spill->reg_in, 1.0);
+
+ /* spill + mem_in <= 1 */
+ ir_snprintf(buf, sizeof(buf), "nospill_%N_%N", irn, bb);
+ nospill = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 1);
+
+ lpp_set_factor_fast(si->lpp, nospill, spill->mem_in, 1.0);
+ lpp_set_factor_fast(si->lpp, nospill, spill->spill, 1.0);
+
+ } /* post_remats are NOT included in register pressure check because
+ they do not increase regpressure */
+
+ /* mem_in/reg_in for live_in values, especially phis and their arguments */
+ pset_foreach(live, irn) {
+ int p = 0,
+ n;
+
+ spill = set_find_spill(spill_bb->ilp, irn);
+ assert(spill && spill->irn == irn);
+
+ if(is_Phi(irn) && get_nodes_block(irn) == bb) {
+ for (n=get_Phi_n_preds(irn)-1; n>=0; --n) {
+ ilp_cst_t mem_in,
+ reg_in;
+ ir_node *phi_arg = get_Phi_pred(irn, n);
+ ir_node *bb_p = get_Block_cfgpred_block(bb, n);
+ spill_bb_t *spill_bb_p = get_irn_link(bb_p);
+ spill_t *spill_p;
+ op_t *op = get_irn_link(irn);
+
+ /* although the phi is in the right regclass one or more of
+ * its arguments can be in a different one or at least to
+ * ignore
+ */
+ if(has_reg_class(si, phi_arg)) {
+ /* mem_in < mem_out_arg + copy */
+ ir_snprintf(buf, sizeof(buf), "mem_in_%N_%N-%d", irn, bb, p);
+ mem_in = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
+
+ /* reg_in < reg_out_arg */
+ ir_snprintf(buf, sizeof(buf), "reg_in_%N_%N-%d", irn, bb, p++);
+ reg_in = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
+
+ lpp_set_factor_fast(si->lpp, mem_in, spill->mem_in, 1.0);
+ lpp_set_factor_fast(si->lpp, reg_in, spill->reg_in, 1.0);
+
+ spill_p = set_find_spill(spill_bb_p->ilp, phi_arg);
+ assert(spill_p);
+
+ lpp_set_factor_fast(si->lpp, mem_in, spill_p->mem_out, -1.0);
+ if(opt_memcopies)
+ lpp_set_factor_fast(si->lpp, mem_in, op->attr.live_range.args.copies[n], -1.0);
+
+ lpp_set_factor_fast(si->lpp, reg_in, spill_p->reg_out, -1.0);
+ }
+ }
+ } else {
+ /* else assure the value arrives on all paths in the same resource */
+
+ for (n=get_Block_n_cfgpreds(bb)-1; n>=0; --n) {
+ ilp_cst_t mem_in,
+ reg_in;
+ ir_node *bb_p = get_Block_cfgpred_block(bb, n);
+ spill_bb_t *spill_bb_p = get_irn_link(bb_p);
+ spill_t *spill_p;
+
+ ir_snprintf(buf, sizeof(buf), "mem_in_%N_%N-%d", irn, bb, p);
+ mem_in = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
+ ir_snprintf(buf, sizeof(buf), "reg_in_%N_%N-%d", irn, bb, p++);
+ reg_in = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 0.0);
+
+ lpp_set_factor_fast(si->lpp, mem_in, spill->mem_in, 1.0);
+ lpp_set_factor_fast(si->lpp, reg_in, spill->reg_in, 1.0);
+
+ spill_p = set_find_spill(spill_bb_p->ilp, irn);
+ assert(spill_p);
+
+ lpp_set_factor_fast(si->lpp, mem_in, spill_p->mem_out, -1.0);
+ lpp_set_factor_fast(si->lpp, reg_in, spill_p->reg_out, -1.0);
+ }
+ }
+ }
+
+ foreach_post_remat(bb, tmp) {
+ int n;
+
+ for (n=get_irn_arity(tmp)-1; n>=0; --n) {
+ ir_node *remat_arg = get_irn_n(tmp, n);
+ op_t *remat_op = get_irn_link(tmp);
+
+ if(!has_reg_class(si, remat_arg)) continue;
+
+ spill = set_find_spill(spill_bb->ilp, remat_arg);
+ assert(spill);
+
+ /* remat <= reg_in_argument */
+ ir_snprintf(buf, sizeof(buf), "req_remat2_%N_%N_arg_%N", tmp, bb, remat_arg);
+ cst = lpp_add_cst(si->lpp, buf, lpp_less, 0.0);
+ lpp_set_factor_fast(si->lpp, cst, spill->reg_in, -1.0);
+ lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, 1.0);
+ }
+ }
+
+ pset_foreach(live, irn) {
+ const op_t *op = get_irn_link(irn);
+ const ir_node *remat;
+ int n_remats = 0;
+
+ if(op->attr.live_range.ilp == ILP_UNDEF) continue;
+
+ cst = ILP_UNDEF;
+
+ foreach_post_remat(bb, remat) {
+ int n;
+
+ for (n=get_irn_arity(remat)-1; n>=0; --n) {
+ const ir_node *arg = get_irn_n(remat, n);
+
+ if(arg == irn) {
+ const op_t *remat_op = get_irn_link(remat);
+
+ if(cst == ILP_UNDEF) {
+ /* \sum post_remat <= 1 + #post_remats * next(lr) */
+ ir_snprintf(buf, sizeof(buf), "remat2_%N_%N_arg_%N", remat, bb, irn);
+ cst = lpp_add_cst(si->lpp, buf, lpp_less, 1.0);
+ }