Commit 81053173 authored by Sebastian Hack's avatar Sebastian Hack
Browse files

Factored copy minimzation out

parent 118267fc
......@@ -119,7 +119,6 @@ int nodes_interfere(const be_chordal_env_t *env, const ir_node *a, const ir_node
static be_ra_chordal_opts_t options = {
BE_CH_DUMP_NONE,
BE_CH_SPILL_BELADY,
BE_CH_COPYMIN_HEUR2,
BE_CH_IFG_STD,
BE_CH_LOWER_PERM_SWAP,
BE_CH_VRFY_WARN,
......@@ -148,19 +147,6 @@ static const lc_opt_enum_int_items_t spill_items[] = {
{ NULL, 0 }
};
static const lc_opt_enum_int_items_t copymin_items[] = {
{ "none", BE_CH_COPYMIN_NONE },
{ "heur1", BE_CH_COPYMIN_HEUR1 },
{ "heur2", BE_CH_COPYMIN_HEUR2 },
{ "heur3", BE_CH_COPYMIN_HEUR3 },
{ "stat", BE_CH_COPYMIN_STAT },
{ "park", BE_CH_COPYMIN_PARK_MOON },
#ifdef WITH_ILP
{ "ilp", BE_CH_COPYMIN_ILP },
#endif /* WITH_ILP */
{ NULL, 0 }
};
static const lc_opt_enum_int_items_t ifg_flavor_items[] = {
{ "std", BE_CH_IFG_STD },
{ "fast", BE_CH_IFG_FAST },
......@@ -206,10 +192,6 @@ static lc_opt_enum_int_var_t spill_var = {
&options.spill_method, spill_items
};
static lc_opt_enum_int_var_t copymin_var = {
&options.copymin_method, copymin_items
};
static lc_opt_enum_int_var_t ifg_flavor_var = {
&options.ifg_flavor, ifg_flavor_items
};
......@@ -226,9 +208,6 @@ static lc_opt_enum_int_var_t be_ch_vrfy_var = {
&options.vrfy_option, be_ch_vrfy_items
};
/** Dump copy minimization statistics. */
static int be_copymin_stats = 0;
/** Enable extreme live range splitting. */
static int be_elr_split = 0;
......@@ -237,12 +216,10 @@ static int be_loop_weight = 9;
static const lc_opt_table_entry_t be_chordal_options[] = {
LC_OPT_ENT_ENUM_INT ("spill", "spill method (belady, morgan or remat)", &spill_var),
LC_OPT_ENT_ENUM_PTR ("copymin", "copymin method (none, heur1, heur2, ilp1, ilp2 or stat)", &copymin_var),
LC_OPT_ENT_ENUM_PTR ("ifg", "interference graph flavour (std, fast, clique, pointer, list, check)", &ifg_flavor_var),
LC_OPT_ENT_ENUM_PTR ("perm", "perm lowering options (copy or swap)", &lower_perm_var),
LC_OPT_ENT_ENUM_MASK("dump", "select dump phases", &dump_var),
LC_OPT_ENT_ENUM_PTR ("vrfy", "verify options (off, warn, assert)", &be_ch_vrfy_var),
LC_OPT_ENT_BOOL ("copymin_stats", "dump statistics of copy minimization", &be_copymin_stats),
LC_OPT_ENT_BOOL ("elrsplit", "enable extreme live range splitting", &be_elr_split),
LC_OPT_ENT_INT ("loop_weight", "assumed amount of loop iterations for guessing the execution frequency", &be_loop_weight),
{ NULL }
......@@ -297,7 +274,7 @@ FILE *be_chordal_open(const be_chordal_env_t *env, const char *prefix, const cha
{
char buf[1024];
ir_snprintf(buf, sizeof(buf), "%s%F_%s.%s", prefix, env->irg, env->cls->name, suffix);
ir_snprintf(buf, sizeof(buf), "%s%F_%s%s", prefix, env->irg, env->cls->name, suffix);
return fopen(buf, "wt");
}
......@@ -305,24 +282,24 @@ void check_ifg_implementations(be_chordal_env_t *chordal_env)
{
FILE *f;
f = be_chordal_open(chordal_env, "std", "log");
f = be_chordal_open(chordal_env, "std", ".log");
chordal_env->ifg = be_ifg_std_new(chordal_env);
be_ifg_check_sorted_to_file(chordal_env->ifg, f);
fclose(f);
f = be_chordal_open(chordal_env, "list", "log");
f = be_chordal_open(chordal_env, "list", ".log");
be_ifg_free(chordal_env->ifg);
chordal_env->ifg = be_ifg_list_new(chordal_env);
be_ifg_check_sorted_to_file(chordal_env->ifg, f);
fclose(f);
f = be_chordal_open(chordal_env, "clique", "log");
f = be_chordal_open(chordal_env, "clique", ".log");
be_ifg_free(chordal_env->ifg);
chordal_env->ifg = be_ifg_clique_new(chordal_env);
be_ifg_check_sorted_to_file(chordal_env->ifg, f);
fclose(f);
f = be_chordal_open(chordal_env, "pointer", "log");
f = be_chordal_open(chordal_env, "pointer", ".log");
be_ifg_free(chordal_env->ifg);
chordal_env->ifg = be_ifg_pointer_new(chordal_env);
be_ifg_check_sorted_to_file(chordal_env->ifg, f);
......@@ -565,67 +542,8 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
/* copy minimization */
BE_TIMER_PUSH(ra_timer.t_copymin);
co = NULL;
if (options.copymin_method != BE_CH_COPYMIN_NONE && options.copymin_method != BE_CH_COPYMIN_STAT) {
co = new_copy_opt(&chordal_env, co_get_costs_exec_freq);
co_build_ou_structure(co);
co_build_graph_structure(co);
if(be_copymin_stats) {
ir_printf("%30F %10s %7d%7d%7d%7d", current_ir_graph, chordal_env.cls->name,
co_get_max_copy_costs(co), co_get_copy_costs(co), co_get_inevit_copy_costs(co), co_get_lower_bound(co));
}
/* Dump the interference graph in Appel's format. */
if(options.dump_flags & BE_CH_DUMP_APPEL) {
FILE *f = be_chordal_open(&chordal_env, "appel-", "apl");
co_dump_appel_graph(co, f);
fclose(f);
}
}
switch(options.copymin_method) {
case BE_CH_COPYMIN_HEUR1:
co_solve_heuristic(co);
break;
case BE_CH_COPYMIN_HEUR2:
co_solve_heuristic_new(co);
break;
case BE_CH_COPYMIN_HEUR3:
co_solve_heuristic_java(co);
break;
case BE_CH_COPYMIN_PARK_MOON:
co_solve_park_moon(co);
break;
case BE_CH_COPYMIN_STAT:
co_compare_solvers(&chordal_env);
break;
#ifdef WITH_ILP
case BE_CH_COPYMIN_ILP:
co_solve_ilp2(co, 60.0);
break;
#endif /* WITH_ILP */
case BE_CH_COPYMIN_NONE:
default:
break;
}
if (co) {
if(be_copymin_stats) {
int optimizable_costs = co_get_max_copy_costs(co) - co_get_lower_bound(co);
int remaining = co_get_copy_costs(co);
int evitable = remaining - co_get_lower_bound(co);
if(optimizable_costs > 0)
printf("%5d %5.2f\n", remaining, (evitable * 100.0) / optimizable_costs);
else
printf("%5d %5s\n", remaining, "-");
}
co_free_graph_structure(co);
co_free_ou_structure(co);
free_copy_opt(co);
}
co_driver(&chordal_env);
BE_TIMER_POP(ra_timer.t_copymin);
dump(BE_CH_DUMP_COPYMIN, irg, chordal_env.cls, "-copymin", dump_ir_block_graph_sched);
BE_TIMER_PUSH(ra_timer.t_verify);
......@@ -650,9 +568,6 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
}
BE_TIMER_POP(ra_timer.t_verify);
if (options.copymin_method == BE_CH_COPYMIN_STAT)
copystat_dump(irg);
be_ifg_free(chordal_env.ifg);
pmap_destroy(chordal_env.border_heads);
bitset_free(chordal_env.ignore_colors);
......
......@@ -112,15 +112,6 @@ enum {
BE_CH_DUMP_APPEL = (1 << 9),
BE_CH_DUMP_ALL = 2 * BE_CH_DUMP_LOWER - 1,
/* copymin method */
BE_CH_COPYMIN_NONE = 0,
BE_CH_COPYMIN_HEUR1 = 1,
BE_CH_COPYMIN_HEUR2 = 2,
BE_CH_COPYMIN_HEUR3 = 3,
BE_CH_COPYMIN_STAT = 4,
BE_CH_COPYMIN_ILP = 5,
BE_CH_COPYMIN_PARK_MOON = 6,
/* ifg flavor */
BE_CH_IFG_STD = 1,
BE_CH_IFG_FAST = 2,
......@@ -142,7 +133,6 @@ enum {
struct _be_ra_chordal_opts_t {
int dump_flags;
int spill_method;
int copymin_method;
int ifg_flavor;
int lower_perm_opt;
int vrfy_option;
......
......@@ -589,6 +589,5 @@ int co_solve_heuristic(copy_opt_t *co) {
ou_optimize(curr);
del_pset(pinned_global);
return 0;
}
......@@ -1217,7 +1217,7 @@ static be_ifg_dump_dot_cb_t ifg_dot_cb = {
};
void co_solve_heuristic_new(copy_opt_t *co)
int co_solve_heuristic_new(copy_opt_t *co)
{
char buf[256];
co2_t env;
......@@ -1257,4 +1257,5 @@ void co_solve_heuristic_new(copy_opt_t *co)
writeback_colors(&env);
phase_free(&env.ph);
return 0;
}
......@@ -91,7 +91,7 @@ static void set_admissible_regs(java_coal_t *coal, copy_opt_t *co, ir_node *irn,
}
}
void co_solve_heuristic_java(copy_opt_t *co)
int co_solve_heuristic_java(copy_opt_t *co)
{
be_ifg_t *ifg = co->cenv->ifg;
void *nodes_it = be_ifg_nodes_iter_alloca(ifg);
......@@ -208,4 +208,5 @@ void co_solve_heuristic_java(copy_opt_t *co)
java_coal_destroy(coal);
bitset_free(nodes);
return 0;
}
......@@ -14,6 +14,41 @@
#ifdef WITH_ILP
#define DUMP_ILP 1
#define DUMP_SOL 2
static int time_limit = 60;
static int solve_net = 1;
static int dump_flags = 0;
#ifdef WITH_LIBCORE
#include <libcore/lc_opts.h>
#include <libcore/lc_opts_enum.h>
static const lc_opt_enum_mask_items_t dump_items[] = {
{ "ilp", DUMP_ILP },
{ "sol", DUMP_SOL },
{ NULL, 0 }
};
static lc_opt_enum_mask_var_t dump_var = {
&dump_flags, dump_items
};
static const lc_opt_table_entry_t options[] = {
LC_OPT_ENT_INT ("limit", "time limit for solving in seconds (0 for unlimited, default 60)", &time_limit),
LC_OPT_ENT_BOOL ("net", "solve over the net (default: yes)", &solve_net),
LC_OPT_ENT_ENUM_MASK("dump", "dump flags (ilp, sol)", &dump_var),
{ NULL }
};
void be_co_ilp_register_options(lc_opt_entry_t *grp)
{
lc_opt_entry_t *ilp_grp = lc_opt_get_grp(grp, "ilp");
lc_opt_add_table(ilp_grp, options);
}
#endif
#include "becopyilp_t.h"
#include "beifg_t.h"
......@@ -148,34 +183,38 @@ ilp_env_t *new_ilp_env(copy_opt_t *co, ilp_callback build, ilp_callback apply, v
ilp_env_t *res = xmalloc(sizeof(*res));
assert(res);
res->co = co;
res->build = build;
res->apply = apply;
res->env = env;
res->sr = new_size_red(co);
res->co = co;
res->build = build;
res->apply = apply;
res->env = env;
res->sr = new_size_red(co);
return res;
}
lpp_sol_state_t ilp_go(ilp_env_t *ienv) {
FILE *f;
char buf[256];
be_main_env_t *main_env = ienv->co->cenv->birg->main_env;
sr_remove(ienv->sr);
ienv->build(ienv);
lpp_set_time_limit(ienv->lp, time_limit);
if(solve_net)
lpp_solve_net(ienv->lp, main_env->options->ilp_server, main_env->options->ilp_solver);
else {
#ifdef LPP_SOLVE_NET
lpp_solve_net(ienv->lp, main_env->options->ilp_server, main_env->options->ilp_solver);
fprintf(stderr, "can only solve ilp over the net\n");
#else
lpp_solve_cplex(ienv->lp);
lpp_solve_cplex(ienv->lp);
#endif
}
snprintf(buf, sizeof(buf), "%s.ilp", ienv->co->name);
f = fopen(buf, "wt");
lpp_dump_plain(ienv->lp, f);
fclose(f);
if(dump_flags & DUMP_ILP) {
FILE *f = be_chordal_open(ienv->co->cenv, "", "-co.ilp");
lpp_dump_plain(ienv->lp, f);
fclose(f);
}
ienv->apply(ienv);
......
......@@ -503,7 +503,7 @@ static void ilp2_apply(ilp_env_t *ienv) {
#endif
}
int co_solve_ilp2(copy_opt_t *co, double time_limit) {
int co_solve_ilp2(copy_opt_t *co) {
lpp_sol_state_t sol_state;
ilp_env_t *ienv;
local_env_t my;
......@@ -511,7 +511,7 @@ int co_solve_ilp2(copy_opt_t *co, double time_limit) {
ASSERT_OU_AVAIL(co); //See build_clique_st
ASSERT_GS_AVAIL(co);
my.time_limit = time_limit;
my.time_limit = 0;
my.first_x_var = -1;
my.last_x_var = -1;
my.nr_2_irn = pmap_create();
......
......@@ -39,16 +39,92 @@
#include "beinsn_t.h"
#include "besched_t.h"
#define DUMP_BEFORE 1
#define DUMP_AFTER 2
#define DUMP_APPEL 4
#define DUMP_ALL 2 * DUMP_APPEL - 1
#define COST_FUNC_FREQ 1
#define COST_FUNC_LOOP 2
#define COST_FUNC_ALL_ONE 3
static int dump_flags = 0;
static int style_flags = 0;
static int do_stats = 0;
static cost_fct_t cost_func = co_get_costs_exec_freq;
static int algo = CO_ALGO_HEUR2;
#ifdef WITH_LIBCORE
static const lc_opt_enum_mask_items_t dump_items[] = {
{ "before", DUMP_BEFORE },
{ "after", DUMP_AFTER },
{ "appel", DUMP_APPEL },
{ "all", DUMP_ALL },
{ NULL, 0 }
};
static const lc_opt_enum_mask_items_t style_items[] = {
{ "color", CO_IFG_DUMP_COLORS },
{ "labels", CO_IFG_DUMP_LABELS },
{ "constr", CO_IFG_DUMP_CONSTR },
{ "shape", CO_IFG_DUMP_SHAPE },
{ "full", 2 * CO_IFG_DUMP_SHAPE - 1 },
{ NULL, 0 }
};
static const lc_opt_enum_mask_items_t algo_items[] = {
{ "heur", CO_ALGO_HEUR },
{ "heur2", CO_ALGO_HEUR2 },
{ "heur3", CO_ALGO_HEUR3 },
{ "ilp", CO_ALGO_ILP },
{ NULL, 0 }
};
static const lc_opt_enum_func_ptr_items_t cost_func_items[] = {
{ "freq", co_get_costs_exec_freq },
{ "loop", co_get_costs_loop_depth },
{ "one", co_get_costs_all_one },
{ NULL, 0 }
};
static lc_opt_enum_mask_var_t dump_var = {
&dump_flags, dump_items
};
static lc_opt_enum_mask_var_t style_var = {
&style_flags, style_items
};
static lc_opt_enum_mask_var_t algo_var = {
&algo, algo_items
};
static lc_opt_enum_func_ptr_var_t cost_func_var = {
&cost_func, cost_func_items
};
static const lc_opt_table_entry_t options[] = {
LC_OPT_ENT_ENUM_INT ("algo", "select copy optimization algo (heur, heur2, heur3, ilp)", &algo_var),
LC_OPT_ENT_ENUM_FUNC_PTR ("cost", "select a cost function (freq, loop, one)", &cost_func_var),
LC_OPT_ENT_ENUM_MASK ("dump", "dump ifg before or after copy optimization", &dump_var),
LC_OPT_ENT_ENUM_MASK ("style", "dump style for ifg dumping", &style_var),
LC_OPT_ENT_BOOL ("stats", "dump statistics after each optimization", &do_stats),
{ NULL }
};
/* Insert additional options registration functions here. */
extern void be_co_ilp_register_options(lc_opt_entry_t *grp);
extern void be_co2_register_options(lc_opt_entry_t *grp);
extern void be_co3_register_options(lc_opt_entry_t *grp);
void co_register_options(lc_opt_entry_t *grp)
{
be_co2_register_options(grp);
be_co3_register_options(grp);
lc_opt_entry_t *co_grp = lc_opt_get_grp(grp, "co");
lc_opt_add_table(co_grp, options);
be_co2_register_options(co_grp);
be_co3_register_options(co_grp);
be_co_ilp_register_options(co_grp);
}
#endif
......@@ -1067,12 +1143,12 @@ void co_dump_appel_graph_cliques(const copy_opt_t *co, FILE *f)
}
/*
___ _____ ____ ____ ___ _____ ____ _
|_ _| ___/ ___| | _ \ / _ \_ _| | _ \ _ _ _ __ ___ _ __ (_)_ __ __ _
| || |_ | | _ | | | | | | || | | | | | | | | '_ ` _ \| '_ \| | '_ \ / _` |
| || _|| |_| | | |_| | |_| || | | |_| | |_| | | | | | | |_) | | | | | (_| |
|___|_| \____| |____/ \___/ |_| |____/ \__,_|_| |_| |_| .__/|_|_| |_|\__, |
|_| |___/
___ _____ ____ ____ ___ _____ ____ _
|_ _| ___/ ___| | _ \ / _ \_ _| | _ \ _ _ _ __ ___ _ __ (_)_ __ __ _
| || |_ | | _ | | | | | | || | | | | | | | | '_ ` _ \| '_ \| | '_ \ / _` |
| || _|| |_| | | |_| | |_| || | | |_| | |_| | | | | | | |_) | | | | | (_| |
|___|_| \____| |____/ \___/ |_| |____/ \__,_|_| |_| |_| .__/|_|_| |_|\__, |
|_| |___/
*/
static const char *get_dot_color_name(int col)
......@@ -1119,20 +1195,9 @@ typedef struct _co_ifg_dump_t {
unsigned flags;
} co_ifg_dump_t;
static const char *get_dot_shape_name(co_ifg_dump_t *cod, ir_node *irn)
{
arch_register_req_t req;
arch_get_register_req(cod->co->aenv, &req, irn, BE_OUT_POS(0));
if(arch_register_req_is(&req, limited))
return "diamond";
return "ellipse";
}
static void ifg_dump_graph_attr(FILE *f, void *self)
{
fprintf(f, "overlay=false");
fprintf(f, "overlap=scale");
}
static int ifg_is_dump_node(void *self, ir_node *irn)
......@@ -1145,8 +1210,31 @@ static void ifg_dump_node_attr(FILE *f, void *self, ir_node *irn)
{
co_ifg_dump_t *env = self;
const arch_register_t *reg = arch_get_irn_register(env->co->aenv, irn);
arch_register_req_t req;
int limited;
arch_get_register_req(env->co->aenv, &req, irn, BE_OUT_POS(0));
limited = arch_register_req_is(&req, limited);
if(env->flags & CO_IFG_DUMP_LABELS) {
ir_fprintf(f, "label=\"%+F", irn);
if((env->flags & CO_IFG_DUMP_CONSTR) && limited) {
bitset_t *bs = bitset_alloca(env->co->cls->n_regs);
req.limited(req.limited_env, bs);
ir_fprintf(f, "\\n%B", bs);
}
ir_fprintf(f, "\" ");
}
else
fprintf(f, "label=\"\"" );
ir_fprintf(f, "label=\"%+F\" style=filled color=%s shape=%s", irn, get_dot_color_name(reg->index), get_dot_shape_name(env, irn));
if(env->flags & CO_IFG_DUMP_SHAPE)
fprintf(f, "shape=%s ", limited ? "diamond" : "ellipse");
if(env->flags & CO_IFG_DUMP_COLORS)
fprintf(f, "style=filled color=%s ", get_dot_color_name(reg->index));
}
static void ifg_dump_at_end(FILE *file, void *self)
......@@ -1165,7 +1253,14 @@ static void ifg_dump_at_end(FILE *file, void *self)
if(aidx < nidx) {
const char *color = nr == ar ? "blue" : "red";
fprintf(file, "\tn%d -- n%d [label=\"%d\" style=dashed color=%s];\n", aidx, nidx, n->costs, color);
fprintf(file, "\tn%d -- n%d [weight=0.01 ", aidx, nidx);
if(env->flags & CO_IFG_DUMP_LABELS)
fprintf(file, "label=\"%d\" ", n->costs);
if(env->flags & CO_IFG_DUMP_COLORS)
fprintf(file, "color=%s ", color);
else
fprintf(file, "style=dashed");
fprintf(file, "];\n");
}
}
}
......@@ -1197,3 +1292,88 @@ void co_solve_park_moon(copy_opt_t *opt)
{
}
static void void_algo(copy_opt_t *co)
{
}
/*
_ _ _ _ _
/ \ | | __ _ ___ _ __(_) |_| |__ _ __ ___ ___
/ _ \ | |/ _` |/ _ \| '__| | __| '_ \| '_ ` _ \/ __|
/ ___ \| | (_| | (_) | | | | |_| | | | | | | | \__ \
/_/ \_\_|\__, |\___/|_| |_|\__|_| |_|_| |_| |_|___/
|___/
*/
static co_algo_t *algos[] = {
void_algo,
co_solve_heuristic,
co_solve_heuristic_new,
co_solve_heuristic_java,
co_solve_ilp2
};
/*
__ __ _ ____ _
| \/ | __ _(_)_ __ | _ \ _ __(_)_ _____ _ __
| |\/| |/ _` | | '_ \ | | | | '__| \ \ / / _ \ '__|
| | | | (_| | | | | | | |_| | | | |\ V / __/ |
|_| |_|\__,_|_|_| |_| |____/|_| |_| \_/ \___|_|
*/
void co_driver(be_chordal_env_t *cenv)
{
copy_opt_t *co;
co_algo_t *algo_func;
if(algo < 0 || algo >= CO_ALGO_LAST)
return;
co = new_copy_opt(cenv, cost_func);
co_build_ou_structure(co);
co_build_graph_structure(co);
if(do_stats) {
ir_printf("%30F %10s %7d%7d%7d%7d", cenv->irg, cenv->cls->name,
co_get_max_copy_costs(co), co_get_copy_costs(co),
co_get_inevit_copy_costs(co), co_get_lower_bound(co));
}
/* Dump the interference graph in Appel's format. */
if(dump_flags & DUMP_APPEL) {
FILE *f = be_chordal_open(cenv, "", ".apl");
co_dump_appel_graph(co, f);
fclose(f);
}
if(dump_flags & DUMP_BEFORE) {
FILE *f = be_chordal_open(cenv, "", "-before.dot");
co_dump_ifg_dot(co, f, style_flags);
fclose(f);
}
algo_func = algos[algo];
algo_func(co);
if(dump_flags & DUMP_AFTER) {
FILE *f = be_chordal_open(cenv, "", "-after.dot");
co_dump_ifg_dot(co, f, style_flags);
fclose(f);
}
if(do_stats) {
int optimizable_costs = co_get_max_copy_costs(co) - co_get_lower_bound(co);
int remaining = co_get_copy_costs(co);
int evitable = remaining - co_get_lower_bound(co);
if(optimizable_costs > 0)
printf("%5d %5.2f\n", remaining, (evitable * 100.0) / optimizable_costs);
else
printf("%5d %5s\n", remaining, "-");
}
co_free_graph_structure(co);
co_free_ou_structure(co);
free_copy_opt(co);
}
......@@ -23,6 +23,31 @@
extern void co_register_options(lc_opt_entry_t *grp