+/**
+ * Update the permutation statistic of a single perm.
+ *
+ * @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(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(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);
+
+ 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);
+ } /* if */
+ }
+ STAT_LEAVE;
+} /* stat_be_block_stat_permcycle */
+
+/* Dumps a statistics snapshot. */
+void stat_dump_snapshot(const char *name, const char *phase)
+{
+ char fname[2048];
+ const char *p;
+ int l;
+
+ if (! status->stat_options)
+ return;
+
+ STAT_ENTER;
+ {
+ graph_entry_t *entry;
+ graph_entry_t *global = graph_get_entry(NULL, status->irg_hash);
+
+ /*
+ * The constant counter is only global, so we clear it here.
+ * Note that it does NOT contain the constants in DELETED
+ * graphs due to this.
+ */
+ if (status->stat_options & FIRMSTAT_COUNT_CONSTS)
+ stat_const_clear(status);
+
+ /* build the name */
+ p = strrchr(name, '/');
+#ifdef _WIN32
+ {
+ const char *q;
+
+ q = strrchr(name, '\\');
+
+ /* NULL might be not the smallest pointer */
+ if (q && (!p || q > p))
+ p = q;
+ }
+#endif /* _WIN32 */
+ if (p) {
+ ++p;
+ l = p - name;
+
+ if (l > (int) (sizeof(fname) - 1))
+ l = sizeof(fname) - 1;
+
+ memcpy(fname, name, l);
+ fname[l] = '\0';
+ } else {
+ fname[0] = '\0';
+ p = name;
+ } /* if */
+ strncat(fname, "firmstat-", sizeof(fname));
+ strncat(fname, phase, sizeof(fname));
+ strncat(fname, "-", sizeof(fname));
+ strncat(fname, p, sizeof(fname));
+
+ stat_dump_init(fname);
+
+ /* calculate the graph statistics */
+ for (entry = pset_first(status->irg_hash); entry; entry = pset_next(status->irg_hash)) {
+ if (entry->irg == NULL) {
+ /* special entry for the global count */
+ continue;
+ } /* if */
+ if (! entry->is_deleted) {
+ /* the graph is still alive, count the nodes on it */
+ update_graph_stat(global, entry);
+ } /* if */
+ } /* for */
+
+ /* some calculations are dependent, we pushed them on the wait_q */
+ while (! pdeq_empty(status->wait_q)) {
+ entry = pdeq_getr(status->wait_q);
+
+ update_graph_stat_2(global, entry);
+ } /* while */
+
+ /* dump per graph */
+ for (entry = pset_first(status->irg_hash); entry; entry = pset_next(status->irg_hash)) {
+ if (entry->irg == NULL) {
+ /* special entry for the global count */
+ continue;
+ } /* if */
+
+ if (! entry->is_deleted || status->stat_options & FIRMSTAT_COUNT_DELETED) {
+ stat_dump_graph(entry);
+ stat_dump_registered(entry);
+ } /* if */
+
+ if (! entry->is_deleted) {
+ /* clear the counter that are not accumulated */
+ graph_clear_entry(entry, 0);
+ } /* if */
+ } /* for */
+
+ /* dump global */
+ stat_dump_graph(global);
+
+ /* dump the const info */
+ if (status->stat_options & FIRMSTAT_COUNT_CONSTS)
+ stat_dump_consts(&status->const_info);
+
+ /* dump the parameter distribution */
+ stat_dump_param_tbl(status->dist_param_cnt, global);
+
+ /* dump the optimization counter and clear them */
+ stat_dump_opt_cnt(status->num_opts, ARR_SIZE(status->num_opts));
+ clear_optimization_counter();
+
+ stat_dump_finish();
+
+ stat_finish_pattern_history(fname);
+
+ /* clear the global counter here */
+ {
+ node_entry_t *entry;
+
+ for (entry = pset_first(global->opcode_hash); entry; entry = pset_next(global->opcode_hash)) {
+ opcode_clear_entry(entry);
+ } /* for */
+ /* clear all global counter */
+ graph_clear_entry(global, 1);
+ }
+ }
+ STAT_LEAVE;
+} /* stat_dump_snapshot */
+
+/** the hook entries for the Firm statistics module */
+static hook_entry_t stat_hooks[hook_last];