More missing config.h
[libfirm] / ir / be / bechordal_main.c
index d82603b..7955bb2 100644 (file)
 #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
@@ -133,12 +135,6 @@ static be_ra_chordal_opts_t options = {
        BE_CH_VRFY_WARN,
 };
 
-/* coalesce spill slots */
-static int coalesce_spill_slots = 1;
-
-/** The name of the file where the statistics are put to. */
-static char stat_file_name[2048];
-
 /** Enable extreme live range splitting. */
 static int be_elr_split = 0;
 
@@ -232,13 +228,11 @@ static lc_opt_enum_int_var_t be_ch_vrfy_var = {
 };
 
 static const lc_opt_table_entry_t be_chordal_options[] = {
-       LC_OPT_ENT_STR      ("statfile",      "the name of the statisctics file", stat_file_name, sizeof(stat_file_name)),
-       LC_OPT_ENT_BOOL     ("spill.coal",    "coalesce the spill slots (default: yes)", &coalesce_spill_slots),
-       LC_OPT_ENT_ENUM_INT ("spill",         "spill method (belady, morgan or remat)", &spill_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_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 }
@@ -259,10 +253,13 @@ static void be_ra_chordal_register_options(lc_opt_entry_t *grp)
                lc_opt_add_table(chordal_grp, be_chordal_options);
 
                co_register_options(chordal_grp);
+#ifdef WITH_JVM
                be_java_coal_register_options(chordal_grp);
+#endif
 #ifdef WITH_ILP
                be_spill_remat_register_options(chordal_grp);
 #endif
+               be_spill_register_options(chordal_grp);
        }
 }
 #endif /* WITH_LIBCORE */
@@ -346,9 +343,12 @@ static void memory_operand_walker(ir_node *irn, void *env) {
        if (! be_is_Reload(irn))
                return;
 
-       // only use memory operands, if the reload is only used by 1 node
+       /* 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);
@@ -357,8 +357,7 @@ static void memory_operand_walker(ir_node *irn, void *env) {
                ir_node *src = get_edge_src_irn(edge);
                int     pos  = get_edge_src_pos(edge);
 
-               if (! src)
-                       continue;
+               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));
@@ -387,8 +386,10 @@ static INLINE void check_for_memory_operands(be_chordal_env_t *chordal_env) {
 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. */
+       unsigned int n_reloads;   /**< Reloads */
 } node_stat_t;
 
 struct node_stat_walker {
@@ -414,6 +415,11 @@ static void node_stat_walker(ir_node *irn, void *data)
                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 */
@@ -529,14 +535,6 @@ static void be_init_timer(be_options_t *main_opts)
 
 #endif /* WITH_LIBCORE */
 
-enum {
-       STAT_TAG_FILE = 0,
-       STAT_TAG_TIME = 1,
-       STAT_TAG_IRG  = 2,
-       STAT_TAG_CLS  = 3,
-       STAT_TAG_LAST
-};
-
 /**
  * Performs chordal register allocation for each register class on given irg.
  *
@@ -550,29 +548,9 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
        ir_graph            *irg       = bi->irg;
        be_options_t        *main_opts = main_env->options;
        int                   splitted = 0;
-       FILE                *stat_file = NULL;
 
-       char time_str[32];
-       char irg_name[128];
-       int j, m, line;
-       char *filename;
+       int j, m;
        be_chordal_env_t chordal_env;
-       const char *stat_tags[STAT_TAG_LAST];
-
-       /* if we want to do some statistics, push the environment. */
-       if(strlen(stat_file_name) > 0 && (stat_file = fopen(stat_file_name, "at")) != NULL) {
-
-               /* initialize the statistics tags */
-               ir_snprintf(time_str, sizeof(time_str),"%u", time(NULL));
-               ir_snprintf(irg_name, sizeof(irg_name), "%F", irg);
-
-               stat_tags[STAT_TAG_FILE] = be_retrieve_dbg_info(get_entity_dbg_info(get_irg_entity(irg)), &line);
-               stat_tags[STAT_TAG_TIME] = time_str;
-               stat_tags[STAT_TAG_IRG]  = irg_name;
-               stat_tags[STAT_TAG_CLS]  = "<all>";
-
-               be_stat_ev_push(stat_tags, STAT_TAG_LAST, stat_file);
-       }
 
        BE_TIMER_INIT(main_opts);
        BE_TIMER_PUSH(ra_timer.t_other);
@@ -584,7 +562,7 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
        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");
 
@@ -597,15 +575,16 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
        /* Perform the following for each register class. */
        for (j = 0, m = arch_isa_get_n_reg_class(isa); j < m; ++j) {
                node_stat_t node_stat;
+               double spillcosts = 0;
 
                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);
 
-               stat_tags[STAT_TAG_CLS] = chordal_env.cls->name;
-               be_stat_ev_push(stat_tags, STAT_TAG_LAST, stat_file);
+               if(be_stat_ev_is_active()) {
+                       be_stat_tags[STAT_TAG_CLS] = chordal_env.cls->name;
+                       be_stat_ev_push(be_stat_tags, STAT_TAG_LAST, be_stat_file);
 
-               if(stat_file) {
                        /* perform some node statistics. */
                        node_stats(&chordal_env, &node_stat);
                        be_stat_ev("phis_before_spill", node_stat.n_phis);
@@ -622,6 +601,10 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
                be_pre_spill_prepare_constr(&chordal_env);
                dump(BE_CH_DUMP_CONSTR, irg, chordal_env.cls, "-constr-pre", dump_ir_block_graph_sched);
 
+               if(be_stat_ev_is_active()) {
+                       spillcosts = be_estimate_irg_costs(irg, main_env->arch_env, chordal_env.exec_freq);
+               }
+
                BE_TIMER_PUSH(ra_timer.t_spill);
 
                /* spilling */
@@ -644,7 +627,10 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
 
                BE_TIMER_POP(ra_timer.t_spill);
 
-               if(stat_file) {
+               if(be_stat_ev_is_active()) {
+                       spillcosts = be_estimate_irg_costs(irg, main_env->arch_env, chordal_env.exec_freq) - spillcosts;
+                       be_stat_ev_l("spillcosts", (long) spillcosts);
+
                        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);
@@ -713,29 +699,39 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
                }
                BE_TIMER_POP(ra_timer.t_ifg);
 
-               if(stat_file) {
+               if(be_stat_ev_is_active()) {
                        be_ifg_stat_t stat;
-                       be_ifg_stat(chordal_env.ifg, irg, &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);
                }
 
                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);
 
+               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);
@@ -750,7 +746,7 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
                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);
 
@@ -758,12 +754,17 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
                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_spillslots);
 
-       if(coalesce_spill_slots)
        be_coalesce_spillslots(&chordal_env);
        dump(BE_CH_DUMP_SPILLSLOTS, irg, NULL, "-spillslots", dump_ir_block_graph_sched);
 
@@ -790,16 +791,11 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
        obstack_free(&chordal_env.obst, NULL);
        be_free_dominance_frontiers(chordal_env.dom_front);
        be_liveness_free(chordal_env.lv);
-       free_execfreq(chordal_env.exec_freq);
 
        BE_TIMER_POP(ra_timer.t_epilog);
        BE_TIMER_POP(ra_timer.t_other);
 
        be_stat_ev("insns_after", count_insns(irg));
-       be_stat_ev_pop();
-
-       if(stat_file)
-               fclose(stat_file);
 
 #ifdef WITH_LIBCORE
        return main_opts->timing == BE_TIME_ON ? &ra_timer : NULL;
@@ -810,8 +806,8 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
 const be_ra_t be_ra_chordal_allocator = {
 #ifdef WITH_LIBCORE
        be_ra_chordal_register_options,
-       be_ra_chordal_main
 #else
-       0
+       NULL,
 #endif
+       be_ra_chordal_main,
 };