+ /* 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);
+
+ 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;
+
+ 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 remat2s <= 1 + n_remats*live_range */
+ ir_snprintf(buf, sizeof(buf), "dying_lr_%N_%N", irn, bb);
+ cst = lpp_add_cst_uniq(si->lpp, buf, lpp_less, 1.0);
+ }
+ lpp_set_factor_fast(si->lpp, cst, remat_op->attr.remat.ilp, 1.0);
+ ++n_remats;
+ break;
+ }
+ }
+ }
+ if(cst != ILP_UNDEF && op->attr.live_range.ilp != ILP_UNDEF) {
+ lpp_set_factor_fast(si->lpp, cst, op->attr.live_range.ilp, -n_remats);
+ }
+ }
+
+ /* first live ranges from reg_ins */
+ pset_foreach(live, irn) {
+ op_t *op = get_irn_link(irn);
+
+ 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);