+ stat_ev_tim_pop("beilpsched_cst_projkeep");
+}
+#endif /* if 0 */
+
+/***************************************************
+ * _____ _ _____ _
+ * |_ _| | | __ \ (_)
+ * | | | | | |__) | _ __ ___ __ _ _ _ __
+ * | | | | | ___/ | '_ ` _ \ / _` | | '_ \
+ * _| |_| |____| | | | | | | | (_| | | | | |
+ * |_____|______|_| |_| |_| |_|\__,_|_|_| |_|
+ *
+ ***************************************************/
+
+/**
+ * Create the ilp (add variables, build constraints, solve, build schedule from solution).
+ */
+static void create_ilp(ir_node *block, void *walk_env) {
+ be_ilpsched_env_t *env = walk_env;
+ be_ilpsched_irn_t *block_node = get_ilpsched_irn(env, block);
+ ilpsched_block_attr_t *ba = get_ilpsched_block_attr(block_node);
+ FILE *logfile = NULL;
+ lpp_t *lpp = NULL;
+ int need_heur = 0;
+ struct obstack var_obst;
+ char name[1024];
+
+ DBG((env->dbg, 255, "\n\n\n=========================================\n"));
+ DBG((env->dbg, 255, " ILP Scheduling for %+F\n", block));
+ DBG((env->dbg, 255, "=========================================\n\n"));
+
+ DBG((env->dbg, LEVEL_1, "Creating ILP Variables for nodes in %+F (%u interesting nodes, %u max steps)\n",
+ block, ba->n_interesting_nodes, ba->max_steps));
+
+ /* notify backend and get block environment */
+ env->block_env = be_ilp_sched_init_block_ilp_schedule(env->sel, block);
+
+ /* if we have less than two interesting nodes, there is no need to create the ILP */
+ if (ba->n_interesting_nodes > 1) {
+ double fact_var = ba->n_interesting_nodes > 25 ? 2.3 : 3;
+ double fact_cst = ba->n_interesting_nodes > 25 ? 3 : 4.5;
+ int base_num = ba->n_interesting_nodes * ba->n_interesting_nodes;
+ int estimated_n_var = (int)((double)base_num * fact_var);
+ int estimated_n_cst = (int)((double)base_num * fact_cst);
+
+ DBG((env->dbg, LEVEL_1, "Creating LPP with estimated numbers: %d vars, %d cst\n",
+ estimated_n_var, estimated_n_cst));
+ (void) estimated_n_var;
+
+ /* set up the LPP object */
+ snprintf(name, sizeof(name), "ilp scheduling IRG %s", get_entity_ld_name(get_irg_entity(env->irg)));
+
+ lpp = new_lpp_userdef(
+ (const char *)name,
+ lpp_minimize,
+ estimated_n_cst, /* num vars */
+ estimated_n_cst + 1, /* num cst */
+ 1.3); /* grow factor */
+ obstack_init(&var_obst);
+
+ /* create ILP variables */
+ create_variables(env, lpp, block_node, &var_obst);
+
+ /* create ILP constraints */
+ DBG((env->dbg, LEVEL_1, "Creating constraints for nodes in %+F:\n", block));
+ create_assignment_and_precedence_constraints(env, lpp, block_node);
+ create_ressource_constraints(env, lpp, block_node);
+ create_bundle_constraints(env, lpp, block_node);
+ create_branch_constraint(env, lpp, block_node);
+ //create_proj_keep_constraints(env, lpp, block_node);
+
+ if (env->opts->regpress) {
+ create_alive_nodes_constraint(env, lpp, block_node);
+ create_alive_livein_nodes_constraint(env, lpp, block_node);
+ create_pressure_alive_constraint(env, lpp, block_node);
+ }
+
+ DBG((env->dbg, LEVEL_1, "ILP to solve: %u variables, %u constraints\n", lpp->var_next, lpp->cst_next));
+
+ /* debug stuff, dump lpp when debugging is on */
+ DEBUG_ONLY({
+ if (firm_dbg_get_mask(env->dbg) > 1) {
+ char buf[1024];
+ FILE *f;
+
+ snprintf(buf, sizeof(buf), "lpp_block_%lu.txt", get_irn_node_nr(block));
+ f = fopen(buf, "w");
+ lpp_dump_plain(lpp, f);
+ fclose(f);
+ snprintf(buf, sizeof(buf), "lpp_block_%lu.mps", get_irn_node_nr(block));
+ lpp_dump(lpp, buf);
+ }
+ })
+
+ /* set solve time limit */
+ lpp_set_time_limit(lpp, env->opts->time_limit);
+
+ /* set logfile if requested */
+ if (strlen(env->opts->log_file) > 0) {
+ if (strcasecmp(env->opts->log_file, "stdout") == 0)
+ lpp_set_log(lpp, stdout);
+ else if (strcasecmp(env->opts->log_file, "stderr") == 0)
+ lpp_set_log(lpp, stderr);
+ else {
+ logfile = fopen(env->opts->log_file, "w");
+ if (! logfile)
+ fprintf(stderr, "Could not open logfile '%s'! Logging disabled.\n", env->opts->log_file);
+ else
+ lpp_set_log(lpp, logfile);
+ }
+ }
+
+ /* solve the ILP */
+ lpp_solve_net(lpp, env->main_env->options->ilp_server, env->main_env->options->ilp_solver);
+
+ if (logfile)
+ fclose(logfile);
+
+ /* check for valid solution */
+ if (! lpp_is_sol_valid(lpp)) {
+ DEBUG_ONLY({
+ char buf[1024];
+ FILE *f;
+
+ if (firm_dbg_get_mask(env->dbg) >= 2) {
+ snprintf(buf, sizeof(buf), "lpp_block_%lu.infeasible.txt", get_irn_node_nr(block));
+ f = fopen(buf, "w");
+ lpp_dump_plain(lpp, f);
+ fclose(f);
+ snprintf(buf, sizeof(buf), "lpp_block_%lu.infeasible.mps", get_irn_node_nr(block));
+ lpp_dump(lpp, buf);
+ dump_ir_block_graph(env->irg, "-infeasible");
+ }
+ })
+
+ ir_fprintf(stderr, "ILP found no solution within time (%+F, %+F), falling back to heuristics.\n", block, env->irg);
+ need_heur = 1;
+ }
+
+ DBG((env->dbg, LEVEL_1, "\nSolution:\n"));
+ DBG((env->dbg, LEVEL_1, "\tsend time: %g sec\n", lpp->send_time / 1000000.0));
+ DBG((env->dbg, LEVEL_1, "\treceive time: %g sec\n", lpp->recv_time / 1000000.0));
+ DBG((env->dbg, LEVEL_1, "\tmatrix: %u elements, density %.2f%%, size %.2fMB\n", lpp->n_elems, lpp->density, (double)lpp->matrix_mem / 1024.0 / 1024.0));
+ DBG((env->dbg, LEVEL_1, "\titerations: %d\n", lpp->iterations));
+ DBG((env->dbg, LEVEL_1, "\tsolution time: %g\n", lpp->sol_time));
+ DBG((env->dbg, LEVEL_1, "\tobjective function: %g\n", LPP_VALUE_IS_0(lpp->objval) ? 0.0 : lpp->objval));
+ DBG((env->dbg, LEVEL_1, "\tbest bound: %g\n", LPP_VALUE_IS_0(lpp->best_bound) ? 0.0 : lpp->best_bound));
+
+ DBG((env->dbg, LEVEL_1, "variables used %u bytes\n", obstack_memory_used(&var_obst)));
+ }