graph_clear_entry(elem, 1);
/* new hash table for opcodes here */
- elem->opcode_hash = new_pset(opcode_cmp, 5);
- elem->address_mark = new_set(address_mark_cmp, 5);
- elem->irg = irg;
+ elem->opcode_hash = new_pset(opcode_cmp, 5);
+ elem->address_mark = new_set(address_mark_cmp, 5);
+ elem->irg = irg;
/* these hash tables are created on demand */
elem->block_hash = NULL;
/* count extended block edges */
if (status->stat_options & FIRMSTAT_COUNT_EXTBB) {
- undate_extbb_info(node, graph);
+ if (graph->irg != get_const_code_irg())
+ undate_extbb_info(node, graph);
}
/* handle statistics for special node types */
graph->block_hash = new_pset(block_cmp, 5);
/* we need dominator info */
- if (graph->irg != get_const_code_irg())
- if (get_irg_dom_state(graph->irg) != dom_consistent)
- compute_doms(graph->irg);
+ if (graph->irg != get_const_code_irg()) {
+ assure_doms(graph->irg);
- if (status->stat_options & FIRMSTAT_COUNT_EXTBB) {
- /* we need extended basic blocks */
- compute_extbb(graph->irg);
+ if (status->stat_options & FIRMSTAT_COUNT_EXTBB) {
+ /* we need extended basic blocks */
+ compute_extbb(graph->irg);
- /* create new extbb counter */
- graph->extbb_hash = new_pset(block_cmp, 5);
+ /* create new extbb counter */
+ graph->extbb_hash = new_pset(block_cmp, 5);
+ }
}
/* count the nodes in the graph */
dumper_t *p = xmalloc(sizeof(*p));
if (p) {
- *p = *dumper;
+ memcpy(p, dumper, sizeof(*p));
p->next = status->dumper;
p->status = status;
}
}
+/**
+ * calls all registered functions.
+ */
+static void stat_dump_registered(graph_entry_t *entry)
+{
+ dumper_t *dumper;
+
+ for (dumper = status->dumper; dumper; dumper = dumper->next) {
+ if (dumper->func_map) {
+ dump_graph_FUNC func;
+
+ foreach_pset(dumper->func_map, func)
+ func(dumper, entry);
+ }
+ }
+}
+
/**
* dumps a constant table
*/
}
}
+/**
+ * register an additional function for all dumper
+ */
+void stat_register_dumper_func(dump_graph_FUNC func) {
+ dumper_t *dumper;
+
+ for (dumper = status->dumper; dumper; dumper = dumper->next) {
+ if (! dumper->func_map)
+ dumper->func_map = pset_new_ptr(3);
+ pset_insert_ptr(dumper->func_map, func);
+ }
+}
+
/* ---------------------------------------------------------------------- */
/*
*
* @param ctx the hook context
*/
-static void stat_strength_red(void *ctx, ir_graph *irg, ir_node *strong, ir_node *cmp)
+static void stat_strength_red(void *ctx, ir_graph *irg, ir_node *strong)
{
if (! status->stat_options)
return;
STAT_LEAVE;
}
-/**
+/*
* Update the register pressure of a block
*
- * @param ctx the hook context
- * @param block the block for which the reg pressure should be set
* @param irg the irg containing the block
+ * @param block the block for which the reg pressure should be set
* @param pressure the pressure
* @param class_name the name of the register class
*/
-static void stat_be_block_regpressure(void *ctx, ir_node *block, ir_graph *irg, int pressure, const char *class_name)
+void stat_be_block_regpressure(ir_graph *irg, ir_node *block, int pressure, const char *class_name)
{
- if (! status->stat_options)
- return;
+ if (! status->stat_options)
+ return;
- STAT_ENTER;
- {
- graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
- be_block_entry_t *block_ent;
- reg_pressure_entry_t *rp_ent;
+ STAT_ENTER;
+ {
+ graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
+ be_block_entry_t *block_ent;
+ reg_pressure_entry_t *rp_ent;
- block_ent = be_block_get_entry(&status->be_data, get_irn_node_nr(block), graph->be_block_hash);
- rp_ent = obstack_alloc(&status->be_data, sizeof(*rp_ent));
- memset(rp_ent, 0, sizeof(*rp_ent));
+ block_ent = be_block_get_entry(&status->be_data, get_irn_node_nr(block), graph->be_block_hash);
+ rp_ent = obstack_alloc(&status->be_data, sizeof(*rp_ent));
+ memset(rp_ent, 0, sizeof(*rp_ent));
- rp_ent->class_name = class_name;
- rp_ent->pressure = pressure;
+ rp_ent->class_name = class_name;
+ rp_ent->pressure = pressure;
- pset_insert(block_ent->reg_pressure, rp_ent, HASH_PTR(class_name));
- }
- STAT_LEAVE;
+ pset_insert(block_ent->reg_pressure, rp_ent, HASH_PTR(class_name));
+ }
+ STAT_LEAVE;
}
/**
* Update the distribution of ready nodes of a block
*
- * @param ctx the hook context
- * @param block the block for which the reg pressure should be set
* @param irg the irg containing the block
+ * @param block the block for which the reg pressure should be set
* @param num_ready the number of ready nodes
*/
-static void stat_be_block_sched_ready(void *ctx, ir_node *block, ir_graph *irg, int num_ready)
+void stat_be_block_sched_ready(ir_graph *irg, ir_node *block, int num_ready)
{
if (! status->stat_options)
return;
{
graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
be_block_entry_t *block_ent;
- const counter_t *cnt_1 = cnt_get_1();
block_ent = be_block_get_entry(&status->be_data, get_irn_node_nr(block), graph->be_block_hash);
- /* add 1 to the counter of corresponding number of ready nodes */
- stat_add_int_distrib_tbl(block_ent->sched_ready, num_ready, cnt_1);
+ /* increase the counter of corresponding number of ready nodes */
+ stat_inc_int_distrib_tbl(block_ent->sched_ready, num_ready);
}
STAT_LEAVE;
}
/**
* Update the permutation statistic of a block
*
- * @param ctx the hook context
* @param class_name the name of the register class
+ * @param n_regs number of registers in the register class
* @param perm the perm node
* @param block the block containing the perm
* @param size the size of the perm
* @param real_size number of pairs with different registers
*/
-void stat_be_block_stat_perm(void *ctx, const char *class_name, int n_regs, ir_node *perm, ir_node *block,
+void stat_be_block_stat_perm(const char *class_name, int n_regs, ir_node *perm, ir_node *block,
int size, int real_size)
{
if (! status->stat_options)
/**
* Update the permutation statistic of a single perm
*
- * @param ctx the hook context
* @param class_name the name of the register class
* @param perm the perm node
* @param block the block containing the perm
* @param is_chain 1 if chain, 0 if cycle
+ * @param size length of the cycle/chain
* @param n_ops the number of ops representing this cycle/chain after lowering
*/
-void stat_be_block_stat_permcycle(void *ctx, const char *class_name, ir_node *perm, ir_node *block,
+void stat_be_block_stat_permcycle(const char *class_name, ir_node *perm, ir_node *block,
int is_chain, int size, int n_ops)
{
if (! status->stat_options)
STAT_ENTER;
{
graph_entry_t *graph = graph_get_entry(get_irn_irg(block), status->irg_hash);
- const counter_t *cnt_1 = cnt_get_1();
be_block_entry_t *block_ent;
perm_class_entry_t *pc_ent;
perm_stat_entry_t *ps_ent;
if (is_chain) {
ps_ent->n_copies += n_ops;
- stat_add_int_distrib_tbl(ps_ent->chains, size, cnt_1);
+ stat_inc_int_distrib_tbl(ps_ent->chains, size);
}
else {
ps_ent->n_exchg += n_ops;
- stat_add_int_distrib_tbl(ps_ent->cycles, size, cnt_1);
+ stat_inc_int_distrib_tbl(ps_ent->cycles, size);
}
}
STAT_LEAVE;
if (! entry->is_deleted || status->stat_options & FIRMSTAT_COUNT_DELETED) {
stat_dump_graph(entry);
+ stat_dump_registered(entry);
}
if (! entry->is_deleted) {
HOOK(hook_func_call, stat_func_call);
HOOK(hook_arch_dep_replace_mul_with_shifts, stat_arch_dep_replace_mul_with_shifts);
HOOK(hook_arch_dep_replace_division_by_const, stat_arch_dep_replace_division_by_const);
- HOOK(hook_be_block_regpressure, stat_be_block_regpressure);
- HOOK(hook_be_block_sched_ready, stat_be_block_sched_ready);
- HOOK(hook_be_block_stat_perm, stat_be_block_stat_perm);
- HOOK(hook_be_block_stat_permcycle, stat_be_block_stat_permcycle);
obstack_init(&status->cnts);
obstack_init(&status->be_data);
#undef X
}
+/**
+ * Frees all dumper structures;
+ */
+static void stat_term_dumper() {
+ dumper_t *dumper, *next_dumper;
+
+ for (dumper = status->dumper; dumper; /* iteration done in loop body */ ) {
+ if (dumper->func_map)
+ del_pset(dumper->func_map);
+
+ next_dumper = dumper->next;
+ free(dumper);
+ dumper = next_dumper;
+ }
+}
+
+
/* terminates the statistics module, frees all memory */
void stat_term(void) {
if (status != (stat_info_t *)&status_disable) {
obstack_free(&status->be_data, NULL);
obstack_free(&status->cnts, NULL);
+
+ stat_term_dumper();
+
xfree(status);
status = (stat_info_t *)&status_disable;
}
}
+/* returns 1 if statistics were initialized, 0 otherwise */
+int stat_is_active(void) {
+ return status != (stat_info_t *)&status_disable;
+}
+
#else
/* initialize the statistics module. */