* @author Sebastian Hack
* @cvs-id $Id$
*
- * Copyright (C) 2005 Universitaet Karlsruhe
+ * Copyright (C) 2005-2006 Universitaet Karlsruhe
* Released under the GPL
*
* Driver for the chordal register allocator.
#include "config.h"
#endif
+#include <time.h>
+
#include "obst.h"
#include "pset.h"
#include "list.h"
#include <libcore/lc_timing.h>
#endif /* WITH_LIBCORE */
+#include "ircons_t.h"
#include "irmode_t.h"
#include "irgraph_t.h"
#include "irprintf_t.h"
#include "irgwalk.h"
+#include "ircons.h"
#include "irdump.h"
#include "irdom.h"
+#include "ircons.h"
#include "irbitset.h"
+#include "irnode.h"
+#include "ircons.h"
#include "debug.h"
#include "xmalloc.h"
#include "execfreq.h"
#include "bechordal_t.h"
#include "beabi.h"
+#include "bejavacoal.h"
#include "beutil.h"
#include "besched.h"
#include "benumb_t.h"
#include "bearch.h"
#include "beifg_t.h"
#include "beifg_impl.h"
+#include "benode_t.h"
+#include "bestatevent.h"
+#include "bestat.h"
#include "bespillbelady.h"
#include "bespillmorgan.h"
+#include "bespillslots.h"
+#include "bespilloptions.h"
#include "belower.h"
#ifdef WITH_ILP
#include "bespillremat.h"
#endif /* WITH_ILP */
+#include "bejavacoal.h"
#include "becopystat.h"
#include "becopyopt.h"
#include "bessadestr.h"
#include "beverify.h"
+#include "bespillcost.h"
+#include "benode_t.h"
void be_ra_chordal_check(be_chordal_env_t *chordal_env) {
const arch_env_t *arch_env = chordal_env->birg->main_env->arch_env;
}
for (o = i+1, n2 = nodes[o]; n2; n2 = nodes[++o]) {
n2_reg = arch_get_irn_register(arch_env, n2);
- if (values_interfere(n1, n2) && n1_reg == n2_reg) {
+ if (values_interfere(chordal_env->lv, n1, n2) && n1_reg == n2_reg) {
DBG((dbg, 0, "Values %+F and %+F interfere and have the same register assigned: %s\n", n1, n2, n1_reg->name));
assert(0 && "Interfering values have the same color!");
}
if(env->ifg)
return be_ifg_connected(env->ifg, a, b);
else
- return values_interfere(a, b);
+ return values_interfere(env->lv, a, b);
}
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,
};
+/** Enable extreme live range splitting. */
+static int be_elr_split = 0;
+
+/** Assumed loop iteration count for execution frequency estimation. */
+static int be_loop_weight = 9;
+
+#ifdef WITH_LIBCORE
static be_ra_timer_t ra_timer = {
NULL,
NULL,
NULL,
NULL,
NULL,
+ NULL,
};
-#ifdef WITH_LIBCORE
static const lc_opt_enum_int_items_t spill_items[] = {
{ "morgan", BE_CH_SPILL_MORGAN },
{ "belady", BE_CH_SPILL_BELADY },
{ 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 },
- { "stat", BE_CH_COPYMIN_STAT },
- { "park", BE_CH_COPYMIN_PARK_MOON },
-#ifdef WITH_ILP
- { "ilp1", BE_CH_COPYMIN_ILP1 },
- { "ilp2", BE_CH_COPYMIN_ILP2 },
-#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 },
};
static const lc_opt_enum_int_items_t dump_items[] = {
- { "spill", BE_CH_DUMP_SPILL },
- { "live", BE_CH_DUMP_LIVE },
- { "color", BE_CH_DUMP_COLOR },
- { "copymin", BE_CH_DUMP_COPYMIN },
- { "ssadestr", BE_CH_DUMP_SSADESTR },
- { "tree", BE_CH_DUMP_TREE_INTV },
- { "constr", BE_CH_DUMP_CONSTR },
- { "lower", BE_CH_DUMP_LOWER },
- { "all", BE_CH_DUMP_ALL },
+ { "spill", BE_CH_DUMP_SPILL },
+ { "live", BE_CH_DUMP_LIVE },
+ { "color", BE_CH_DUMP_COLOR },
+ { "copymin", BE_CH_DUMP_COPYMIN },
+ { "ssadestr", BE_CH_DUMP_SSADESTR },
+ { "tree", BE_CH_DUMP_TREE_INTV },
+ { "constr", BE_CH_DUMP_CONSTR },
+ { "lower", BE_CH_DUMP_LOWER },
+ { "spillslots", BE_CH_DUMP_SPILLSLOTS },
+ { "appel", BE_CH_DUMP_APPEL },
+ { "all", BE_CH_DUMP_ALL },
{ NULL, 0 }
};
&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
};
&options.vrfy_option, be_ch_vrfy_items
};
-static int be_copymin_stats = 0;
-
-/** Assumed loop iteration count for execution frequency estimation. */
-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)", ©min_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_INT ("spill", "spill method", &spill_var),
+ LC_OPT_ENT_ENUM_PTR ("ifg", "interference graph flavour", &ifg_flavor_var),
+ LC_OPT_ENT_ENUM_PTR ("perm", "perm lowering options", &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_ENUM_PTR ("vrfy", "verify options", &be_ch_vrfy_var),
+ 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 }
};
+extern void be_spill_remat_register_options(lc_opt_entry_t *ent);
+
+
static void be_ra_chordal_register_options(lc_opt_entry_t *grp)
{
static int run_once = 0;
chordal_grp = lc_opt_get_grp(grp, "chordal");
lc_opt_add_table(chordal_grp, be_chordal_options);
- }
- co_register_options(chordal_grp);
+ co_register_options(chordal_grp);
+ be_java_coal_register_options(chordal_grp);
+#ifdef WITH_ILP
+ be_spill_remat_register_options(chordal_grp);
+#endif
+ be_spill_register_options(chordal_grp);
+ }
}
#endif /* WITH_LIBCORE */
{
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");
}
{
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);
};
/**
- * Performs chordal register allocation for each register class on given irg.
- *
- * @param bi Backend irg object
- * @return Structure containing timer for the single phases or NULL if no timing requested.
+ * Checks for every reload if it's user can perform the load on itself.
*/
-static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
+static void memory_operand_walker(ir_node *irn, void *env) {
+ be_chordal_env_t *cenv = env;
+ const arch_env_t *aenv = cenv->birg->main_env->arch_env;
+ const ir_edge_t *edge, *ne;
+ ir_node *block;
+ ir_node *spill;
+
+ if (! be_is_Reload(irn))
+ return;
+
+ /* always use addressmode, it's good for x86 */
+#if 0
+ /* only use memory operands, if the reload is only used by 1 node */
+ if(get_irn_n_edges(irn) > 1)
+ return;
+#endif
+
+ spill = be_get_Reload_mem(irn);
+ block = get_nodes_block(irn);
+
+ foreach_out_edge_safe(irn, edge, ne) {
+ ir_node *src = get_edge_src_irn(edge);
+ int pos = get_edge_src_pos(edge);
+
+ assert(src && "outedges broken!");
+
+ if (get_nodes_block(src) == block && arch_possible_memory_operand(aenv, src, pos)) {
+ DBG((cenv->dbg, LEVEL_3, "performing memory operand %+F at %+F\n", irn, src));
+ arch_perform_memory_operand(aenv, src, spill, pos);
+ }
+ }
+
+ /* kill the Reload */
+ if (get_irn_n_edges(irn) == 0) {
+ sched_remove(irn);
+ set_irn_n(irn, 0, new_Bad());
+ set_irn_n(irn, 1, new_Bad());
+ }
+}
+
+/**
+ * Starts a walk for memory operands if supported by the backend.
+ */
+static INLINE void check_for_memory_operands(be_chordal_env_t *chordal_env) {
+ irg_walk_graph(chordal_env->irg, NULL, memory_operand_walker, chordal_env);
+}
+
+/**
+ * Sorry for doing stats again...
+ */
+typedef struct _node_stat_t {
+ unsigned int n_phis; /**< Phis of the current register class. */
+ unsigned int n_mem_phis; /**< Memory Phis (Phis with spill operands). */
+ unsigned int n_copies; /**< Copies */
+ unsigned int n_perms; /**< Perms */
+ unsigned int n_spills; /**< Spill nodes */
+ unsigned int n_reloads; /**< Reloads */
+} node_stat_t;
+
+struct node_stat_walker {
+ node_stat_t *stat;
+ const be_chordal_env_t *cenv;
+ bitset_t *mem_phis;
+};
+
+static void node_stat_walker(ir_node *irn, void *data)
{
- const be_main_env_t *main_env = bi->main_env;
- const arch_isa_t *isa = arch_env_get_isa(main_env->arch_env);
- ir_graph *irg = bi->irg;
- be_options_t *main_opts = main_env->options;
+ struct node_stat_walker *env = data;
+ const arch_env_t *aenv = env->cenv->birg->main_env->arch_env;
- int j, m;
- be_chordal_env_t chordal_env;
+ if(arch_irn_consider_in_reg_alloc(aenv, env->cenv->cls, irn)) {
+ /* if the node is a normal phi */
+ if(is_Phi(irn))
+ env->stat->n_phis++;
+
+ else if(arch_irn_classify(aenv, irn) & arch_irn_class_spill)
+ ++env->stat->n_spills;
+
+ else if(arch_irn_classify(aenv, irn) & arch_irn_class_reload)
+ ++env->stat->n_reloads;
+
+ else if(arch_irn_classify(aenv, irn) & arch_irn_class_copy)
+ ++env->stat->n_copies;
+
+ else if(arch_irn_classify(aenv, irn) & arch_irn_class_perm)
+ ++env->stat->n_perms;
+ }
+
+ /* a mem phi is a PhiM with a mem phi operand or a Spill operand */
+ else if(is_Phi(irn) && get_irn_mode(irn) == mode_M) {
+ int i;
+
+ for(i = get_irn_arity(irn) - 1; i >= 0; --i) {
+ ir_node *op = get_irn_n(irn, i);
+
+ if((is_Phi(op) && bitset_contains_irn(env->mem_phis, op)) || (arch_irn_classify(aenv, op) & arch_irn_class_spill)) {
+ bitset_add_irn(env->mem_phis, irn);
+ env->stat->n_mem_phis++;
+ break;
+ }
+ }
+ }
+}
+
+static void node_stats(const be_chordal_env_t *cenv, node_stat_t *stat)
+{
+ struct node_stat_walker env;
+
+ memset(stat, 0, sizeof(stat[0]));
+ env.cenv = cenv;
+ env.mem_phis = bitset_irg_malloc(cenv->irg);
+ env.stat = stat;
+ irg_walk_graph(cenv->irg, NULL, node_stat_walker, &env);
+ bitset_free(env.mem_phis);
+}
+
+static void insn_count_walker(ir_node *irn, void *data)
+{
+ int *cnt = data;
+
+ switch(get_irn_opcode(irn)) {
+ case iro_Proj:
+ case iro_Phi:
+ case iro_Start:
+ case iro_End:
+ break;
+ default:
+ (*cnt)++;
+ }
+}
+
+static unsigned int count_insns(ir_graph *irg)
+{
+ int cnt = 0;
+ irg_walk_graph(irg, insn_count_walker, NULL, &cnt);
+ return cnt;
+}
+
+#ifdef WITH_LIBCORE
+/**
+ * Initialize all timers.
+ */
+static void be_init_timer(be_options_t *main_opts)
+{
if (main_opts->timing == BE_TIME_ON) {
- ra_timer.t_prolog = lc_timer_register("ra_prolog", "regalloc prolog");
- ra_timer.t_epilog = lc_timer_register("ra_epilog", "regalloc epilog");
- ra_timer.t_live = lc_timer_register("ra_liveness", "be liveness");
- ra_timer.t_spill = lc_timer_register("ra_spill", "spiller");
- ra_timer.t_color = lc_timer_register("ra_color", "graph coloring");
- ra_timer.t_ifg = lc_timer_register("ra_ifg", "interference graph");
- ra_timer.t_copymin = lc_timer_register("ra_copymin", "copy minimization");
- ra_timer.t_ssa = lc_timer_register("ra_ssadestr", "ssa destruction");
- ra_timer.t_verify = lc_timer_register("ra_verify", "graph verification");
- ra_timer.t_other = lc_timer_register("ra_other", "other time");
+ ra_timer.t_prolog = lc_timer_register("ra_prolog", "regalloc prolog");
+ ra_timer.t_epilog = lc_timer_register("ra_epilog", "regalloc epilog");
+ ra_timer.t_live = lc_timer_register("ra_liveness", "be liveness");
+ ra_timer.t_spill = lc_timer_register("ra_spill", "spiller");
+ ra_timer.t_spillslots = lc_timer_register("ra_spillslots", "spillslots");
+ ra_timer.t_color = lc_timer_register("ra_color", "graph coloring");
+ ra_timer.t_ifg = lc_timer_register("ra_ifg", "interference graph");
+ ra_timer.t_copymin = lc_timer_register("ra_copymin", "copy minimization");
+ ra_timer.t_ssa = lc_timer_register("ra_ssadestr", "ssa destruction");
+ ra_timer.t_verify = lc_timer_register("ra_verify", "graph verification");
+ ra_timer.t_other = lc_timer_register("ra_other", "other time");
LC_STOP_AND_RESET_TIMER(ra_timer.t_prolog);
LC_STOP_AND_RESET_TIMER(ra_timer.t_epilog);
LC_STOP_AND_RESET_TIMER(ra_timer.t_live);
LC_STOP_AND_RESET_TIMER(ra_timer.t_spill);
+ LC_STOP_AND_RESET_TIMER(ra_timer.t_spillslots);
LC_STOP_AND_RESET_TIMER(ra_timer.t_color);
LC_STOP_AND_RESET_TIMER(ra_timer.t_ifg);
LC_STOP_AND_RESET_TIMER(ra_timer.t_copymin);
LC_STOP_AND_RESET_TIMER(ra_timer.t_verify);
LC_STOP_AND_RESET_TIMER(ra_timer.t_other);
}
+}
-#define BE_TIMER_PUSH(timer) \
- if (main_opts->timing == BE_TIME_ON) { \
- int res = lc_timer_push(timer); \
- if (options.vrfy_option == BE_CH_VRFY_ASSERT) \
- assert(res && "Timer already on stack, cannot be pushed twice."); \
- else if (options.vrfy_option == BE_CH_VRFY_WARN && ! res) \
- fprintf(stderr, "Timer %s already on stack, cannot be pushed twice.\n", \
- lc_timer_get_name(timer)); \
+#define BE_TIMER_INIT(main_opts) be_init_timer(main_opts)
+
+#define BE_TIMER_PUSH(timer) \
+ if (main_opts->timing == BE_TIME_ON) { \
+ if (! lc_timer_push(timer)) { \
+ if (options.vrfy_option == BE_CH_VRFY_ASSERT) \
+ assert(!"Timer already on stack, cannot be pushed twice."); \
+ else if (options.vrfy_option == BE_CH_VRFY_WARN) \
+ fprintf(stderr, "Timer %s already on stack, cannot be pushed twice.\n", \
+ lc_timer_get_name(timer)); \
+ } \
}
#define BE_TIMER_POP(timer) \
if (main_opts->timing == BE_TIME_ON) { \
lc_timer_get_name(tmp), lc_timer_get_name(timer)); \
timer = tmp; \
}
+#else
+
+#define BE_TIMER_INIT(main_opts)
+#define BE_TIMER_PUSH(timer)
+#define BE_TIMER_POP(timer)
+#endif /* WITH_LIBCORE */
+
+/**
+ * Performs chordal register allocation for each register class on given irg.
+ *
+ * @param bi Backend irg object
+ * @return Structure containing timer for the single phases or NULL if no timing requested.
+ */
+static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
+{
+ const be_main_env_t *main_env = bi->main_env;
+ const arch_isa_t *isa = arch_env_get_isa(main_env->arch_env);
+ ir_graph *irg = bi->irg;
+ be_options_t *main_opts = main_env->options;
+ int splitted = 0;
+
+ int j, m;
+ be_chordal_env_t chordal_env;
+
+ BE_TIMER_INIT(main_opts);
BE_TIMER_PUSH(ra_timer.t_other);
BE_TIMER_PUSH(ra_timer.t_prolog);
chordal_env.irg = irg;
chordal_env.birg = bi;
chordal_env.dom_front = be_compute_dominance_frontiers(irg);
- chordal_env.exec_freq = compute_execfreq(irg, be_loop_weight);
+ chordal_env.exec_freq = bi->execfreqs;
+ chordal_env.lv = be_liveness(irg);
FIRM_DBG_REGISTER(chordal_env.dbg, "firm.be.chordal");
obstack_init(&chordal_env.obst);
BE_TIMER_POP(ra_timer.t_prolog);
+ be_stat_ev("insns_before", count_insns(irg));
+
/* Perform the following for each register class. */
for (j = 0, m = arch_isa_get_n_reg_class(isa); j < m; ++j) {
- FILE *f;
- copy_opt_t *co = NULL;
+ node_stat_t node_stat;
chordal_env.cls = arch_isa_get_reg_class(isa, j);
chordal_env.border_heads = pmap_create();
chordal_env.ignore_colors = bitset_malloc(chordal_env.cls->n_regs);
- BE_TIMER_PUSH(ra_timer.t_live);
+ be_stat_tags[STAT_TAG_CLS] = chordal_env.cls->name;
+
+ if(be_stat_ev_is_active()) {
+ be_stat_ev_push(be_stat_tags, STAT_TAG_LAST, be_stat_file);
+
+ /* perform some node statistics. */
+ node_stats(&chordal_env, &node_stat);
+ be_stat_ev("phis_before_spill", node_stat.n_phis);
+ }
/* put all ignore registers into the ignore register set. */
put_ignore_colors(&chordal_env);
- be_liveness(irg);
-
+ BE_TIMER_PUSH(ra_timer.t_live);
+ be_liveness_recompute(chordal_env.lv);
BE_TIMER_POP(ra_timer.t_live);
-
dump(BE_CH_DUMP_LIVE, irg, chordal_env.cls, "-live", dump_ir_block_graph_sched);
+ be_pre_spill_prepare_constr(&chordal_env);
+ dump(BE_CH_DUMP_CONSTR, irg, chordal_env.cls, "-constr-pre", dump_ir_block_graph_sched);
+
BE_TIMER_PUSH(ra_timer.t_spill);
/* spilling */
BE_TIMER_POP(ra_timer.t_spill);
+ if(be_stat_ev_is_active()) {
+ node_stats(&chordal_env, &node_stat);
+ be_stat_ev("phis_after_spill", node_stat.n_phis);
+ be_stat_ev("mem_phis", node_stat.n_mem_phis);
+ be_stat_ev("reloads", node_stat.n_reloads);
+ be_stat_ev("spills", node_stat.n_spills);
+ }
+
+ DBG((chordal_env.dbg, LEVEL_1, "spill costs for %+F in regclass %s: %g\n",irg, chordal_env.cls->name, get_irg_spill_cost(&chordal_env)));
+
dump(BE_CH_DUMP_SPILL, irg, chordal_env.cls, "-spill", dump_ir_block_graph_sched);
- be_abi_fix_stack_nodes(bi->abi);
+
+ check_for_memory_operands(&chordal_env);
+
+ be_abi_fix_stack_nodes(bi->abi, chordal_env.lv);
BE_TIMER_PUSH(ra_timer.t_verify);
/* verify schedule and register pressure */
if (options.vrfy_option == BE_CH_VRFY_WARN) {
be_verify_schedule(irg);
- be_verify_register_pressure(chordal_env.birg->main_env->arch_env, chordal_env.cls, irg);
+ be_verify_register_pressure(chordal_env.birg, chordal_env.cls, irg);
}
else if (options.vrfy_option == BE_CH_VRFY_ASSERT) {
assert(be_verify_schedule(irg) && "Schedule verification failed");
- assert(be_verify_register_pressure(chordal_env.birg->main_env->arch_env, chordal_env.cls, irg)
+ assert(be_verify_register_pressure(chordal_env.birg, chordal_env.cls, irg)
&& "Register pressure verification failed");
}
-
BE_TIMER_POP(ra_timer.t_verify);
- BE_TIMER_PUSH(ra_timer.t_live);
- be_liveness(irg);
- BE_TIMER_POP(ra_timer.t_live);
- BE_TIMER_PUSH(ra_timer.t_color);
+
+ if (be_elr_split && ! splitted) {
+ extreme_liverange_splitting(&chordal_env);
+ splitted = 1;
+ }
+
/* Color the graph. */
+ BE_TIMER_PUSH(ra_timer.t_color);
be_ra_chordal_color(&chordal_env);
-
BE_TIMER_POP(ra_timer.t_color);
dump(BE_CH_DUMP_CONSTR, irg, chordal_env.cls, "-color", dump_ir_block_graph_sched);
- BE_TIMER_PUSH(ra_timer.t_ifg);
-
/* Create the ifg with the selected flavor */
+ BE_TIMER_PUSH(ra_timer.t_ifg);
switch (options.ifg_flavor) {
default:
fprintf(stderr, "no valid ifg flavour selected. falling back to std\n");
chordal_env.ifg = be_ifg_std_new(&chordal_env);
break;
}
+ BE_TIMER_POP(ra_timer.t_ifg);
-
-#if 0
- {
- be_ifg_t *std = be_ifg_std_new(&chordal_env);
- f = be_chordal_open(&chordal_env, "std", "csv");
- be_ifg_check_sorted_to_file(std, f);
- be_ifg_free(std);
- fclose(f);
+ if(be_stat_ev_is_active()) {
+ be_ifg_stat_t stat;
+ be_ifg_stat(&chordal_env, &stat);
+ be_stat_ev("ifg_nodes", stat.n_nodes);
+ be_stat_ev("ifg_edges", stat.n_edges);
+ be_stat_ev("ifg_comps", stat.n_comps);
}
- f = be_chordal_open(&chordal_env, "clique", "csv");
- be_ifg_check_sorted_to_file(chordal_env.ifg, f);
- fclose(f);
-#endif
- BE_TIMER_POP(ra_timer.t_ifg);
-
BE_TIMER_PUSH(ra_timer.t_verify);
-
- if (options.vrfy_option != BE_CH_VRFY_OFF)
- be_ra_chordal_check(&chordal_env);
-
-// be_ifg_check_sorted(chordal_env.ifg);
- BE_TIMER_POP(ra_timer.t_verify);
- BE_TIMER_PUSH(ra_timer.t_copymin);
-
- /* copy minimization */
- if (options.copymin_method != BE_CH_COPYMIN_NONE && options.copymin_method != BE_CH_COPYMIN_STAT) {
- FILE *f;
- co = new_copy_opt(&chordal_env, co_get_costs_loop_depth);
- co_build_ou_structure(co);
- co_build_graph_structure(co);
- if(be_copymin_stats) {
- ir_printf("%40F %20s\n", current_ir_graph, chordal_env.cls->name);
- printf("max copy costs: %d\n", co_get_max_copy_costs(co));
- printf("init copy costs: %d\n", co_get_copy_costs(co));
- printf("inevit copy costs: %d\n", co_get_inevit_copy_costs(co));
- printf("copy costs lower bound: %d\n", co_get_lower_bound(co));
- }
-
-#if 0
- f = be_chordal_open(&chordal_env, "appel-", "apl");
- co_dump_appel_graph(co, f);
- fclose(f);
- f = be_chordal_open(&chordal_env, "appel-clique-", "p");
- co_dump_appel_graph_cliques(co, f);
- fclose(f);
-#endif
+ if (options.vrfy_option != BE_CH_VRFY_OFF) {
+ //be_ra_chordal_check(&chordal_env);
}
- 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_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_ILP1:
- printf("FIXME: %s:%d ILP1 not yet implemented!\n", __FILE__, __LINE__);
- co_solve_ilp1(co, 60.0);
- break;
- case BE_CH_COPYMIN_ILP2:
- co_solve_ilp2(co, 60.0);
- break;
-#endif /* WITH_ILP */
- case BE_CH_COPYMIN_NONE:
- default:
- break;
- }
+ BE_TIMER_POP(ra_timer.t_verify);
- if (co) {
- if(be_copymin_stats) {
- printf("final copy costs : %d\n", co_get_copy_costs(co));
- }
- co_free_graph_structure(co);
- co_free_ou_structure(co);
- free_copy_opt(co);
+ if(be_stat_ev_is_active()) {
+ node_stats(&chordal_env, &node_stat);
+ be_stat_ev("perms_before_coal", node_stat.n_perms);
+ be_stat_ev("copies_before_coal", node_stat.n_copies);
}
+ /* copy minimization */
+ BE_TIMER_PUSH(ra_timer.t_copymin);
+ 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);
- if (options.vrfy_option != BE_CH_VRFY_OFF)
- be_ra_chordal_check(&chordal_env);
+ if (options.vrfy_option != BE_CH_VRFY_OFF) {
+ //be_ra_chordal_check(&chordal_env);
+ }
BE_TIMER_POP(ra_timer.t_verify);
BE_TIMER_PUSH(ra_timer.t_ssa);
BE_TIMER_PUSH(ra_timer.t_verify);
if (options.vrfy_option != BE_CH_VRFY_OFF) {
be_ssa_destruction_check(&chordal_env);
- be_ra_chordal_check(&chordal_env);
+ //be_ra_chordal_check(&chordal_env);
}
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);
+
+ if(be_stat_ev_is_active()) {
+ node_stats(&chordal_env, &node_stat);
+ be_stat_ev("perms_after_coal", node_stat.n_perms);
+ be_stat_ev("copies_after_coal", node_stat.n_copies);
+ }
+
+ be_stat_ev_pop();
}
- BE_TIMER_PUSH(ra_timer.t_epilog);
+ BE_TIMER_PUSH(ra_timer.t_spillslots);
+
+ be_coalesce_spillslots(&chordal_env);
+ dump(BE_CH_DUMP_SPILLSLOTS, irg, NULL, "-spillslots", dump_ir_block_graph_sched);
+
+ BE_TIMER_POP(ra_timer.t_spillslots);
- be_compute_spill_offsets(&chordal_env);
+ BE_TIMER_PUSH(ra_timer.t_verify);
+
+ /* verify spillslots */
+ if (options.vrfy_option == BE_CH_VRFY_WARN) {
+ be_verify_spillslots(main_env->arch_env, irg);
+ }
+ else if (options.vrfy_option == BE_CH_VRFY_ASSERT) {
+ assert(be_verify_spillslots(main_env->arch_env, irg) && "Spillslot verification failed");
+ }
+ BE_TIMER_POP(ra_timer.t_verify);
+
+ BE_TIMER_PUSH(ra_timer.t_epilog);
dump(BE_CH_DUMP_LOWER, irg, NULL, "-spilloff", dump_ir_block_graph_sched);
obstack_free(&chordal_env.obst, NULL);
be_free_dominance_frontiers(chordal_env.dom_front);
- free_execfreq(chordal_env.exec_freq);
+ be_liveness_free(chordal_env.lv);
BE_TIMER_POP(ra_timer.t_epilog);
BE_TIMER_POP(ra_timer.t_other);
-#undef BE_TIMER_PUSH
-#undef BE_TIMER_POP
+ be_stat_ev("insns_after", count_insns(irg));
+#ifdef WITH_LIBCORE
return main_opts->timing == BE_TIME_ON ? &ra_timer : NULL;
+#endif /* WITH_LIBCORE */
+ return NULL;
}
const be_ra_t be_ra_chordal_allocator = {
#ifdef WITH_LIBCORE
be_ra_chordal_register_options,
+#else
+ NULL,
#endif
- be_ra_chordal_main
+ be_ra_chordal_main,
};