}
/**
- * compare two elements of the block/extbb hash
+ * compare two elements of reg pressure hash
*/
static int reg_pressure_cmp(const void *elt, const void *key)
{
const reg_pressure_entry_t *e1 = elt;
const reg_pressure_entry_t *e2 = key;
- return e1->id_name != e2->id_name;
+ return e1->class_name != e2->class_name;
+}
+
+/**
+ * compare two elements of the perm_stat hash
+ */
+static int perm_stat_cmp(const void *elt, const void *key)
+{
+ const perm_stat_entry_t *e1 = elt;
+ const perm_stat_entry_t *e2 = key;
+
+ return e1->perm != e2->perm;
+}
+
+/**
+ * compare two elements of the perm_class hash
+ */
+static int perm_class_cmp(const void *elt, const void *key)
+{
+ const perm_class_entry_t *e1 = elt;
+ const perm_class_entry_t *e2 = key;
+
+ return e1->class_name != e2->class_name;
}
/**
key.irg = irg;
elem = pset_find(hmap, &key, HASH_PTR(irg));
- if (elem)
+
+ if (elem) {
+ /* create hash map backend block information */
+ if (! elem->be_block_hash)
+ elem->be_block_hash = new_pset(be_block_cmp, 5);
+
return elem;
+ }
/* allocate a new one */
elem = obstack_alloc(&status->cnts, sizeof(*elem));
elem->address_mark = new_set(address_mark_cmp, 5);
elem->irg = irg;
- /* create hash map backend block information */
- elem->be_block_hash = new_pset(be_block_cmp, 5);
-
/* these hash tables are created on demand */
elem->block_hash = NULL;
elem->extbb_hash = NULL;
if (elem->sched_ready)
stat_delete_distrib_tbl(elem->sched_ready);
- elem->reg_pressure = new_pset(reg_pressure_cmp, 5);
- elem->sched_ready = stat_new_int_distrib_tbl();
+ if (elem->perm_class_stat)
+ del_pset(elem->perm_class_stat);
+
+ elem->reg_pressure = new_pset(reg_pressure_cmp, 5);
+ elem->sched_ready = stat_new_int_distrib_tbl();
+ elem->perm_class_stat = new_pset(perm_class_cmp, 5);
}
/**
return pset_insert(hmap, elem, block_nr);
}
+/**
+ * clears all sets in perm_class_entry_t
+ */
+static void perm_class_clear_entry(perm_class_entry_t *elem) {
+ if (elem->perm_stat)
+ del_pset(elem->perm_stat);
+
+ elem->perm_stat = new_pset(perm_stat_cmp, 5);
+}
+
+/**
+ * Returns the associated perm_class entry for a register class.
+ *
+ * @param class_name the register class name
+ * @param hmap a hash map containing class_name -> perm_class_entry_t
+ */
+static perm_class_entry_t *perm_class_get_entry(struct obstack *obst, const char *class_name,
+ hmap_perm_class_entry_t *hmap)
+{
+ perm_class_entry_t key;
+ perm_class_entry_t *elem;
+
+ key.class_name = class_name;
+
+ elem = pset_find(hmap, &key, HASH_PTR(class_name));
+ if (elem)
+ return elem;
+
+ elem = obstack_alloc(obst, sizeof(*elem));
+ memset(elem, 0, sizeof(*elem));
+
+ /* clear new counter */
+ perm_class_clear_entry(elem);
+
+ elem->class_name = class_name;
+
+ return pset_insert(hmap, elem, HASH_PTR(class_name));
+}
+
+/**
+ * clears all sets in perm_stat_entry_t
+ */
+static void perm_stat_clear_entry(perm_stat_entry_t *elem) {
+ if (elem->chains)
+ stat_delete_distrib_tbl(elem->chains);
+
+ if (elem->cycles)
+ stat_delete_distrib_tbl(elem->cycles);
+
+ elem->chains = stat_new_int_distrib_tbl();
+ elem->cycles = stat_new_int_distrib_tbl();
+}
+
+/**
+ * Returns the associated perm_stat entry for a perm.
+ *
+ * @param perm the perm node
+ * @param hmap a hash map containing perm -> perm_stat_entry_t
+ */
+static perm_stat_entry_t *perm_stat_get_entry(struct obstack *obst, ir_node *perm, hmap_perm_stat_entry_t *hmap)
+{
+ perm_stat_entry_t key;
+ perm_stat_entry_t *elem;
+
+ key.perm = perm;
+
+ elem = pset_find(hmap, &key, HASH_PTR(perm));
+ if (elem)
+ return elem;
+
+ elem = obstack_alloc(obst, sizeof(*elem));
+ memset(elem, 0, sizeof(*elem));
+
+ /* clear new counter */
+ perm_stat_clear_entry(elem);
+
+ elem->perm = perm;
+
+ return pset_insert(hmap, elem, HASH_PTR(perm));
+}
/**
* Returns the ir_op for an IR-node,
/* 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 (graph->irg != get_const_code_irg()) {
if (get_irg_dom_state(graph->irg) != dom_consistent)
compute_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 */
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 ident name of the register class
+ * @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, ident *class_name)
+void stat_be_block_regpressure(ir_graph *irg, ir_node *block, int pressure, const char *class_name)
+{
+ 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;
+
+ 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;
+
+ pset_insert(block_ent->reg_pressure, rp_ent, HASH_PTR(class_name));
+ }
+ STAT_LEAVE;
+}
+
+/**
+ * Update the distribution of ready nodes of a block
+ *
+ * @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
+ */
+void stat_be_block_sched_ready(ir_graph *irg, ir_node *block, int num_ready)
{
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;
+ graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
+ be_block_entry_t *block_ent;
+
+ block_ent = be_block_get_entry(&status->be_data, get_irn_node_nr(block), graph->be_block_hash);
+
+ /* increase the counter of corresponding number of ready nodes */
+ stat_inc_int_distrib_tbl(block_ent->sched_ready, num_ready);
+ }
+ STAT_LEAVE;
+}
- /* create new be_block hash */
- if (! graph->be_block_hash)
- graph->be_block_hash = new_pset(be_block_cmp, 5);
+/**
+ * Update the permutation statistic of a block
+ *
+ * @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(const char *class_name, int n_regs, ir_node *perm, ir_node *block,
+ int size, int real_size)
+{
+ if (! status->stat_options)
+ return;
+
+ STAT_ENTER;
+ {
+ graph_entry_t *graph = graph_get_entry(get_irn_irg(block), status->irg_hash);
+ be_block_entry_t *block_ent;
+ perm_class_entry_t *pc_ent;
+ perm_stat_entry_t *ps_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));
+ pc_ent = perm_class_get_entry(&status->be_data, class_name, block_ent->perm_class_stat);
+ ps_ent = perm_stat_get_entry(&status->be_data, perm, pc_ent->perm_stat);
- rp_ent->id_name = class_name;
- rp_ent->pressure = pressure;
+ pc_ent->n_regs = n_regs;
- pset_insert(block_ent->reg_pressure, rp_ent, HASH_PTR(class_name));
+ /* update information */
+ ps_ent->size = size;
+ ps_ent->real_size = real_size;
}
STAT_LEAVE;
}
/**
- * Update the distribution of ready nodes of a block
+ * Update the permutation statistic of a single perm
*
- * @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 num_ready the number of ready nodes
+ * @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
*/
-static void stat_be_block_sched_ready(void *ctx, ir_node *block, ir_graph *irg, int num_ready)
+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)
return;
STAT_ENTER;
{
- graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
- be_block_entry_t *block_ent;
- counter_t cnt_1;
-
- /* create new be_block hash */
- if (! graph->be_block_hash)
- graph->be_block_hash = new_pset(be_block_cmp, 5);
+ graph_entry_t *graph = graph_get_entry(get_irn_irg(block), status->irg_hash);
+ be_block_entry_t *block_ent;
+ perm_class_entry_t *pc_ent;
+ perm_stat_entry_t *ps_ent;
block_ent = be_block_get_entry(&status->be_data, get_irn_node_nr(block), graph->be_block_hash);
+ pc_ent = perm_class_get_entry(&status->be_data, class_name, block_ent->perm_class_stat);
+ ps_ent = perm_stat_get_entry(&status->be_data, perm, pc_ent->perm_stat);
- /* add 1 to the counter of orresponding number of ready nodes */
- cnt_clr(&cnt_1);
- cnt_inc(&cnt_1);
- stat_add_int_distrib_tbl(block_ent->sched_ready, num_ready, &cnt_1);
+ if (is_chain) {
+ ps_ent->n_copies += n_ops;
+ stat_inc_int_distrib_tbl(ps_ent->chains, size);
+ }
+ else {
+ ps_ent->n_exchg += n_ops;
+ stat_inc_int_distrib_tbl(ps_ent->cycles, size);
+ }
}
STAT_LEAVE;
}
-
/* Dumps a statistics snapshot */
void stat_dump_snapshot(const char *name, const char *phase)
{
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);
obstack_init(&status->cnts);
obstack_init(&status->be_data);
}
}
+/* 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. */