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

Added statistics events in several files

parent 2f92ed0d
......@@ -35,7 +35,8 @@ SOURCES += Makefile.in besched.h belistsched.h belistsched.c \
beverify.h beverify.c bepressurestat.c bepressurestat.h \
bessadestrsimple.c beifg_clique.c beifg_list.c beifg_pointer.c \
bejavacoal.c becopyheur3.c bespillcost.c bespillremat.c \
bespillslots.h bespillslots.c
bespillslots.h bespillslots.c \
bestatevent.h bestatevent.c
include $(topdir)/MakeRules
......
......@@ -49,6 +49,7 @@
#include "beirgmod.h"
#include "beifg.h"
#include "beinsn_t.h"
#include "bestatevent.h"
#include "bechordal_t.h"
#include "bechordal_draw.h"
......@@ -424,6 +425,7 @@ static ir_node *pre_process_constraints(be_chordal_alloc_env_t *alloc_env, be_in
if(perm) {
const ir_edge_t *edge;
be_stat_ev("constr_perm", 1);
foreach_out_edge(perm, edge) {
ir_node *proj = get_edge_src_irn(edge);
arch_set_irn_register(aenv, proj, NULL);
......
......@@ -13,6 +13,8 @@
#include "config.h"
#endif
#include <time.h>
#include "obst.h"
#include "pset.h"
#include "list.h"
......@@ -54,6 +56,7 @@
#include "beifg_t.h"
#include "beifg_impl.h"
#include "benode_t.h"
#include "bestatevent.h"
#include "bespillbelady.h"
#include "bespillmorgan.h"
......@@ -130,6 +133,12 @@ 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;
......@@ -223,6 +232,8 @@ 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),
......@@ -370,6 +381,91 @@ 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_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)
{
struct node_stat_walker *env = data;
const arch_env_t *aenv = env->cenv->birg->main_env->arch_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;
}
/* 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.
......@@ -377,17 +473,17 @@ static INLINE void check_for_memory_operands(be_chordal_env_t *chordal_env) {
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_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");
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);
......@@ -433,6 +529,14 @@ 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.
*
......@@ -445,10 +549,30 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
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 splitted = 0;
FILE *stat_file = NULL;
int j, m;
char time_str[32];
char irg_name[128];
int j, m, line;
char *filename;
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);
......@@ -468,12 +592,25 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
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) {
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);
stat_tags[STAT_TAG_CLS] = chordal_env.cls->name;
be_stat_ev_push(stat_tags, STAT_TAG_LAST, 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);
}
/* put all ignore registers into the ignore register set. */
put_ignore_colors(&chordal_env);
......@@ -507,11 +644,15 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
BE_TIMER_POP(ra_timer.t_spill);
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))
);
if(stat_file) {
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);
......@@ -572,6 +713,13 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
}
BE_TIMER_POP(ra_timer.t_ifg);
if(stat_file) {
be_ifg_stat_t stat;
be_ifg_stat(chordal_env.ifg, irg, &stat);
be_stat_ev("ifg_nodes", stat.n_nodes);
be_stat_ev("ifg_edges", stat.n_edges);
}
BE_TIMER_PUSH(ra_timer.t_verify);
if (options.vrfy_option != BE_CH_VRFY_OFF)
be_ra_chordal_check(&chordal_env);
......@@ -609,10 +757,13 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
be_ifg_free(chordal_env.ifg);
pmap_destroy(chordal_env.border_heads);
bitset_free(chordal_env.ignore_colors);
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);
......@@ -644,6 +795,12 @@ static be_ra_timer_t *be_ra_chordal_main(const be_irg_t *bi)
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;
#endif /* WITH_LIBCORE */
......
/**
* Internal datastructures for the chordal register allocator.
* Internal data structures for the chordal register allocator.
* @author Sebastian Hack
* @date 25.1.2005
*/
......
......@@ -39,6 +39,7 @@
#include "beinsn_t.h"
#include "besched_t.h"
#include "benodesets.h"
#include "bestatevent.h"
#define DUMP_BEFORE 1
#define DUMP_AFTER 2
......@@ -244,18 +245,21 @@ int co_get_costs_loop_depth(const copy_opt_t *co, ir_node *root, ir_node* arg, i
int d = get_loop_depth(loop);
cost = d*d;
}
return cost+1;
return 1+cost;
}
int co_get_costs_exec_freq(const copy_opt_t *co, ir_node *root, ir_node* arg, int pos) {
int res;
ir_node *root_bl = get_nodes_block(root);
ir_node *copy_bl = is_Phi(root) ? get_Block_cfgpred_block(root_bl, pos) : root_bl;
unsigned long freq = get_block_execfreq_ulong(co->cenv->exec_freq, copy_bl);
return freq > 0 ? (int) freq : 1;
res = get_block_execfreq_ulong(co->cenv->exec_freq, copy_bl);
/* don't allow values smaller than one. */
return res < 1 ? 1 : res;
}
int co_get_costs_all_one(const copy_opt_t *co, ir_node *root, ir_node* arg, int pos) {
int co_get_costs_all_one(const copy_opt_t *co, ir_node *root, ir_node *arg, int pos) {
return 1;
}
......@@ -631,6 +635,40 @@ int co_get_lower_bound(const copy_opt_t *co) {
return res;
}
void co_complete_stats(const copy_opt_t *co, co_complete_stats_t *stat)
{
bitset_t *seen = bitset_irg_malloc(co->irg);
affinity_node_t *an;
memset(stat, 0, sizeof(stat[0]));
/* count affinity edges. */
co_gs_foreach_aff_node(co, an) {
neighb_t *neigh;
stat->aff_nodes += 1;
bitset_add_irn(seen, an->irn);
co_gs_foreach_neighb(an, neigh) {
if(!bitset_contains_irn(seen, neigh->irn)) {
stat->aff_edges += 1;
stat->max_costs += neigh->costs;
if(get_irn_col(co, an->irn) != get_irn_col(co, neigh->irn)) {
stat->costs += neigh->costs;
stat->unsatisfied_edges += 1;
}
if(nodes_interfere(co->cenv, an->irn, neigh->irn)) {
stat->aff_int += 1;
stat->inevit_costs += neigh->costs;
}
}
}
}
bitset_free(seen);
}
/******************************************************************************
_____ _ _____ _
/ ____| | | / ____| |
......@@ -815,7 +853,7 @@ void co_dump_appel_graph(const copy_opt_t *co, FILE *f)
if(!arch_irn_is(co->aenv, n->irn, ignore)) {
int n_idx = PTR_TO_INT(get_irn_link(n->irn));
if(idx < n_idx)
fprintf(f, "%d %d %d\n", idx, n_idx, n->costs);
fprintf(f, "%d %d %d\n", idx, n_idx, (int) n->costs);
}
}
}
......@@ -1261,7 +1299,7 @@ static void ifg_dump_at_end(FILE *file, void *self)
if(env->flags & CO_IFG_DUMP_COLORS)
fprintf(file, "color=%s ", color);
else
fprintf(file, "style=dashed");
fprintf(file, "style=dotted");
fprintf(file, "];\n");
}
}
......@@ -1330,9 +1368,9 @@ static co_algo_t *algos[] = {
void co_driver(be_chordal_env_t *cenv)
{
co_complete_stats_t before, after;
copy_opt_t *co;
co_algo_t *algo_func;
int init_costs;
if(algo < 0 || algo >= CO_ALGO_LAST)
return;
......@@ -1340,7 +1378,17 @@ void co_driver(be_chordal_env_t *cenv)
co = new_copy_opt(cenv, cost_func);
co_build_ou_structure(co);
co_build_graph_structure(co);
init_costs = co_get_copy_costs(co);
co_complete_stats(co, &before);
be_stat_ev("co_aff_nodes", before.aff_nodes);
be_stat_ev("co_aff_edges", before.aff_edges);
be_stat_ev("co_max_costs", before.max_costs);
be_stat_ev("co_inevit_costs", before.inevit_costs);
be_stat_ev("co_aff_int", before.aff_int);
be_stat_ev("co_init_costs", before.costs);
be_stat_ev("co_init_unsat", before.unsatisfied_edges);
/* Dump the interference graph in Appel's format. */
if(dump_flags & DUMP_APPEL) {
......@@ -1364,21 +1412,23 @@ void co_driver(be_chordal_env_t *cenv)
fclose(f);
}
co_complete_stats(co, &after);
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);
int optimizable_costs = after.max_costs - after.inevit_costs;
int evitable = after.costs - after.inevit_costs;
ir_printf("%30F %10s %10d%10d%10d%10d", cenv->irg, cenv->cls->name,
co_get_max_copy_costs(co), init_costs,
co_get_inevit_copy_costs(co), co_get_lower_bound(co));
ir_printf("%30F %10s %10d%10d%10d", cenv->irg, cenv->cls->name, after.max_costs, before.costs, after.inevit_costs);
if(optimizable_costs > 0)
printf("%10d %5.2f\n", remaining, (evitable * 100.0) / optimizable_costs);
printf("%10d %5.2f\n", after.costs, (evitable * 100.0) / optimizable_costs);
else
printf("%10d %5s\n", remaining, "-");
printf("%10d %5s\n", after.costs, "-");
}
be_stat_ev("co_after_costs", after.costs);
be_stat_ev("co_after_unsat", after.unsatisfied_edges);
co_free_graph_structure(co);
co_free_ou_structure(co);
free_copy_opt(co);
......
......@@ -105,7 +105,26 @@ int co_get_costs_exec_freq(const copy_opt_t *co, ir_node *root, ir_node* arg, in
*/
int co_get_costs_all_one(const copy_opt_t *co, ir_node *root, ir_node* arg, int pos);
/**
* Statistics over a copy optimization module.
*/
typedef struct {
int aff_edges; /**< number of affinity edges. */
int aff_nodes; /**< number of nodes with incident affinity edges. */
int aff_int; /**< number of affinity edges whose nodes also interfere. */
int inevit_costs; /**< costs which cannot be evited (due to interfering affinities). */
int max_costs; /**< all costs of the affinities. */
int costs; /**< The costs of the current coloring. */
int unsatisfied_edges; /**< The number of unequally colored affinity edges. */
} co_complete_stats_t;
/**
* Collect statistics of a copy optimization module.
* @param co The copy optimization environment.
* @param stat Where to put the stats.
* @note This requires the graph info to be computed.
*/
void co_complete_stats(const copy_opt_t *co, co_complete_stats_t *stat);
/**
......
......@@ -100,7 +100,6 @@ typedef struct _unit_t {
typedef struct _neighb_t neighb_t;
typedef struct _affinity_node_t affinity_node_t;
struct _neighb_t {
neighb_t *next; /** the next neighbour entry*/
ir_node *irn; /** the neighbour itself */
......
......@@ -37,6 +37,7 @@
#include "irnode_t.h"
#include "irprintf.h"
#include "irtools.h"
#include "irbitset.h"
#include "beifg_t.h"
#include "beifg_impl.h"
#include "irphase.h"
......@@ -649,3 +650,23 @@ void be_ifg_dump_dot(be_ifg_t *ifg, ir_graph *irg, FILE *file, const be_ifg_dump
fprintf(file, "}\n");
bitset_free(nodes);
}
be_ifg_stat_t *be_ifg_stat(const be_ifg_t *ifg, ir_graph *irg, be_ifg_stat_t *stat)
{
void *nodes_it = be_ifg_nodes_iter_alloca(ifg);
void *neigh_it = be_ifg_neighbours_iter_alloca(ifg);
bitset_t *nodes = bitset_irg_malloc(irg);
ir_node *n, *m;
memset(stat, 0, sizeof(stat[0]));
be_ifg_foreach_node(ifg, nodes_it, n) {
stat->n_nodes += 1;
be_ifg_foreach_neighbour(ifg, neigh_it, n, m) {
bitset_add_irn(nodes, n);
stat->n_edges += !bitset_contains_irn(nodes, m);
}
}
bitset_free(nodes);
}
......@@ -54,6 +54,13 @@ int (be_ifg_degree)(const void *self, const ir_node *irn);
*(count) != -1 ; \
*(count) = be_ifg_cliques_next(self, iter))
typedef struct {
int n_nodes;
int n_edges;
} be_ifg_stat_t;
be_ifg_stat_t *be_ifg_stat(const be_ifg_t *ifg, ir_graph *irg, be_ifg_stat_t *stat);
/*
____ _
| _ \ _ _ _ __ ___ _ __ (_)_ __ __ _
......
......@@ -29,6 +29,7 @@
#include "benode_t.h"
#include "besched_t.h"
#include "benodesets.h"
#include "bestatevent.h"
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
......@@ -139,6 +140,8 @@ static void insert_all_perms_walker(ir_node *bl, void *data) {
in[pp->pos] = pp->arg;
perm = be_new_Perm(chordal_env->cls, irg, pred_bl, n_projs, in);
be_stat_ev("phi_perm", 1);
free(in);
insert_after = sched_skip(sched_last(pred_bl), 0, sched_skip_cf_predicator, chordal_env->birg->main_env->arch_env);
sched_add_after(insert_after, perm);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment