summaryrefslogtreecommitdiffhomepage
path: root/ir/stat
diff options
context:
space:
mode:
authorMatthias Braun <matze@braunis.de>2015-09-19 21:03:53 +0200
committerMatthias Braun <matze@braunis.de>2015-09-19 21:29:34 +0200
commitaa7c5e023514273149afd3b0129f42227f925fd7 (patch)
treef4afc8e231653cc479e03557b8d02090b8efd74e /ir/stat
parentec1b79145891563a7f08c3e6c91a4b4e8203c51f (diff)
Remove firmstat
It is barely used but cross cuts into most libfirm components and therefore isn't maintenance free. The statev framework stays obviously.
Diffstat (limited to 'ir/stat')
-rw-r--r--ir/stat/const_stat.c137
-rw-r--r--ir/stat/counter.h186
-rw-r--r--ir/stat/dags.c378
-rw-r--r--ir/stat/dags.h20
-rw-r--r--ir/stat/distrib.c140
-rw-r--r--ir/stat/firmstat.c1792
-rw-r--r--ir/stat/firmstat_t.h517
-rw-r--r--ir/stat/pattern.c911
-rw-r--r--ir/stat/pattern.h35
-rw-r--r--ir/stat/pattern_dmp.c406
-rw-r--r--ir/stat/pattern_dmp.h76
-rw-r--r--ir/stat/stat_dmp.c663
-rw-r--r--ir/stat/stat_dmp.h28
13 files changed, 0 insertions, 5289 deletions
diff --git a/ir/stat/const_stat.c b/ir/stat/const_stat.c
deleted file mode 100644
index 4b3c2a3..0000000
--- a/ir/stat/const_stat.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * This file is part of libFirm.
- * Copyright (C) 2012 University of Karlsruhe.
- */
-
-/**
- * @file
- * @brief Statistic functions for constant counting.
- * @author Michael Beck
- */
-#include "firmstat_t.h"
-#include "tv_t.h"
-#include "util.h"
-
-/**
- * calculated the dual logarithm of |value|
- */
-static unsigned log2abs(long value)
-{
- unsigned res = 0;
-
- if (value < 0)
- value = -value;
-
- if (value > 0xFFFF) {
- res += 16;
- value >>= 16;
- }
- if (value > 0xFF) {
- res += 8;
- value >>= 8;
- }
- if (value > 0xF) {
- res += 4;
- value >>= 4;
- }
- if (value > 3) {
- res += 2;
- value >>= 2;
- }
- if (value > 1) {
- res += 1;
- }
-
- return res;
-}
-
-/**
- * classify the value of a float tarval
- */
-static float_classify_t classify_float_value(ir_tarval *tv)
-{
- ir_mode *mode = get_tarval_mode(tv);
-
- if (tv == get_mode_null(mode)) {
- return STAT_FC_0;
- } else if (tv == get_mode_one(mode)) {
- return STAT_FC_1;
- } else if (tarval_is_finite(tv) && tarval_zero_mantissa(tv)) {
- int exp = tarval_get_exponent(tv);
-
- if (! tarval_is_negative(tv)) {
- if (exp == 1)
- return STAT_FC_2;
- else if (exp == -1)
- return STAT_FC_0_5;
- }
- return STAT_FC_POWER_OF_TWO;
- }
- return STAT_FC_OTHER;
-}
-
-/* return a human readable name for an float classification */
-const char *stat_fc_name(float_classify_t classification)
-{
- switch (classification) {
- case STAT_FC_0: return "0.0";
- case STAT_FC_1: return "1.0";
- case STAT_FC_2: return "2.0";
- case STAT_FC_0_5: return "0.5";
- case STAT_FC_POWER_OF_TWO: return "2.0^x";
- case STAT_FC_OTHER: return "other";
- default: return "<UNKNOWN>";
- }
-}
-
-/* update info on Consts */
-void stat_update_const(stat_info_t *status, ir_node *node, graph_entry_t *graph)
-{
- ir_mode *mode = get_irn_mode(node);
- ir_tarval *tv;
- unsigned bits;
- (void) graph;
-
- if (mode_is_int(mode)) {
- tv = get_Const_tarval(node);
-
- /* FIXME: */
- if (! tarval_is_long(tv))
- return;
-
- bits = log2abs(get_tarval_long(tv));
-
- if (bits > ARRAY_SIZE(status->const_info.int_bits_count))
- bits = ARRAY_SIZE(status->const_info.int_bits_count);
-
- cnt_inc(&status->const_info.int_bits_count[bits]);
- } else if (mode_is_float(mode)) {
- tv = get_Const_tarval(node);
-
- cnt_inc(&status->const_info.floats[classify_float_value(tv)]);
- } else {
- /* something different */
- cnt_inc(&status->const_info.others);
- }
-}
-
-/* clears the const statistics for a new snapshot */
-void stat_const_clear(stat_info_t *status)
-{
- size_t i;
-
- for (i = 0; i < ARRAY_SIZE(status->const_info.int_bits_count); ++i)
- cnt_clr(&status->const_info.int_bits_count[i]);
-
- for (i = 0; i < ARRAY_SIZE(status->const_info.floats); ++i)
- cnt_clr(&status->const_info.floats[i]);
-
- cnt_clr(&status->const_info.others);
-}
-
-/* initialize the Const statistic. */
-void stat_init_const_cnt(stat_info_t *status)
-{
- (void) status;
- /* currently nothing */
-}
diff --git a/ir/stat/counter.h b/ir/stat/counter.h
deleted file mode 100644
index 69cc3dc..0000000
--- a/ir/stat/counter.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * This file is part of libFirm.
- * Copyright (C) 2012 University of Karlsruhe.
- */
-
-/**
- * @file
- * @brief Statistics for Firm. Counter implementation.
- * @author Michael Beck
- */
-#ifndef FIRM_STAT_COUNTER_H
-#define FIRM_STAT_COUNTER_H
-
-#include <string.h>
-#include <limits.h>
-
-/*
- * 32 bit should be enough for most cases
- */
-#ifndef STAT_CNT_NUM
-#define STAT_CNT_NUM 1
-#endif
-
-typedef struct counter_t {
- unsigned cnt[STAT_CNT_NUM];
-} counter_t;
-
-/** initializes a counter with zero */
-#define ZERO_CNT { { 0 } }
-
-/**
- * increase a counter
- */
-static inline void cnt_inc(counter_t *cnt)
-{
- int i;
-
- for (i = 0; i < STAT_CNT_NUM; ++i) {
- if (++cnt->cnt[i])
- break;
- }
-}
-
-/**
- * decrease a counter
- */
-static inline void cnt_dec(counter_t *cnt)
-{
- int i;
-
- for (i = 0; i < STAT_CNT_NUM; ++i) {
- if (--cnt->cnt[i] != (unsigned) -1)
- break;
- }
-}
-
-/**
- * set a counter to zero
- */
-static inline void cnt_clr(counter_t *cnt)
-{
- memset(cnt->cnt, 0, sizeof(cnt->cnt));
-}
-
-/**
- * add a counter to another
- */
-static inline void cnt_add(counter_t *dst, const counter_t *src)
-{
- int i, carry = 0;
-
- for (i = 0; i < STAT_CNT_NUM; ++i) {
- unsigned x = dst->cnt[i];
- unsigned y = src->cnt[i];
- unsigned a = x + y + carry;
-
- carry = (int)((x & y) | ((x | y) & ~a)) < 0 ? 1 : 0;
-
- dst->cnt[i] = a;
- }
-}
-
-/**
- * add an (positive) integer to an counter
- */
-static inline void cnt_add_i(counter_t *dst, int src)
-{
- int i;
- unsigned carry = src;
-
- for (i = 0; i < STAT_CNT_NUM; ++i) {
- unsigned a = dst->cnt[i] + carry;
-
- carry = a < dst->cnt[i];
-
- dst->cnt[i] = a;
-
- if (! carry)
- break;
- }
-}
-
-/**
- * compare two counter
- */
-static inline int cnt_cmp(const counter_t *a, const counter_t *b)
-{
- int i;
- unsigned va = 0;
- unsigned vb = 0;
-
- for (i = STAT_CNT_NUM - 1 ; i >= 0; --i) {
- va = a->cnt[i];
- vb = b->cnt[i];
-
- if (va != vb)
- break;
- }
-
- if (va != vb)
- return va < vb ? -1 : 1;
- return 0;
-}
-
-/**
- * convert a counter into a double
- */
-static inline double cnt_to_dbl(const counter_t *a)
-{
- int i;
- double res = 0.0, scale = 1.0, tmp;
-
- i = (1 << (sizeof(a->cnt[0]) * 4));
- tmp = ((double)i) * ((double)i);
-
- for (i = 0; i < STAT_CNT_NUM; ++i) {
- res += scale * (double)a->cnt[i];
-
- scale *= tmp;
- }
- return res;
-}
-
-/**
- * convert a counter into an unsigned
- */
-static inline unsigned cnt_to_uint(const counter_t *a)
-{
- int i;
-
- for (i = 1; i < STAT_CNT_NUM; ++i)
- if (a->cnt[i])
- return UINT_MAX;
-
- return a->cnt[0];
-}
-
-/**
- * check, if a counter is equal to an unsigned
- */
-static inline int cnt_eq(const counter_t *a, unsigned value)
-{
- int i;
-
- for (i = 1; i < STAT_CNT_NUM; ++i)
- if (a->cnt[i])
- return 0;
-
- return a->cnt[0] == value;
-}
-
-/**
- * check, if a counter as greater than an unsigned
- */
-static inline int cnt_gt(const counter_t *a, unsigned value)
-{
- int i;
-
- for (i = 1; i < STAT_CNT_NUM; ++i)
- if (a->cnt[i])
- return 1;
-
- return a->cnt[0] > value;
-}
-
-#endif
diff --git a/ir/stat/dags.c b/ir/stat/dags.c
deleted file mode 100644
index b2b04c7..0000000
--- a/ir/stat/dags.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * This file is part of libFirm.
- * Copyright (C) 2012 University of Karlsruhe.
- */
-
-/**
- * @file
- * @brief Statistics for Firm. DAG's in graphs.
- * @author Michael Beck
- */
-#include <assert.h>
-
-#include "irdump.h"
-#include "dags.h"
-#include "irtools.h"
-#include "ircons.h"
-
-enum dag_counting_options_t {
- FIRMSTAT_COPY_CONSTANTS = 0x00000001, /**< if set, constants will be treated as they are in
- the same block as its successors */
- FIRMSTAT_LOAD_IS_LEAVE = 0x00000002, /**< Load nodes are always leaves */
- FIRMSTAT_CALL_IS_LEAVE = 0x00000004, /**< Call nodes are always leaves */
- FIRMSTAT_ARGS_ARE_ROOTS = 0x00000008, /**< arguments (Proj(Proj(Start)) are roots */
-};
-
-typedef struct dag_entry_t dag_entry_t;
-
-/**
- * Environment for connecting DAG's
- */
-typedef struct dag_env_t {
- struct obstack obst;
- unsigned num_of_dags; /**< Number of found DAGs so far. */
- dag_entry_t *list_of_dags; /**< List of found DAGs. */
- unsigned options; /**< DAG counting options. */
-} dag_env_t;
-
-/**
- * a DAG Entry
- */
-struct dag_entry_t {
- unsigned id; /**< assigned ID for this DAG */
- ir_node *root; /**< one root of the DAG */
- unsigned num_roots; /**< number of root nodes in the DAG */
- unsigned num_nodes; /**< overall number of nodes in the DAG */
- unsigned num_inner_nodes; /**< number of inner nodes in the DAG */
- unsigned is_dead:1; /**< marks a dead entry */
- unsigned is_tree:1; /**< True if this DAG is a tree. */
- unsigned is_ext_ref:1; /**< True if this DAG is external referenced, so it cannot be combined. */
- dag_entry_t *next; /**< link all entries of a DAG */
- dag_entry_t *link; /**< if set, this entry is an ID */
-};
-
-/**
- * return an DAG entry for the node n
- */
-static dag_entry_t *get_irn_dag_entry(const ir_node *n)
-{
- dag_entry_t *p = (dag_entry_t*)get_irn_link(n);
-
- if (p) {
- /* skip any dead links */
- if (p->link) {
- do {
- p = p->link;
- } while (p->link != NULL);
- /* hacky cast to ir_node* */
- set_irn_link((ir_node*)n, p);
- }
- }
- return p;
-}
-
-#define set_irn_dag_entry(n, e) set_irn_link(n, e)
-
-/**
- * checks whether a node is an arg
- */
-static int is_arg(ir_node *node)
-{
- if (! is_Proj(node))
- return 0;
-
- node = get_Proj_pred(node);
- if (! is_Proj(node))
- return 0;
-
- node = get_Proj_pred(node);
- return is_Start(node);
-}
-
-/**
- * Allocate a new DAG entry.
- */
-static dag_entry_t *new_dag_entry(dag_env_t *dag_env, ir_node *node)
-{
- dag_entry_t *entry = OALLOC(&dag_env->obst, dag_entry_t);
-
- entry->num_nodes = 1;
- entry->num_roots = 1;
- entry->num_inner_nodes = 0;
- entry->root = node;
- entry->is_dead = 0;
- entry->is_tree = 1;
- entry->is_ext_ref = 0;
- entry->next = dag_env->list_of_dags;
- entry->link = NULL;
-
- ++dag_env->num_of_dags;
- dag_env->list_of_dags = entry;
-
- set_irn_dag_entry(node, entry);
- return entry;
-}
-
-/**
- * Post-walker to detect DAG roots that are referenced form other blocks
- */
-static void find_dag_roots(ir_node *node, void *env)
-{
- dag_env_t *dag_env = (dag_env_t*)env;
- dag_entry_t *entry;
- ir_node *block;
-
- if (is_Block(node))
- return;
-
- block = get_nodes_block(node);
-
- /* ignore start end end blocks */
- ir_graph *const irg = get_irn_irg(node);
- if (block == get_irg_start_block(irg) || block == get_irg_end_block(irg))
- return;
-
- /* Phi nodes always references nodes from "other" block */
- if (is_Phi(node)) {
- if (get_irn_mode(node) != mode_M) {
- foreach_irn_in(node, i, prev) {
- if (is_Phi(prev))
- continue;
-
- if (dag_env->options & FIRMSTAT_COPY_CONSTANTS) {
- if (is_irn_constlike(prev))
- continue;
- }
-
- entry = get_irn_dag_entry(prev);
-
- if (! entry) {
- /* found an unassigned node, a new root */
- entry = new_dag_entry(dag_env, node);
- entry->is_ext_ref = 1;
- }
- }
- }
- } else {
- foreach_irn_in(node, i, prev) {
- ir_mode *mode = get_irn_mode(prev);
-
- if (mode == mode_X || mode == mode_M)
- continue;
-
- if (is_Phi(prev))
- continue;
-
- if (dag_env->options & FIRMSTAT_COPY_CONSTANTS) {
- if (is_irn_constlike(prev))
- continue;
- }
-
- if (get_nodes_block(prev) != block) {
- /* The predecessor is from another block. It forms
- a root. */
- entry = get_irn_dag_entry(prev);
- if (! entry) {
- /* found an unassigned node, a new root */
- entry = new_dag_entry(dag_env, node);
- entry->is_ext_ref = 1;
- }
- }
- }
- }
-}
-
-/**
- * Pre-walker for connecting DAGs and counting.
- */
-static void connect_dags(ir_node *node, void *env)
-{
- dag_env_t *dag_env = (dag_env_t*)env;
- ir_node *block;
- dag_entry_t *entry;
- ir_mode *mode;
-
- if (is_Block(node))
- return;
-
- block = get_nodes_block(node);
-
- /* ignore start end end blocks */
- ir_graph *const irg = get_irn_irg(node);
- if (block == get_irg_start_block(irg) || block == get_irg_end_block(irg))
- return;
-
- /* ignore Phi nodes */
- if (is_Phi(node))
- return;
-
- if (dag_env->options & FIRMSTAT_ARGS_ARE_ROOTS && is_arg(node))
- return;
-
- mode = get_irn_mode(node);
- if (mode == mode_X || mode == mode_M) {
- /* do NOT count mode_X and mode_M nodes */
- return;
- }
-
- /* if this option is set, Loads are always leaves */
- if (dag_env->options & FIRMSTAT_LOAD_IS_LEAVE && is_Load(node))
- return;
-
- if (dag_env->options & FIRMSTAT_CALL_IS_LEAVE && is_Call(node))
- return;
-
- entry = get_irn_dag_entry(node);
-
- if (! entry) {
- /* found an unassigned node, maybe a new root */
- entry = new_dag_entry(dag_env, node);
- }
-
- /* put the predecessors into the same DAG as the current */
- foreach_irn_in(node, i, prev) {
- ir_mode *mode = get_irn_mode(prev);
-
- if (is_Phi(prev))
- continue;
-
- if (mode == mode_X || mode == mode_M)
- continue;
-
- /*
- * copy constants if requested into the DAG's
- * beware, do NOT add a link, as this will result in
- * wrong intersections
- */
- if (dag_env->options & FIRMSTAT_COPY_CONSTANTS) {
- if (is_irn_constlike(prev)) {
- ++entry->num_nodes;
- ++entry->num_inner_nodes;
- }
- }
-
- /* only nodes from the same block goes into the DAG */
- if (get_nodes_block(prev) == block) {
- dag_entry_t *prev_entry = get_irn_dag_entry(prev);
-
- if (! prev_entry) {
- /* not assigned node, put it into the same DAG */
- set_irn_dag_entry(prev, entry);
- ++entry->num_nodes;
- ++entry->num_inner_nodes;
- } else {
- if (prev_entry == entry) {
- /* We found a node that is already assigned to this DAG.
- This DAG is not a tree. */
- entry->is_tree = 0;
- } else {
- /* two DAGs intersect: copy the data to one of them
- and kill the other */
- entry->num_roots += prev_entry->num_roots;
- entry->num_nodes += prev_entry->num_nodes;
- entry->num_inner_nodes += prev_entry->num_inner_nodes;
- entry->is_tree &= prev_entry->is_tree;
-
- --dag_env->num_of_dags;
-
- prev_entry->is_dead = 1;
- prev_entry->link = entry;
- }
- }
- }
- }
-}
-
-#define DEFAULT_RET 1
-#define COLOR_RET 1
-
-static unsigned mark_options;
-
-/**
- * a vcg attribute hook
- */
-static int stat_dag_mark_hook(FILE *F, const ir_node *n, const ir_node *l)
-{
- static const char *colors[] = { "purple", "pink", "lightblue", "orange", "khaki", "orchid", "lilac", "turquoise" };
- dag_entry_t *entry;
-
- /* do not count Bad / NoMem */
- if (l) {
- if (is_NoMem(l) || is_Bad(l))
- return DEFAULT_RET;
-
- /* check for additional options */
- if (mark_options & FIRMSTAT_LOAD_IS_LEAVE && is_Load(n))
- return DEFAULT_RET;
-
- if (mark_options & FIRMSTAT_CALL_IS_LEAVE && is_Call(n))
- return DEFAULT_RET;
- }
-
- entry = get_irn_dag_entry(n);
- if (! entry)
- return DEFAULT_RET;
-
- fprintf(F, "color: %s info3: \"DAG id: %u\"", colors[entry->id & 7], entry->id);
-
- /* I know the color! */
- return COLOR_RET;
-}
-
-/**
- * count the DAG's size of a graph
- *
- * @param global the global entry
- * @param graph the current graph entry
- */
-void count_dags_in_graph(graph_entry_t *global, graph_entry_t *graph)
-{
- dag_env_t root_env;
- dag_entry_t *entry;
- unsigned id;
- (void) global;
-
- /* do NOT check the const code irg */
- if (graph->irg == get_const_code_irg())
- return;
-
- /* first step, clear the links */
- irg_walk_graph(graph->irg, firm_clear_link, NULL, NULL);
-
- obstack_init(&root_env.obst);
- root_env.num_of_dags = 0;
- root_env.list_of_dags = NULL;
- root_env.options = FIRMSTAT_COPY_CONSTANTS | FIRMSTAT_LOAD_IS_LEAVE | FIRMSTAT_CALL_IS_LEAVE;
-
- /* find the DAG roots that are referenced from other block */
- irg_walk_graph(graph->irg, NULL, find_dag_roots, &root_env);
-
- /* connect and count them */
- irg_walk_graph(graph->irg, connect_dags, NULL, &root_env);
-
- printf("Graph %p %s --- %u\n", (void *)graph->irg, get_entity_name(get_irg_entity(graph->irg)),
- root_env.num_of_dags);
-
- for (id = 0, entry = root_env.list_of_dags; entry; entry = entry->next) {
- if (entry->is_dead)
- continue;
- entry->id = id++;
-
- printf("number of roots %u number of nodes %u inner %u tree %u %ld\n",
- entry->num_roots,
- entry->num_nodes,
- entry->num_inner_nodes,
- (unsigned)entry->is_tree,
- get_irn_node_nr(entry->root));
- }
-
- /* dump for test */
- mark_options = root_env.options;
- set_dump_node_vcgattr_hook(stat_dag_mark_hook);
- dump_ir_graph(graph->irg, "dag");
- set_dump_node_vcgattr_hook(NULL);
-
- assert(id == root_env.num_of_dags);
-
- obstack_free(&root_env.obst, NULL);
-}
diff --git a/ir/stat/dags.h b/ir/stat/dags.h
deleted file mode 100644
index 12e478d..0000000
--- a/ir/stat/dags.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * This file is part of libFirm.
- * Copyright (C) 2012 University of Karlsruhe.
- */
-
-/**
- * @file
- * @brief Statistics for Firm. DAG's in graphs.
- * @author Michael Beck
- */
-#ifndef FIRM_STAT_DAGS_H
-#define FIRM_STAT_DAGS_H
-
-#include "firmstat_t.h"
-/*
- * count the DAG's size of a graph
- */
-void count_dags_in_graph(graph_entry_t *global, graph_entry_t *graph);
-
-#endif
diff --git a/ir/stat/distrib.c b/ir/stat/distrib.c
deleted file mode 100644
index ff7664d..0000000
--- a/ir/stat/distrib.c
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * This file is part of libFirm.
- * Copyright (C) 2012 University of Karlsruhe.
- */
-
-/**
- * @file
- * @brief Statistics for Firm. Distribution tables.
- * @author Michael Beck
- */
-#include <limits.h>
-
-#include "hashptr.h"
-#include "util.h"
-#include "xmalloc.h"
-#include "firmstat_t.h"
-
-/**
- * calculates a hash value for an address
- */
-static unsigned addr_hash(const void *object)
-{
- return hash_ptr(object);
-}
-
-/**
- * calculates a hash value for an integer
- */
-static unsigned int_hash(const void *object)
-{
- return (unsigned)PTR_TO_INT(object);
-}
-
-/**
- * compare function for integer distribution tables
- */
-static int int_cmp_fun(const void *elt, const void *key)
-{
- const distrib_entry_t *p1 = (const distrib_entry_t*)elt;
- const distrib_entry_t *p2 = (const distrib_entry_t*)key;
-
- if (p1->object == p2->object)
- return 0;
- return p1->object < p2->object ? -1 : 1;
-}
-
-/*
- * create a new distribution table
- */
-distrib_tbl_t *stat_new_distrib_tbl(pset_cmp_fun cmp_func, distrib_hash_fun hash_func)
-{
- distrib_tbl_t *res = XMALLOC(distrib_tbl_t);
-
- obstack_init(&res->cnts);
-
- /* create the hash-table */
- res->hash_map = new_pset(cmp_func, 8);
- res->hash_func = hash_func ? hash_func : addr_hash;
- res->int_dist = 0;
-
- return res;
-}
-
-/*
- * create a new distribution table for an integer distribution
- */
-distrib_tbl_t *stat_new_int_distrib_tbl(void)
-{
- distrib_tbl_t *res = stat_new_distrib_tbl(int_cmp_fun, int_hash);
-
- if (res)
- res->int_dist = 1;
-
- return res;
-}
-
-/*
- * destroy a distribution table
- */
-void stat_delete_distrib_tbl(distrib_tbl_t *tbl)
-{
- if (tbl) {
- /* free all entries */
- obstack_free(&tbl->cnts, NULL);
-
- /* delete the hash table */
- del_pset(tbl->hash_map);
- }
-}
-
-/**
- * Returns the associates distrib_entry_t for an object
- */
-static distrib_entry_t *distrib_get_entry(distrib_tbl_t *tbl, const void *object)
-{
- distrib_entry_t key;
- distrib_entry_t *elem;
-
- key.object = object;
-
- elem = (distrib_entry_t*)pset_find(tbl->hash_map, &key, tbl->hash_func(object));
- if (elem)
- return elem;
-
- elem = OALLOC(&tbl->cnts, distrib_entry_t);
-
- /* clear counter */
- cnt_clr(&elem->cnt);
-
- elem->object = object;
-
- return (distrib_entry_t*)pset_insert(tbl->hash_map, elem, tbl->hash_func(object));
-}
-
-/*
- * increases object count by one
- */
-void stat_inc_distrib_tbl(distrib_tbl_t *tbl, const void *object)
-{
- distrib_entry_t *elem = distrib_get_entry(tbl, object);
-
- cnt_inc(&elem->cnt);
-}
-
-/*
- * increases key count by one
- */
-void stat_inc_int_distrib_tbl(distrib_tbl_t *tbl, int key)
-{
- stat_inc_distrib_tbl(tbl, INT_TO_PTR(key));
-}
-
-/**
- * iterates over all entries in a distribution table
- */
-void stat_iterate_distrib_tbl(const distrib_tbl_t *tbl, eval_distrib_entry_fun eval, void *env)
-{
- foreach_pset(tbl->hash_map, distrib_entry_t, entry)
- eval(entry, env);
-}
diff --git a/ir/stat/firmstat.c b/ir/stat/firmstat.c
deleted file mode 100644
index 2fbdbc4..0000000
--- a/ir/stat/firmstat.c
+++ /dev/null
@@ -1,1792 +0,0 @@
-/*
- * This file is part of libFirm.
- * Copyright (C) 2012 University of Karlsruhe.
- */
-
-/**
- * @file
- * @brief Statistics for Firm.
- * @author Michael Beck
- */
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "dags.h"
-#include "firmstat_t.h"
-#include "hashptr.h"
-#include "ircons.h"
-#include "irdump.h"
-#include "irhooks.h"
-#include "irouts.h"
-#include "irtools.h"
-#include "lc_opts.h"
-#include "lc_opts_enum.h"
-#include "pattern.h"
-#include "stat_dmp.h"
-#include "util.h"
-#include "xmalloc.h"
-
-/*
- * need this to be static:
- * Special pseudo Opcodes that we need to count some interesting cases
- */
-
-static unsigned stat_options;
-
-/* ---------------------------------------------------------------------------------- */
-
-/** Marks the begin of a statistic (hook) function. */
-#define STAT_ENTER ++status->recursive
-
-/** Marks the end of a statistic (hook) functions. */
-#define STAT_LEAVE --status->recursive
-
-/** Allows to enter a statistic function only when we are not already in a hook. */
-#define STAT_ENTER_SINGLE do { if (status->recursive > 0) return; ++status->recursive; } while (0)
-
-/**
- * global status
- */
-static stat_info_t *status = NULL;
-
-/**
- * Compare two elements of the opcode hash.
- */
-static int opcode_cmp(const void *elt, const void *key)
-{
- const node_entry_t *e1 = (const node_entry_t*)elt;
- const node_entry_t *e2 = (const node_entry_t*)key;
-
- return e1->op_id != e2->op_id;
-}
-
-/**
- * Compare two elements of the graph hash.
- */
-static int graph_cmp(const void *elt, const void *key)
-{
- const graph_entry_t *e1 = (const graph_entry_t*)elt;
- const graph_entry_t *e2 = (const graph_entry_t*)key;
-
- return e1->irg != e2->irg;
-}
-
-/**
- * Compare two elements of the optimization hash.
- */
-static int opt_cmp(const void *elt, const void *key)
-{
- const opt_entry_t *e1 = (const opt_entry_t*)elt;
- const opt_entry_t *e2 = (const opt_entry_t*)key;
-
- return e1->op_id != e2->op_id;
-}
-
-/**
- * Compare two elements of the block hash.
- */
-static int block_cmp(const void *elt, const void *key)
-{
- const block_entry_t *e1 = (const block_entry_t*)elt;
- const block_entry_t *e2 = (const block_entry_t*)key;
-
- /* it's enough to compare the block number */
- return e1->block_nr != e2->block_nr;
-}
-
-/**
- * Compare two elements of the be_block hash.
- */
-static int be_block_cmp(const void *elt, const void *key)
-{
- const be_block_entry_t *e1 = (const be_block_entry_t*)elt;
- const be_block_entry_t *e2 = (const be_block_entry_t*)key;
-
- return e1->block_nr != e2->block_nr;
-}
-
-/**
- * Compare two elements of reg pressure hash.
- */
-static int reg_pressure_cmp(const void *elt, const void *key)
-{
- const reg_pressure_entry_t *e1 = (const reg_pressure_entry_t*)elt;
- const reg_pressure_entry_t *e2 = (const reg_pressure_entry_t*)key;
-
- return e1->class_name != e2->class_name;
-}
-
-/**
- * Compare two elements of the ir_op hash.
- */
-static int opcode_cmp_2(const void *elt, const void *key)
-{
- const ir_op *e1 = (const ir_op*)elt;
- const ir_op *e2 = (const ir_op*)key;
-
- return e1->code != e2->code;
-}
-
-/**
- * Compare two elements of the address_mark set.
- */
-static int address_mark_cmp(const void *elt, const void *key, size_t size)
-{
- (void)size;
- const address_mark_entry_t *e1 = (const address_mark_entry_t*)elt;
- const address_mark_entry_t *e2 = (const address_mark_entry_t*)key;
-
- /* compare only the nodes, the rest is used as data container */
- return e1->node != e2->node;
-}
-
-/**
- * Clear all counter in a node_entry_t.
- */
-static void opcode_clear_entry(node_entry_t *elem)
-{
- cnt_clr(&elem->cnt_alive);
- cnt_clr(&elem->new_node);
- cnt_clr(&elem->into_Id);
- cnt_clr(&elem->normalized);
-}
-
-/**
- * Returns the associates node_entry_t for an ir_op (and allocates
- * one if not yet available).
- *
- * @param op_id the IR operation
- * @param hmap a hash map containing ir_op* -> node_entry_t*
- */
-static node_entry_t *opcode_get_entry(op_id_t const op_id, hmap_node_entry_t *const hmap)
-{
- node_entry_t key;
- key.op_id = op_id;
-
- node_entry_t *elem = (node_entry_t*)pset_find(hmap, &key, hash_ptr(op_id));
- if (elem)
- return elem;
-
- elem = OALLOCZ(&status->cnts, node_entry_t);
-
- /* clear counter */
- opcode_clear_entry(elem);
-
- elem->op_id = op_id;
-
- return (node_entry_t*)pset_insert(hmap, elem, hash_ptr(op_id));
-}
-
-/**
- * Returns the associates ir_op for an opcode
- *
- * @param code the IR opcode
- * @param hmap the hash map containing opcode -> ir_op*
- */
-static ir_op *opcode_find_entry(ir_opcode code, hmap_ir_op *hmap)
-{
- ir_op key;
- key.code = code;
- return (ir_op*)pset_find(hmap, &key, code);
-}
-
-/**
- * Clears all counter in a graph_entry_t.
- *
- * @param elem the graph entry
- * @param all if non-zero, clears all counters, else leave accumulated ones
- */
-static void graph_clear_entry(graph_entry_t *elem, int all)
-{
- /* clear accumulated / non-accumulated counter */
- for (int i = all ? 0 : _gcnt_non_acc; i < _gcnt_last; ++i) {
- cnt_clr(&elem->cnt[i]);
- }
-
- if (elem->block_hash) {
- del_pset(elem->block_hash);
- elem->block_hash = NULL;
- }
-
- obstack_free(&elem->recalc_cnts, NULL);
- obstack_init(&elem->recalc_cnts);
-}
-
-/**
- * Returns the associated graph_entry_t for an IR graph.
- *
- * @param irg the IR graph, NULL for the global counter
- * @param hmap the hash map containing ir_graph* -> graph_entry_t*
- */
-static graph_entry_t *graph_get_entry(ir_graph *irg, hmap_graph_entry_t *hmap)
-{
- graph_entry_t key;
- key.irg = irg;
-
- graph_entry_t *elem = (graph_entry_t*)pset_find(hmap, &key, hash_ptr(irg));
- 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 = OALLOCZ(&status->cnts, graph_entry_t);
- obstack_init(&elem->recalc_cnts);
-
- /* clear counter */
- 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;
-
- /* these hash tables are created on demand */
- elem->block_hash = NULL;
-
- for (size_t i = 0; i != ARRAY_SIZE(elem->opt_hash); ++i)
- elem->opt_hash[i] = new_pset(opt_cmp, 4);
-
- return (graph_entry_t*)pset_insert(hmap, elem, hash_ptr(irg));
-}
-
-static graph_entry_t *get_graph_entry(ir_node *const node, hmap_graph_entry_t *const hmap)
-{
- ir_graph *const irg = get_irn_irg(node);
- return graph_get_entry(irg, hmap);
-}
-
-static node_entry_t *get_node_entry(ir_node *const node, op_id_t const op_id)
-{
- ir_graph *const irg = node ? get_irn_irg(node) : NULL;
- graph_entry_t *const graph = graph_get_entry(irg, status->irg_hash);
- return opcode_get_entry(op_id, graph->opcode_hash);
-}
-
-/**
- * Clear all counter in an opt_entry_t.
- */
-static void opt_clear_entry(opt_entry_t *elem)
-{
- cnt_clr(&elem->count);
-}
-
-/**
- * Returns the associated opt_entry_t for an IR operation.
- *
- * @param op_id the IR operation
- * @param hmap the hash map containing ir_op* -> opt_entry_t*
- */
-static opt_entry_t *opt_get_entry(op_id_t const op_id, hmap_opt_entry_t *const hmap)
-{
- opt_entry_t key;
- key.op_id = op_id;
-
- opt_entry_t *elem = (opt_entry_t*)pset_find(hmap, &key, hash_ptr(op_id));
- if (elem)
- return elem;
-
- elem = OALLOCZ(&status->cnts, opt_entry_t);
-
- /* clear new counter */
- opt_clear_entry(elem);
-
- elem->op_id = op_id;
-
- return (opt_entry_t*)pset_insert(hmap, elem, hash_ptr(op_id));
-}
-
-/**
- * clears all counter in a block_entry_t
- */
-static void block_clear_entry(block_entry_t *elem)
-{
- for (int i = 0; i < _bcnt_last; ++i)
- cnt_clr(&elem->cnt[i]);
-}
-
-/**
- * Returns the associated block_entry_t for an block.
- *
- * @param block_nr an IR block number
- * @param hmap a hash map containing long -> block_entry_t
- */
-static block_entry_t *block_get_entry(struct obstack *obst, long block_nr, hmap_block_entry_t *hmap)
-{
- block_entry_t key;
- key.block_nr = block_nr;
-
- block_entry_t *elem = (block_entry_t*)pset_find(hmap, &key, block_nr);
- if (elem)
- return elem;
-
- elem = OALLOCZ(obst, block_entry_t);
-
- /* clear new counter */
- block_clear_entry(elem);
-
- elem->block_nr = block_nr;
-
- return (block_entry_t*)pset_insert(hmap, elem, block_nr);
-}
-
-/**
- * Clear all sets in be_block_entry_t.
- */
-static void be_block_clear_entry(be_block_entry_t *elem)
-{
- if (elem->reg_pressure)
- del_pset(elem->reg_pressure);
-
- elem->reg_pressure = new_pset(reg_pressure_cmp, 5);
-}
-
-/**
- * Returns the associated be_block_entry_t for an block.
- *
- * @param block a block
- * @param hmap a hash map containing long -> be_block_entry_t
- */
-static be_block_entry_t *be_block_get_entry(ir_node *const block, hmap_be_block_entry_t *const hmap)
-{
- long const block_nr = get_irn_node_nr(block);
- be_block_entry_t key;
- key.block_nr = block_nr;
-
- be_block_entry_t *elem = (be_block_entry_t*)pset_find(hmap, &key, block_nr);
- if (elem)
- return elem;
-
- elem = OALLOCZ(&status->be_data, be_block_entry_t);
-
- /* clear new counter */
- be_block_clear_entry(elem);
-
- elem->block_nr = block_nr;
-
- return (be_block_entry_t*)pset_insert(hmap, elem, block_nr);
-}
-
-/**
- * Clear optimizations counter,
- */
-static void clear_optimization_counter(void)
-{
- for (int i = 0; i < FS_OPT_MAX; ++i)
- cnt_clr(&status->num_opts[i]);
-}
-
-/**
- * Returns the ir_op for an IR-node,
- * handles special cases and return pseudo op codes.
- *
- * @param none an IR node
- */
-static op_id_t stat_get_irn_op(ir_node *node)
-{
- ir_op *const op = get_irn_op(node);
- op_id_t op_id = get_op_name(op);
- switch (op->code) {
- case iro_Phi:
- if (get_irn_arity(node) == 0) {
- /* special case, a Phi0 node, count on extra counter */
- op_id = status->op_Phi0 ? status->op_Phi0 : op_id;
- } else if (get_irn_mode(node) == mode_M) {
- /* special case, a Memory Phi node, count on extra counter */
- op_id = status->op_PhiM ? status->op_PhiM : op_id;
- }
- break;
- case iro_Proj:
- if (get_irn_mode(node) == mode_M) {
- /* special case, a Memory Proj node, count on extra counter */
- op_id = status->op_ProjM ? status->op_ProjM : op_id;
- }
- break;
- case iro_Mul:
- if (is_Const(get_Mul_left(node)) || is_Const(get_Mul_right(node))) {
- /* special case, a Multiply by a const, count on extra counter */
- op_id = status->op_MulC ? status->op_MulC : op_id;
- }
- break;
- case iro_Div:
- if (is_Const(get_Div_right(node))) {
- /* special case, a division by a const, count on extra counter */
- op_id = status->op_DivC ? status->op_DivC : op_id;
- }
- break;
- case iro_Mod:
- if (is_Const(get_Mod_right(node))) {
- /* special case, a module by a const, count on extra counter */
- op_id = status->op_ModC ? status->op_ModC : op_id;
- }
- break;
- case iro_Sel:
- if (is_Sel(get_Sel_ptr(node))) {
- /* special case, a Sel of a Sel, count on extra counter */
- op_id = status->op_SelSel ? status->op_SelSel : op_id;
- if (is_Sel(get_Sel_ptr(get_Sel_ptr(node)))) {
- /* special case, a Sel of a Sel of a Sel, count on extra counter */
- op_id = status->op_SelSelSel ? status->op_SelSelSel : op_id;
- }
- }
- break;
- default:
- break;
- }
-
- return op_id;
-}
-
-/**
- * update the block counter
- */
-static void undate_block_info(ir_node *node, graph_entry_t *graph)
-{
- /* check for block */
- if (is_Block(node)) {
- block_entry_t *const b_entry = block_get_entry(&graph->recalc_cnts, get_irn_node_nr(node), graph->block_hash);
- /* mark start end block to allow to filter them out */
- if (node == get_irg_start_block(graph->irg))
- b_entry->is_start = 1;
- else if (node == get_irg_end_block(graph->irg))
- b_entry->is_end = 1;
-
- /* count all incoming edges */
- foreach_irn_in(node, i, pred) {
- ir_node *other_block = get_nodes_block(pred);
- block_entry_t *b_entry_other = block_get_entry(&graph->recalc_cnts, get_irn_node_nr(other_block), graph->block_hash);
-
- cnt_inc(&b_entry->cnt[bcnt_in_edges]); /* an edge coming from another block */
- cnt_inc(&b_entry_other->cnt[bcnt_out_edges]);
- }
- return;
- }
-
- ir_node *const block = get_nodes_block(node);
- block_entry_t *const b_entry = block_get_entry(&graph->recalc_cnts, get_irn_node_nr(block), graph->block_hash);
-
- if (is_Phi(node) && get_irn_mode(node) != mode_M) {
- /* count data Phi per block */
- cnt_inc(&b_entry->cnt[bcnt_phi_data]);
- }
-
- /* we have a new node in our block */
- cnt_inc(&b_entry->cnt[bcnt_nodes]);
-
- /* don't count keep-alive edges */
- if (is_End(node))
- return;
-
- foreach_irn_in(node, i, pred) {
- ir_node *const other_block = get_nodes_block(pred);
- if (other_block == block) {
- cnt_inc(&b_entry->cnt[bcnt_edges]); /* a in block edge */
- } else {
- block_entry_t *b_entry_other = block_get_entry(&graph->recalc_cnts, get_irn_node_nr(other_block), graph->block_hash);
-
- cnt_inc(&b_entry->cnt[bcnt_in_edges]); /* an edge coming from another block */
- cnt_inc(&b_entry_other->cnt[bcnt_out_edges]);
- }
- }
-}
-
-/**
- * Find the base address of a Sel node.
- *
- * @param sel the node
- *
- * @return the base address.
- */
-static ir_node *find_base_adr(ir_node *sel)
-{
- ir_node *ptr = sel;
- do {
- ptr = get_Sel_ptr(ptr);
- } while (is_Sel(ptr));
- return ptr;
-}
-
-/**
- * Calculates how many arguments of the call are const, updates
- * param distribution.
- */
-static void analyse_params_of_Call(graph_entry_t *graph, ir_node *call)
-{
- int num_const_args = 0;
- int num_local_adr = 0;
- int n = get_Call_n_params(call);
- for (int i = 0; i < n; ++i) {
- ir_node *param = get_Call_param(call, i);
- if (is_irn_constlike(param)) {
- ++num_const_args;
- } else if (is_Sel(param)) {
- ir_node *const base = find_base_adr(param);
- if (base == get_irg_frame(graph->irg))
- ++num_local_adr;
- }
- }
-
- if (num_const_args > 0)
- cnt_inc(&graph->cnt[gcnt_call_with_cnst_arg]);
- if (num_const_args == n)
- cnt_inc(&graph->cnt[gcnt_call_with_all_cnst_arg]);
- if (num_local_adr > 0)
- cnt_inc(&graph->cnt[gcnt_call_with_local_adr]);
-
- stat_inc_int_distrib_tbl(status->dist_param_cnt, n);
-}
-
-/**
- * Update info on calls.
- *
- * @param call The call
- * @param graph The graph entry containing the call
- */
-static void stat_update_call(ir_node *call, graph_entry_t *graph)
-{
- /* If the block is bad, the whole subgraph will collapse later
- * so do not count this call.
- * This happens in dead code. */
- ir_node *block = get_nodes_block(call);
- if (is_Bad(block))
- return;
-
- cnt_inc(&graph->cnt[gcnt_all_calls]);
-
- /* found a call, this function is not a leaf */
- graph->is_leaf = 0;
-
- ir_graph *callee = NULL;
- ir_node *const ptr = get_Call_ptr(call);
- if (is_Address(ptr)) {
- /* ok, we seem to know the entity */
- ir_entity *const ent = get_Address_entity(ptr);
- callee = get_entity_irg(ent);
-
- /* it is recursive, if it calls at least once */
- if (callee == graph->irg)
- graph->is_recursive = 1;
- if (callee == NULL)
- cnt_inc(&graph->cnt[gcnt_external_calls]);
- } else {
- /* indirect call, could not predict */
- cnt_inc(&graph->cnt[gcnt_indirect_calls]);
-
- /* NOT a leaf call */
- graph->is_leaf_call = LCS_NON_LEAF_CALL;
- }
-
- /* check, if it's a chain-call: Then, the call-block
- * must dominate the end block. */
- {
- int const depth = get_Block_dom_depth(block);
- ir_node *curr = get_irg_end_block(graph->irg);
- for (; curr != block && get_Block_dom_depth(curr) > depth;) {
- curr = get_Block_idom(curr);
- if (!curr || !is_Block(curr))
- break;
- }
-
- if (curr != block)
- graph->is_chain_call = 0;
- }
-
- /* check, if the callee is a leaf */
- if (callee) {
- graph_entry_t *called = graph_get_entry(callee, status->irg_hash);
- if (called->is_analyzed) {
- if (!called->is_leaf)
- graph->is_leaf_call = LCS_NON_LEAF_CALL;
- }
- }
-
- analyse_params_of_Call(graph, call);
-}
-
-/**
- * Update info on calls for graphs on the wait queue.
- */
-static void stat_update_call_2(ir_node *call, graph_entry_t *graph)
-{
- /* If the block is bad, the whole subgraph will collapse later
- * so do not count this call.
- * This happens in dead code. */
- ir_node *const block = get_nodes_block(call);
- if (is_Bad(block))
- return;
-
- ir_graph *callee = NULL;
- ir_node *const ptr = get_Call_ptr(call);
- if (is_Address(ptr)) {
- /* ok, we seem to know the entity */
- ir_entity *const ent = get_Address_entity(ptr);
- callee = get_entity_irg(ent);
- }
-
- /* check, if the callee is a leaf */
- if (callee) {
- graph_entry_t *called = graph_get_entry(callee, status->irg_hash);
-
- assert(called->is_analyzed);
-
- if (!called->is_leaf)
- graph->is_leaf_call = LCS_NON_LEAF_CALL;
- } else
- graph->is_leaf_call = LCS_NON_LEAF_CALL;
-}
-
-/**
- * Update info on Load/Store address statistics.
- */
-static void stat_update_address(ir_node *node, graph_entry_t *graph)
-{
- unsigned const opc = get_irn_opcode(node);
- switch (opc) {
- case iro_Address:
- /* a global address */
- cnt_inc(&graph->cnt[gcnt_global_adr]);
- break;
-
- case iro_Sel: {
- ir_node *const base = find_base_adr(node);
- ir_graph *const irg = graph->irg;
- if (base == get_irg_frame(irg)) {
- /* a local Variable. */
- cnt_inc(&graph->cnt[gcnt_local_adr]);
- } else {
- /* Pointer access */
- if (is_Proj(base) && skip_Proj(get_Proj_pred(base)) == get_irg_start(irg)) {
- /* pointer access through parameter, check for THIS */
- ir_entity *const ent = get_irg_entity(irg);
- if (ent) {
- ir_type *const ent_tp = get_entity_type(ent);
- if (get_method_calling_convention(ent_tp) & cc_this_call) {
- if (get_Proj_num(base) == 0) {
- /* THIS pointer */
- cnt_inc(&graph->cnt[gcnt_this_adr]);
- goto end_parameter;
- }
- }
- }
- /* other parameter */
- cnt_inc(&graph->cnt[gcnt_param_adr]);
-end_parameter: ;
- } else {
- /* unknown Pointer access */
- cnt_inc(&graph->cnt[gcnt_other_adr]);
- }
- }
- }
-
- default:
- break;
- }
-}
-
-/**
- * Walker for reachable nodes count.
- */
-static void update_node_stat(ir_node *node, void *env)
-{
- graph_entry_t *const graph = (graph_entry_t*)env;
- op_id_t const op = stat_get_irn_op(node);
- node_entry_t *const entry = opcode_get_entry(op, graph->opcode_hash);
-
- cnt_inc(&entry->cnt_alive);
- int const arity = get_irn_arity(node);
- cnt_add_i(&graph->cnt[gcnt_edges], arity);
-
- /* count block edges */
- undate_block_info(node, graph);
-
- /* handle statistics for special node types */
-
- switch (get_irn_opcode(node)) {
- case iro_Call:
- /* check for properties that depends on calls like recursion/leaf/indirect call */
- stat_update_call(node, graph);
- break;
- case iro_Load:
- /* check address properties */
- stat_update_address(get_Load_ptr(node), graph);
- break;
- case iro_Store:
- /* check address properties */
- stat_update_address(get_Store_ptr(node), graph);
- break;
- case iro_Phi:
- /* check for non-strict Phi nodes */
- foreach_irn_in_r(node, i, pred) {
- if (is_Unknown(pred)) {
- /* found an Unknown predecessor, graph is not strict */
- graph->is_strict = 0;
- break;
- }
- }
- default:
- break;
- }
-
- /* we want to count the constant IN nodes, not the CSE'ed constant's itself */
- if (status->stat_options & FIRMSTAT_COUNT_CONSTS) {
- foreach_irn_in_r(node, i, pred) {
- if (is_Const(pred)) {
- /* check properties of constants */
- stat_update_const(status, pred, graph);
- }
- }
- }
-}
-
-/**
- * Walker for reachable nodes count for graphs on the wait_q.
- */
-static void update_node_stat_2(ir_node *node, void *env)
-{
- graph_entry_t *const graph = (graph_entry_t*)env;
-
- /* check for properties that depends on calls like recursion/leaf/indirect call */
- if (is_Call(node))
- stat_update_call_2(node, graph);
-}
-
-/**
- * Get the current address mark.
- */
-static unsigned get_adr_mark(graph_entry_t *const graph, ir_node const *const node)
-{
- address_mark_entry_t const val = { node, 0 };
- address_mark_entry_t *const value = set_find(address_mark_entry_t, graph->address_mark, &val, sizeof(val), hash_ptr(node));
- return value ? value->mark : 0;
-}
-
-/**
- * Set the current address mark.
- */
-static void set_adr_mark(graph_entry_t *graph, ir_node *node, unsigned val)
-{
- address_mark_entry_t const value = { node, val };
- (void)set_insert(address_mark_entry_t, graph->address_mark, &value, sizeof(value), hash_ptr(node));
-}
-
-#undef DUMP_ADR_MODE
-
-#ifdef DUMP_ADR_MODE
-/**
- * a vcg attribute hook: Color a node with a different color if
- * it's identified as a part of an address expression or at least referenced
- * by an address expression.
- */
-static int stat_adr_mark_hook(FILE *const F, ir_node const *const node, ir_node const *const local)
-{
- ir_node const *const n = local ? local : node;
- graph_entry_t *const graph = get_graph_entry(n, status->irg_hash);
- unsigned const mark = get_adr_mark(graph, n);
-
- if (mark & MARK_ADDRESS_CALC)
- fprintf(F, "color: purple");
- else if ((mark & (MARK_REF_ADR | MARK_REF_NON_ADR)) == MARK_REF_ADR)
- fprintf(F, "color: pink");
- else if ((mark & (MARK_REF_ADR | MARK_REF_NON_ADR)) == (MARK_REF_ADR|MARK_REF_NON_ADR))
- fprintf(F, "color: lightblue");
- else
- return 0;
-
- /* I know the color! */
- return 1;
-}
-#endif
-
-/**
- * Return the "operational" mode of a Firm node.
- */
-static ir_mode *get_irn_op_mode(ir_node *node)
-{
- switch (get_irn_opcode(node)) {
- case iro_Load: return get_Load_mode(node);
- case iro_Store: return get_irn_mode(get_Store_value(node));
- case iro_Div: return get_irn_mode(get_Div_left(node));
- case iro_Mod: return get_irn_mode(get_Mod_left(node));
- case iro_Cmp: /* Cmp is no address calculation, or is it? */
- default: return get_irn_mode(node);
- }
-}
-
-/**
- * Post-walker that marks every node that is an address calculation.
- *
- * Users of a node must be visited first. We ensure this by
- * calling it in the post of an outs walk. This should work even in cycles,
- * while the normal pre-walk will not.
- */
-static void mark_address_calc(ir_node *node, void *env)
-{
- graph_entry_t *const graph = (graph_entry_t*)env;
-
- ir_mode *const mode = get_irn_op_mode(node);
- if (!mode_is_data(mode))
- return;
-
- unsigned mark_preds = MARK_REF_NON_ADR;
- if (mode_is_reference(mode)) {
- /* a reference is calculated here, we are sure */
- set_adr_mark(graph, node, MARK_ADDRESS_CALC);
-
- mark_preds = MARK_REF_ADR;
- } else {
- unsigned mark = get_adr_mark(graph, node);
-
- if ((mark & (MARK_REF_ADR | MARK_REF_NON_ADR)) == MARK_REF_ADR) {
- /* this node has no reference mode, but is only
- * referenced by address calculations */
- mark_preds = MARK_REF_ADR;
- }
- }
-
- /* mark all predecessors */
- foreach_irn_in(node, i, pred) {
- if (mode_is_data(get_irn_op_mode(pred)))
- set_adr_mark(graph, pred, get_adr_mark(graph, pred) | mark_preds);
- }
-}
-
-/**
- * Post-walker that marks every node that is an address calculation.
- *
- * Users of a node must be visited first. We ensure this by
- * calling it in the post of an outs walk. This should work even in cycles,
- * while the normal pre-walk will not.
- */
-static void count_adr_ops(ir_node *node, void *env)
-{
- graph_entry_t *const graph = (graph_entry_t*)env;
-
- unsigned const mark = get_adr_mark(graph, node);
- if (mark & MARK_ADDRESS_CALC)
- cnt_inc(&graph->cnt[gcnt_pure_adr_ops]);
- else if ((mark & (MARK_REF_ADR | MARK_REF_NON_ADR)) == MARK_REF_ADR)
- cnt_inc(&graph->cnt[gcnt_pure_adr_ops]);
- else if ((mark & (MARK_REF_ADR | MARK_REF_NON_ADR)) == (MARK_REF_ADR|MARK_REF_NON_ADR))
- cnt_inc(&graph->cnt[gcnt_all_adr_ops]);
-}
-
-/**
- * Called for every graph when the graph is either deleted or stat_dump_snapshot()
- * is called, must recalculate all statistic info.
- *
- * @param global The global entry
- * @param graph The current entry
- */
-static void update_graph_stat(graph_entry_t *global, graph_entry_t *graph)
-{
- /* clear first the alive counter in the graph */
- foreach_pset(graph->opcode_hash, node_entry_t, entry) {
- cnt_clr(&entry->cnt_alive);
- }
-
- /* set pessimistic values */
- graph->is_leaf = 1;
- graph->is_leaf_call = LCS_UNKNOWN;
- graph->is_recursive = 0;
- graph->is_chain_call = 1;
- graph->is_strict = 1;
-
- /* create new block counter */
- graph->block_hash = new_pset(block_cmp, 5);
-
- /* we need dominator info */
- if (graph->irg != get_const_code_irg()) {
- assure_irg_properties(graph->irg, IR_GRAPH_PROPERTY_CONSISTENT_DOMINANCE);
- }
-
- /* count the nodes in the graph */
- irg_walk_graph(graph->irg, update_node_stat, NULL, graph);
-
- /* recursive functions are never chain calls, leafs don't have calls */
- if (graph->is_recursive || graph->is_leaf)
- graph->is_chain_call = 0;
-
- /* assume we walk every graph only ONCE, we could sum here the global count */
- foreach_pset(graph->opcode_hash, node_entry_t, entry) {
- node_entry_t *g_entry = opcode_get_entry(entry->op_id, global->opcode_hash);
-
- /* update the node counter */
- cnt_add(&g_entry->cnt_alive, &entry->cnt_alive);
- }
-
- /* count the number of address calculation */
- if (graph->irg != get_const_code_irg()) {
- assure_irg_outs(graph->irg);
-
- /* Must be done an the outs graph */
- irg_out_walk(get_irg_start(graph->irg), NULL, mark_address_calc, graph);
-
-#ifdef DUMP_ADR_MODE
- /* register the vcg hook and dump the graph for test */
- set_dump_node_vcgattr_hook(stat_adr_mark_hook);
- dump_ir_graph(graph->irg, "-adr");
- set_dump_node_vcgattr_hook(NULL);
-#endif
-
- irg_walk_graph(graph->irg, NULL, count_adr_ops, graph);
- }
-
- /* count the DAG's */
- if (status->stat_options & FIRMSTAT_COUNT_DAG)
- count_dags_in_graph(global, graph);
-
- /* calculate the patterns of this graph */
- stat_calc_pattern_history(graph->irg);
-
- /* leaf function did not call others */
- if (graph->is_leaf) {
- graph->is_leaf_call = LCS_NON_LEAF_CALL;
- } else if (graph->is_leaf_call == LCS_UNKNOWN) {
- /* we still don't know if this graph calls leaf-functions, so enqueue */
- pdeq_putl(status->wait_q, graph);
- }
-
- /* we have analyzed this graph */
- graph->is_analyzed = 1;
-
- /* accumulate all counter's */
- for (int i = 0; i < _gcnt_last; ++i)
- cnt_add(&global->cnt[i], &graph->cnt[i]);
-}
-
-/**
- * Called for every graph that was on the wait_q in stat_dump_snapshot()
- * must finish all statistic info calculations.
- *
- * @param graph The current entry
- */
-static void update_graph_stat_2(graph_entry_t *graph)
-{
- if (graph->is_deleted) {
- /* deleted, ignore */
- return;
- }
-
- if (graph->irg) {
- /* count the nodes in the graph */
- irg_walk_graph(graph->irg, update_node_stat_2, NULL, graph);
-
- if (graph->is_leaf_call == LCS_UNKNOWN)
- graph->is_leaf_call = LCS_LEAF_CALL;
- }
-}
-
-/**
- * Register a dumper.
- */
-static void stat_register_dumper(const dumper_t *dumper)
-{
- dumper_t *p = XMALLOC(dumper_t);
- *p = *dumper;
-
- p->next = status->dumper;
- p->status = status;
- status->dumper = p;
-
- /* FIXME: memory leak */
-}
-
-/**
- * Dumps the statistics of an IR graph.
- */
-static void stat_dump_graph(graph_entry_t *entry)
-{
- for (dumper_t *dumper = status->dumper; dumper; dumper = dumper->next) {
- if (dumper->dump_graph)
- dumper->dump_graph(dumper, entry);
- }
-}
-
-/**
- * Dumps a constant table.
- */
-static void stat_dump_consts(const constant_info_t *tbl)
-{
- for (dumper_t *dumper = status->dumper; dumper; dumper = dumper->next) {
- if (dumper->dump_const_tbl)
- dumper->dump_const_tbl(dumper, tbl);
- }
-}
-
-/**
- * Dumps the parameter distribution
- */
-static void stat_dump_param_tbl(const distrib_tbl_t *tbl, graph_entry_t *global)
-{
- for (dumper_t *dumper = status->dumper; dumper; dumper = dumper->next) {
- if (dumper->dump_param_tbl)
- dumper->dump_param_tbl(dumper, tbl, global);
- }
-}
-
-/**
- * Dumps the optimization counter
- */
-static void stat_dump_opt_cnt(const counter_t *tbl, unsigned len)
-{
- for (dumper_t *dumper = status->dumper; dumper; dumper = dumper->next) {
- if (dumper->dump_opt_cnt)
- dumper->dump_opt_cnt(dumper, tbl, len);
- }
-}
-
-/**
- * Initialize the dumper.
- */
-static void stat_dump_init(const char *name)
-{
- for (dumper_t *dumper = status->dumper; dumper; dumper = dumper->next) {
- if (dumper->init)
- dumper->init(dumper, name);
- }
-}
-
-/**
- * Finish the dumper.
- */
-static void stat_dump_finish(void)
-{
- for (dumper_t *dumper = status->dumper; dumper; dumper = dumper->next) {
- if (dumper->finish)
- dumper->finish(dumper);
- }
-}
-
-/* ---------------------------------------------------------------------- */
-
-/*
- * Helper: get an ir_op from an opcode.
- */
-ir_op *stat_get_op_from_opcode(unsigned code)
-{
- return opcode_find_entry((ir_opcode)code, status->ir_op_hash);
-}
-
-/**
- * Hook: A new IR op is registered.
- *
- * @param ctx the hook context
- * @param op the new IR opcode that was created.
- */
-static void stat_new_ir_op(void *ctx, ir_op *op)
-{
- (void)ctx;
- if (!status->stat_options)
- return;
-
- STAT_ENTER;
- {
- graph_entry_t *graph = graph_get_entry(NULL, status->irg_hash);
-
- /* execute for side effect :-) */
- opcode_get_entry(get_op_name(op), graph->opcode_hash);
-
- pset_insert(status->ir_op_hash, op, op->code);
- }
- STAT_LEAVE;
-}
-
-/**
- * Hook: An IR op is freed.
- *
- * @param ctx the hook context
- * @param op the IR opcode that is freed
- */
-static void stat_free_ir_op(void *ctx, ir_op *op)
-{
- (void)ctx;
- (void)op;
- if (!status->stat_options)
- return;
-
- STAT_ENTER;
- {
- }
- STAT_LEAVE;
-}
-
-/**
- * Hook: A new node is created.
- *
- * @param ctx the hook context
- * @param node the new IR node that was created
- */
-static void stat_new_node(void *ctx, ir_node *node)
-{
- (void)ctx;
- if (!status->stat_options)
- return;
-
- /* do NOT count during dead node elimination */
- if (status->in_dead_node_elim)
- return;
-
- STAT_ENTER;
- {
- op_id_t const op_id = stat_get_irn_op(node);
- /* increase global value */
- cnt_inc(&get_node_entry(NULL, op_id)->new_node);
- /* increase local value */
- cnt_inc(&get_node_entry(node, op_id)->new_node);
- }
- STAT_LEAVE;
-}
-
-/**
- * Hook: A node is changed into a Id node
- *
- * @param ctx the hook context
- * @param node the IR node that will be turned into an ID
- */
-static void stat_turn_into_id(void *ctx, ir_node *node)
-{
- (void)ctx;
- if (!status->stat_options)
- return;
-
- STAT_ENTER;
- {
- op_id_t const op_id = stat_get_irn_op(node);
- /* increase global value */
- cnt_inc(&get_node_entry(NULL, op_id)->into_Id);
- /* increase local value */
- cnt_inc(&get_node_entry(node, op_id)->into_Id);
- }
- STAT_LEAVE;
-}
-
-/**
- * Hook: A node is normalized
- *
- * @param ctx the hook context
- * @param node the IR node that was normalized
- */
-static void stat_normalize(void *ctx, ir_node *node)
-{
- (void)ctx;
- if (!status->stat_options)
- return;
-
- STAT_ENTER;
- {
- op_id_t const op_id = stat_get_irn_op(node);
- /* increase global value */
- cnt_inc(&get_node_entry(NULL, op_id)->normalized);
- /* increase local value */
- cnt_inc(&get_node_entry(node, op_id)->normalized);
- }
- STAT_LEAVE;
-}
-
-/**
- * Hook: A new graph was created
- *
- * @param ctx the hook context
- * @param irg the new IR graph that was created
- * @param ent the entity of this graph
- */
-static void stat_new_graph(void *ctx, ir_graph *irg, ir_entity *ent)
-{
- (void)ctx;
- if (!status->stat_options)
- return;
-
- STAT_ENTER;
- {
- /* execute for side effect :-) */
- graph_entry_t *const graph = graph_get_entry(irg, status->irg_hash);
- graph->ent = ent;
- graph->is_deleted = 0;
- graph->is_leaf = 0;
- graph->is_leaf_call = 0;
- graph->is_recursive = 0;
- graph->is_chain_call = 0;
- graph->is_strict = 1;
- graph->is_analyzed = 0;
- }
- STAT_LEAVE;
-}
-
-/**
- * Hook: A graph will be deleted
- *
- * @param ctx the hook context
- * @param irg the IR graph that will be deleted
- *
- * Note that we still hold the information for this graph
- * in our hash maps, only a flag is set which prevents this
- * information from being changed, it's "frozen" from now.
- */
-static void stat_free_graph(void *ctx, ir_graph *irg)
-{
- (void)ctx;
- if (!status->stat_options)
- return;
-
- STAT_ENTER;
- {
- graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
- graph_entry_t *global = graph_get_entry(NULL, status->irg_hash);
-
- graph->is_deleted = 1;
-
- if (status->stat_options & FIRMSTAT_COUNT_DELETED) {
- /* count the nodes of the graph yet, it will be destroyed later */
- update_graph_stat(global, graph);
- }
- }
- STAT_LEAVE;
-}
-
-/**
- * Hook: A walk over a graph is initiated. Do not count walks from statistic code.
- *
- * @param ctx the hook context
- * @param irg the IR graph that will be walked
- * @param pre the pre walker
- * @param post the post walker
- */
-static void stat_irg_walk(void *ctx, ir_graph *irg, generic_func *pre, generic_func *post)
-{
- (void)ctx;
- (void)pre;
- (void)post;
- if (!status->stat_options)
- return;
-
- STAT_ENTER_SINGLE;
- {
- graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
- cnt_inc(&graph->cnt[gcnt_acc_walked]);
- }
- STAT_LEAVE;
-}
-
-/**
- * Hook: A walk over a graph in block-wise order is initiated. Do not count walks from statistic code.
- *
- * @param ctx the hook context
- * @param irg the IR graph that will be walked
- * @param pre the pre walker
- * @param post the post walker
- */
-static void stat_irg_walk_blkwise(void *ctx, ir_graph *irg, generic_func *pre, generic_func *post)
-{
- /* for now, do NOT differentiate between blockwise and normal */
- stat_irg_walk(ctx, irg, pre, post);
-}
-
-/**
- * Hook: A walk over the graph's blocks is initiated. Do not count walks from statistic code.
- *
- * @param ctx the hook context
- * @param irg the IR graph that will be walked
- * @param node the IR node
- * @param pre the pre walker
- * @param post the post walker
- */
-static void stat_irg_block_walk(void *ctx, ir_graph *irg, ir_node *node, generic_func *pre, generic_func *post)
-{
- (void)ctx;
- (void)node;
- (void)pre;
- (void)post;
- if (!status->stat_options)
- return;
-
- STAT_ENTER_SINGLE;
- {
- graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
- cnt_inc(&graph->cnt[gcnt_acc_walked_blocks]);
- }
- STAT_LEAVE;
-}
-
-static bool is_const(ir_node *const node)
-{
- switch (get_irn_opcode(node)) {
- case iro_Address:
- case iro_Align:
- case iro_Const:
- case iro_Offset:
- case iro_Size:
- return true;
- default:
- return false;
- }
-}
-
-/**
- * Called for every node that is removed due to an optimization.
- *
- * @param n the IR node that will be removed
- * @param hmap the hash map containing ir_op* -> opt_entry_t*
- * @param kind the optimization kind
- */
-static void removed_due_opt(ir_node *n, hmap_opt_entry_t *hmap, hook_opt_kind kind)
-{
- /* ignore CSE for Constants */
- if (kind == HOOK_OPT_CSE && is_const(n))
- return;
-
- /* increase global value */
- op_id_t const op_id = stat_get_irn_op(n);
- opt_entry_t *const entry = opt_get_entry(op_id, hmap);
- cnt_inc(&entry->count);
-}
-
-/**
- * Hook: Reassociation is started/stopped.
- *
- * @param ctx the hook context
- * @param flag if non-zero, reassociation is started else stopped
- */
-static void stat_reassociate(void *ctx, int flag)
-{
- (void)ctx;
- if (!status->stat_options)
- return;
-
- STAT_ENTER;
- {
- status->reassoc_run = flag;
- }
- STAT_LEAVE;
-}
-
-/**
- * Hook: A node was lowered into other nodes
- *
- * @param ctx the hook context
- * @param node the IR node that will be lowered
- */
-static void stat_lower(void *ctx, ir_node *node)
-{
- (void)ctx;
- if (!status->stat_options)
- return;
-
- STAT_ENTER;
- {
- graph_entry_t *const graph = get_graph_entry(node, status->irg_hash);
- removed_due_opt(node, graph->opt_hash[HOOK_LOWERED], HOOK_LOWERED);
- }
- STAT_LEAVE;
-}
-
-/**
- * Hook: A graph was inlined.
- *
- * @param ctx the hook context
- * @param call the IR call that will re changed into the body of
- * the called IR graph
- * @param called_irg the IR graph representing the called routine
- */
-static void stat_inline(void *ctx, ir_node *call, ir_graph *called_irg)
-{
- (void)ctx;
- if (!status->stat_options)
- return;
-
- STAT_ENTER;
- {
- graph_entry_t *const graph = get_graph_entry(call, status->irg_hash);
- cnt_inc(&graph->cnt[gcnt_acc_got_inlined]);
- graph_entry_t *const i_graph = graph_get_entry(called_irg, status->irg_hash);
- cnt_inc(&i_graph->cnt[gcnt_acc_was_inlined]);
- }
- STAT_LEAVE;
-}
-
-/**
- * Hook: A graph with tail-recursions was optimized.
- *
- * @param ctx the hook context
- */
-static void stat_tail_rec(void *ctx, ir_graph *irg, int n_calls)
-{
- (void)ctx;
- if (!status->stat_options)
- return;
-
- STAT_ENTER;
- {
- graph_entry_t *const graph = graph_get_entry(irg, status->irg_hash);
- graph->num_tail_recursion += n_calls;
- }
- STAT_LEAVE;
-}
-
-/**
- * Strength reduction was performed on an iteration variable.
- *
- * @param ctx the hook context
- */
-static void stat_strength_red(void *ctx, ir_graph *irg, ir_node *strong)
-{
- (void)ctx;
- if (!status->stat_options)
- return;
-
- STAT_ENTER;
- {
- graph_entry_t *const graph = graph_get_entry(irg, status->irg_hash);
- cnt_inc(&graph->cnt[gcnt_acc_strength_red]);
-
- removed_due_opt(strong, graph->opt_hash[HOOK_OPT_STRENGTH_RED], HOOK_OPT_STRENGTH_RED);
- }
- STAT_LEAVE;
-}
-
-/**
- * Hook: Start/Stop the dead node elimination.
- *
- * @param ctx the hook context
- */
-static void stat_dead_node_elim(void *ctx, ir_graph *irg, int start)
-{
- (void)ctx;
- (void)irg;
- if (!status->stat_options)
- return;
-
- status->in_dead_node_elim = (start != 0);
-}
-
-/**
- * Hook: real function call was optimized.
- */
-static void stat_func_call(void *context, ir_graph *irg, ir_node *call)
-{
- (void)context;
- (void)call;
- if (!status->stat_options)
- return;
-
- STAT_ENTER;
- {
- graph_entry_t *const graph = graph_get_entry(irg, status->irg_hash);
- cnt_inc(&graph->cnt[gcnt_acc_real_func_call]);
- }
- STAT_LEAVE;
-}
-
-/**
- * Hook: A multiply was replaced by a series of Shifts/Adds/Subs.
- *
- * @param ctx the hook context
- */
-static void stat_arch_dep_replace_mul_with_shifts(void *ctx, ir_node *mul)
-{
- (void)ctx;
- if (!status->stat_options)
- return;
-
- STAT_ENTER;
- {
- graph_entry_t *const graph = get_graph_entry(mul, status->irg_hash);
- removed_due_opt(mul, graph->opt_hash[HOOK_OPT_ARCH_DEP], HOOK_OPT_ARCH_DEP);
- }
- STAT_LEAVE;
-}
-
-/**
- * Hook: A division by const was replaced.
- *
- * @param ctx the hook context
- * @param node the division node that will be optimized
- */
-static void stat_arch_dep_replace_division_by_const(void *ctx, ir_node *node)
-{
- (void)ctx;
- if (!status->stat_options)
- return;
-
- STAT_ENTER;
- {
- graph_entry_t *const graph = get_graph_entry(node, status->irg_hash);
- removed_due_opt(node, graph->opt_hash[HOOK_OPT_ARCH_DEP], HOOK_OPT_ARCH_DEP);
- }
- STAT_LEAVE;
-}
-
-/*
- * Update the register pressure of a block.
- *
- * @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
- */
-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 *const graph = graph_get_entry(irg, status->irg_hash);
- be_block_entry_t *const block_ent = be_block_get_entry(block, graph->be_block_hash);
- reg_pressure_entry_t *const rp_ent = OALLOCZ(&status->be_data, reg_pressure_entry_t);
-
- rp_ent->class_name = class_name;
- rp_ent->pressure = pressure;
-
- pset_insert(block_ent->reg_pressure, rp_ent, hash_ptr(class_name));
- }
- STAT_LEAVE;
-}
-
-/* Dumps a statistics snapshot. */
-void stat_dump_snapshot(const char *name, const char *phase)
-{
- if (!status->stat_options)
- return;
-
- STAT_ENTER;
- {
- graph_entry_t *const 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 */
- char const *p = strrchr(name, '/');
-#ifdef _WIN32
- {
- char const *const q = strrchr(name, '\\');
- /* NULL might be not the smallest pointer */
- if (q && (!p || q > p))
- p = q;
- }
-#endif /* _WIN32 */
- p = p ? p + 1 : name;
-
- char fname[2048];
- snprintf(fname, sizeof(fname), "%.*sfirmstat-%s-%s", (int)(p - name), name, phase, p);
-
- stat_dump_init(fname);
-
- /* calculate the graph statistics */
- foreach_pset(status->irg_hash, graph_entry_t, entry) {
- /* special entry for the global count */
- if (!entry->irg)
- continue;
- if (!entry->is_deleted) {
- /* the graph is still alive, count the nodes on it */
- update_graph_stat(global, entry);
- }
- }
-
- /* some calculations are dependent, we pushed them on the wait_q */
- while (!pdeq_empty(status->wait_q)) {
- graph_entry_t *const entry = (graph_entry_t*)pdeq_getr(status->wait_q);
- update_graph_stat_2(entry);
- }
-
- /* dump per graph */
- foreach_pset(status->irg_hash, graph_entry_t, entry) {
- /* special entry for the global count */
- if (!entry->irg)
- continue;
-
- if (!entry->is_deleted || status->stat_options & FIRMSTAT_COUNT_DELETED) {
- stat_dump_graph(entry);
- }
-
- if (!entry->is_deleted) {
- /* clear the counter that are not accumulated */
- graph_clear_entry(entry, 0);
- }
- }
-
- /* 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, ARRAY_SIZE(status->num_opts));
- clear_optimization_counter();
-
- stat_dump_finish();
-
- stat_finish_pattern_history(fname);
-
- /* clear the global counters here */
- foreach_pset(global->opcode_hash, node_entry_t, entry) {
- opcode_clear_entry(entry);
- }
- /* clear all global counter */
- graph_clear_entry(global, /*all=*/1);
- }
- STAT_LEAVE;
-}
-
-/** the hook entries for the Firm statistics module */
-static hook_entry_t stat_hooks[hook_last];
-
-/* initialize the statistics module. */
-void firm_init_stat(void)
-{
-#define HOOK(h, fkt) \
- stat_hooks[h].hook._##h = fkt; register_hook(h, &stat_hooks[h])
-
- if (!(stat_options & FIRMSTAT_ENABLED))
- return;
-
- status = XMALLOCZ(stat_info_t);
-
- /* enable statistics */
- status->stat_options = stat_options & FIRMSTAT_ENABLED ? stat_options : 0;
-
- /* register all hooks */
- HOOK(hook_new_ir_op, stat_new_ir_op);
- HOOK(hook_free_ir_op, stat_free_ir_op);
- HOOK(hook_new_node, stat_new_node);
- HOOK(hook_turn_into_id, stat_turn_into_id);
- HOOK(hook_normalize, stat_normalize);
- HOOK(hook_new_graph, stat_new_graph);
- HOOK(hook_free_graph, stat_free_graph);
- HOOK(hook_irg_walk, stat_irg_walk);
- HOOK(hook_irg_walk_blkwise, stat_irg_walk_blkwise);
- HOOK(hook_irg_block_walk, stat_irg_block_walk);
- HOOK(hook_reassociate, stat_reassociate);
- HOOK(hook_lower, stat_lower);
- HOOK(hook_inline, stat_inline);
- HOOK(hook_tail_rec, stat_tail_rec);
- HOOK(hook_strength_red, stat_strength_red);
- HOOK(hook_dead_node_elim, stat_dead_node_elim);
- 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);
-
- obstack_init(&status->cnts);
- obstack_init(&status->be_data);
-
- /* create the hash-tables */
- status->irg_hash = new_pset(graph_cmp, 8);
- status->ir_op_hash = new_pset(opcode_cmp_2, 1);
-
- /* create the wait queue */
- status->wait_q = new_pdeq();
-
- if (stat_options & FIRMSTAT_COUNT_STRONG_OP) {
- status->op_Phi0 = "Phi0";
- status->op_PhiM = "PhiM";
- status->op_ProjM = "ProjM";
- status->op_MulC = "MulC";
- status->op_DivC = "DivC";
- status->op_ModC = "ModC";
- } else {
- status->op_Phi0 = NULL;
- status->op_PhiM = NULL;
- status->op_ProjM = NULL;
- status->op_MulC = NULL;
- status->op_DivC = NULL;
- status->op_ModC = NULL;
- }
-
- /* for Florian: count the Sel depth */
- if (stat_options & FIRMSTAT_COUNT_SELS) {
- status->op_SelSel = "Sel(Sel)";
- status->op_SelSelSel = "Sel(Sel(Sel))";
- } else {
- status->op_SelSel = NULL;
- status->op_SelSelSel = NULL;
- }
-
- /* register the dumper */
- stat_register_dumper(&simple_dumper);
-
- if (stat_options & FIRMSTAT_CSV_OUTPUT)
- stat_register_dumper(&csv_dumper);
-
- /* initialize the pattern hash */
- stat_init_pattern_history(stat_options & FIRMSTAT_PATTERN_ENABLED);
-
- /* initialize the Const options */
- if (stat_options & FIRMSTAT_COUNT_CONSTS)
- stat_init_const_cnt(status);
-
- /* distribution table for parameter counts */
- status->dist_param_cnt = stat_new_int_distrib_tbl();
-
- clear_optimization_counter();
-
-#undef HOOK
-}
-
-/**
- * Frees all dumper structures.
- */
-static void stat_term_dumper(void)
-{
- for (dumper_t *dumper = status->dumper; dumper;) {
- dumper_t *const next_dumper = dumper->next;
- free(dumper);
- dumper = next_dumper;
- }
-}
-
-
-/* Terminates the statistics module, frees all memory. */
-void stat_term(void)
-{
- if (status) {
- obstack_free(&status->be_data, NULL);
- obstack_free(&status->cnts, NULL);
-
- stat_term_dumper();
-
- free(status);
- status = NULL;
- }
-}
-
-/* returns 1 if statistics were initialized, 0 otherwise */
-int stat_is_active(void)
-{
- return status != NULL;
-}
-
-void init_stat(void)
-{
- lc_opt_entry_t *root_grp = firm_opt_get_root();
- lc_opt_entry_t *be_grp = lc_opt_get_grp(root_grp, "be");
-
- static const lc_opt_enum_mask_items_t stat_items[] = {
- { "enabled", FIRMSTAT_ENABLED },
- { "pattern", FIRMSTAT_PATTERN_ENABLED },
- { "count_strong_op", FIRMSTAT_COUNT_STRONG_OP },
- { "count_dag", FIRMSTAT_COUNT_DAG },
- { "count_deleted", FIRMSTAT_COUNT_DELETED },
- { "count_sels", FIRMSTAT_COUNT_SELS },
- { "count_consts", FIRMSTAT_COUNT_CONSTS },
- { "csv_output", FIRMSTAT_CSV_OUTPUT },
- { NULL, 0 }
- };
- static lc_opt_enum_mask_var_t statmask = { &stat_options, stat_items };
- static const lc_opt_table_entry_t stat_optionstable[] = {
- LC_OPT_ENT_ENUM_MASK("statistics", "enable statistics", &statmask),
- LC_OPT_LAST
- };
- lc_opt_add_table(be_grp, stat_optionstable);
-}
diff --git a/ir/stat/firmstat_t.h b/ir/stat/firmstat_t.h
deleted file mode 100644
index 39236df..0000000
--- a/ir/stat/firmstat_t.h
+++ /dev/null
@@ -1,517 +0,0 @@
-/*
- * This file is part of libFirm.
- * Copyright (C) 2012 University of Karlsruhe.
- */
-
-/**
- * @file
- * @brief Statistics for Firm. Internal data structures.
- * @author Michael Beck
- */
-#ifndef FIRM_STAT_FIRMSTAT_T_H
-#define FIRM_STAT_FIRMSTAT_T_H
-
-#include "firmstat.h"
-
-#include "irop_t.h"
-#include "irnode_t.h"
-#include "irgraph_t.h"
-#include "pset.h"
-#include "pdeq.h"
-#include "irprog.h"
-#include "irgwalk.h"
-#include "counter.h"
-#include "irhooks.h"
-#include "set.h"
-
-/*
- * just be make some things clear :-), the
- * poor man "generics"
- */
-#define HASH_MAP(type) hmap_##type
-
-typedef pset hmap_node_entry_t;
-typedef pset hmap_graph_entry_t;
-typedef pset hmap_opt_entry_t;
-typedef pset hmap_block_entry_t;
-typedef pset hmap_be_block_entry_t;
-typedef pset hmap_reg_pressure_entry_t;
-typedef pset hmap_ir_op;
-typedef pset hmap_distrib_entry_t;
-
-/**
- * Statistic options, can be or'ed.
- */
-enum firmstat_options_t {
- FIRMSTAT_ENABLED = 0x00000001, /**< enable statistics */
- FIRMSTAT_PATTERN_ENABLED = 0x00000002, /**< enable pattern calculation */
- FIRMSTAT_COUNT_STRONG_OP = 0x00000004, /**< if set, count Mul/Div/Mod by constant */
- FIRMSTAT_COUNT_DAG = 0x00000008, /**< if set, count DAG statistics */
- FIRMSTAT_COUNT_DELETED = 0x00000010, /**< if set, count deleted graphs */
- FIRMSTAT_COUNT_SELS = 0x00000020, /**< if set, count Sel(Sel(..)) differently */
- FIRMSTAT_COUNT_CONSTS = 0x00000040, /**< if set, count Const statistics */
- FIRMSTAT_CSV_OUTPUT = 0x10000000 /**< CSV output of some mini-statistic */
-};
-
-/**
- * Additional flags for statistics.
- */
-enum firmstat_optimizations_t {
- FS_OPT_NEUTRAL_0 = HOOK_OPT_LAST, /**< a op 0 = 0 op a = a */
- FS_OPT_NEUTRAL_1, /**< a op 1 = 1 op a = a */
- FS_OPT_ADD_A_A, /**< a + a = a * 2 */
- FS_OPT_ADD_A_MINUS_B, /**< a + -b = a - b */
- FS_OPT_ADD_SUB, /**< (a + x) - x = (a - x) + x */
- FS_OPT_ADD_MUL_A_X_A, /**< a * x + a = a * (x + 1) */
- FS_OPT_SUB_0_A, /**< 0 - a = -a */
- FS_OPT_MINUS_SUB, /**< - (a - b) = b - a */
- FS_OPT_SUB_MINUS, /**< a - (-b) = a + b */
- FS_OPT_SUB_MUL_A_X_A, /**< a * x - a = a * (x - 1) */
- FS_OPT_SUB_SUB_X_Y_Z, /**< (x - y) - z = x - (y + z) */
- FS_OPT_SUB_C_NOT_X, /**< c - ~a = a + (c+1) */
- FS_OPT_SUB_TO_ADD, /**< (-a) - b = -(a + b), a - (b - c) = a + (c - b), a - (b * C) -> a + (b * -C) */
- FS_OPT_SUB_TO_NOT, /**< -1 - x -> ~x on two's complement */
- FS_OPT_SUB_TO_CONV, /**< a - NULL = (int)a */
- FS_OPT_MUL_MINUS, /**< (-a) * (b - c) -> a * (c - b) */
- FS_OPT_MUL_MINUS_1, /**< a * -1 = -a */
- FS_OPT_MINUS_MUL_C, /**< (-a) * C = a * (-C) */
- FS_OPT_MUL_MINUS_MINUS, /**< (-a) * (-b) = a * b */
- FS_OPT_OR, /**< a | a = a | 0 = 0 | a = a */
- FS_OPT_AND, /**< a & 0b1...1 = 0b1...1 & a = a & a = a */
- FS_OPT_TO_EOR, /**< (a|b) & ~(a&b) = a^b */
- FS_OPT_EOR_A_A, /**< a ^ a = 0 */
- FS_OPT_EOR_A_B_A, /**< (a ^ b) ^ a = b */
- FS_OPT_EOR_TO_NOT_BOOL, /**< bool ^ 1 = !bool */
- FS_OPT_EOR_TO_NOT, /**< x ^ 0b1..1 = ~x, (a ^ b) & b -> ~a & b */
- FS_OPT_NOT_CMP, /**< !(a cmp b) = a !cmp b */
- FS_OPT_REASSOC_SHIFT, /**< (x SHF c1) SHF c2 = x SHF (c1+c2) */
- FS_OPT_SHIFT_AND, /**< (a SHF c) AND (b SHF c) = (a AND b) SHF c */
- FS_OPT_SHIFT_OR, /**< (a SHF c) OR (b SHF c) = (a OR b) SHF c */
- FS_OPT_SHIFT_EOR, /**< (a SHF c) XOR (b SHF c) = (a XOR b) SHF c */
- FS_OPT_CONV, /**< a Conv could be removed */
- FS_OPT_MIN_MAX_EQ, /**< Min(a,a) = Max(a,a) = a */
- FS_OPT_MUX_COMBINE, /**< two Mux nodes where combined into one */
- FS_OPT_MUX_CONV, /**< MuxI(sel, 1, 0) = (I)sel */
- FS_OPT_MUX_BOOL, /**< Muxb(sel, true, false) = sel */
- FS_OPT_MUX_NOT_BOOL, /**< Muxb(sel, false, true) = Not(sel) */
- FS_OPT_MUX_OR_BOOL, /**< Muxb(sel, true, x) = Or(sel, x) */
- FS_OPT_MUX_ORNOT_BOOL, /**< Muxb(sel, x, true) = Or(Not(sel), x) */
- FS_OPT_MUX_AND_BOOL, /**< Muxb(sel, x, false) = And(sel, x) */
- FS_OPT_MUX_ANDNOT_BOOL, /**< Muxb(sel, false, x) = And(Not(sel), x) */
- FS_OPT_MUX_C, /**< Mux(C, f, t) = C ? t : f */
- FS_OPT_MUX_EQ, /**< Mux(v, x, x) = x */
- FS_OPT_MUX_TRANSFORM, /**< Mux(t ==/!= f, t, f) = f/t, Mux(t ==/!= 0, -t, t) = -t/t */
- FS_OPT_MUX_TO_MIN, /**< Mux(a < b, a, b) = Min(a,b) */
- FS_OPT_MUX_TO_MAX, /**< Mux(a > b, a, b) = Max(a,b) */
- FS_OPT_MUX_TO_BITOP, /**< Mux((a & 2^x) ==/!= 0, 2^x, 0) = (a & 2^x) (xor 2^x) */
- FS_OPT_INVOLUTION, /**< OP(OP(x)) = x */
- FS_OPT_MINUS_NOT, /**< -(~x) = x + 1 */
- FS_OPT_NOT_MINUS_1, /**< ~(x - 1) = -x */
- FS_OPT_NOT_PLUS_C, /**< ~x + C = (C - 1) - x */
- FS_OPT_ADD_X_NOT_X, /**< ~x + x = -1 */
- FS_OPT_FP_INV_MUL, /**< x / y = x * (1.0/y) */
- FS_OPT_CONST_PHI, /**< Constant evaluation on Phi */
- FS_OPT_PREDICATE, /**< Predicate optimization */
- FS_OPT_DEMORGAN, /**< optimization using DeMorgan's law */
- FS_OPT_CMP_OP_OP, /**< CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y) */
- FS_OPT_CMP_OP_C, /**< CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2) */
- FS_OPT_CMP_CONV_CONV, /**< CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y) */
- FS_OPT_CMP_CONV, /**< CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y) */
- FS_OPT_CMP_TO_BOOL, /**< CMP optimization: Cmp(x, y) = BoolOP(x, y) */
- FS_OPT_CMP_CNST_MAGN, /**< CMP optimization: reduced magnitude of a const */
- FS_OPT_CMP_SHF_TO_AND, /**< CMP optimization: transformed shift into And */
- FS_OPT_CMP_MOD_TO_AND, /**< CMP optimization: transformed Mod into And */
- FS_OPT_NOP, /**< the operation is a NOP */
- FS_OPT_GVN_FOLLOWER, /**< GVN-PRE: replaced a follower */
- FS_OPT_GVN_FULLY, /**< GVN-PRE: replaced by fully redundant value */
- FS_OPT_GVN_PARTLY, /**< GVN-PRE: replaced by partly redundant value */
- FS_OPT_COMBO_CONST, /**< Combo: evaluated into Constant */
- FS_OPT_COMBO_CF, /**< Combo: removed conditional control flow */
- FS_OPT_COMBO_FOLLOWER, /**< Combo: replaced a follower */
- FS_OPT_COMBO_CONGRUENT, /**< Combo: replaced by congruent */
- FS_OPT_JUMPTHREADING, /**< Jump threading: removed conditional control flow */
- FS_OPT_RTS_ABS, /**< RTS optimization: call to abs() replaced */
- FS_OPT_RTS_ALLOCA, /**< RTS optimization: call to alloca() replaced */
- FS_OPT_RTS_SQRT, /**< RTS optimization: call to sqrt() replaced */
- FS_OPT_RTS_CBRT, /**< RTS optimization: call to cbrt() replaced */
- FS_OPT_RTS_POW, /**< RTS optimization: call to pow() replaced */
- FS_OPT_RTS_EXP, /**< RTS optimization: call to exp() replaced */
- FS_OPT_RTS_LOG, /**< RTS optimization: call to log() replaced */
- FS_OPT_RTS_SIN, /**< RTS optimization: call to sin() replaced */
- FS_OPT_RTS_COS, /**< RTS optimization: call to cos() replaced */
- FS_OPT_RTS_TAN, /**< RTS optimization: call to tan() replaced */
- FS_OPT_RTS_ASIN, /**< RTS optimization: call to asin() replaced */
- FS_OPT_RTS_ACOS, /**< RTS optimization: call to acos() replaced */
- FS_OPT_RTS_ATAN, /**< RTS optimization: call to atan() replaced */
- FS_OPT_RTS_SINH, /**< RTS optimization: call to sinh() replaced */
- FS_OPT_RTS_COSH, /**< RTS optimization: call to cosh() replaced */
- FS_OPT_RTS_TANH, /**< RTS optimization: call to tanh() replaced */
- FS_OPT_RTS_SYMMETRIC, /**< RTS optimization: call to symmetric function f(-x) replaced by f(x) */
- FS_OPT_RTS_STRCMP, /**< RTS optimization: call to strcmp() replaced */
- FS_OPT_RTS_STRNCMP, /**< RTS optimization: call to strncmp() replaced */
- FS_OPT_RTS_STRCPY, /**< RTS optimization: call to strcpy() replaced */
- FS_OPT_RTS_STRLEN, /**< RTS optimization: call to strlen() replaced */
- FS_OPT_RTS_MEMCPY, /**< RTS optimization: call to memcpy() replaced */
- FS_OPT_RTS_MEMPCPY, /**< RTS optimization: call to mempcpy() replaced */
- FS_OPT_RTS_MEMMOVE, /**< RTS optimization: call to memmove() replaced */
- FS_OPT_RTS_MEMSET, /**< RTS optimization: call to memset() replaced */
- FS_OPT_RTS_MEMCMP, /**< RTS optimization: call to memcmp() replaced */
- FS_OPT_MAX
-};
-
-/**
- * An entry in a distribution table
- */
-typedef struct distrib_entry_t {
- counter_t cnt; /**< the current count */
- const void *object; /**< the object which is counted */
-} distrib_entry_t;
-
-/** The type of the hash function for objects in distribution tables. */
-typedef unsigned (*distrib_hash_fun)(const void *object);
-
-/**
- * The distribution table.
- */
-typedef struct distrib_tbl_t {
- struct obstack cnts; /**< obstack containing the distrib_entry_t entries */
- HASH_MAP(distrib_entry_t) *hash_map; /**< the hash map containing the distribution */
- distrib_hash_fun hash_func; /**< the hash function for object in this distribution */
- unsigned int_dist; /**< non-zero, if it's a integer distribution */
-} distrib_tbl_t;
-
-/**
- * possible address marker values
- */
-enum adr_marker_t {
- MARK_ADDRESS_CALC = 1, /**< the node is an address expression */
- MARK_REF_ADR = 2, /**< the node is referenced by an address expression */
- MARK_REF_NON_ADR = 4, /**< the node is referenced by a non-address expression */
-};
-
-/**
- * An entry in the address_mark set
- */
-typedef struct address_mark_entry_t {
- ir_node const *node; /**< the node which this entry belongs to, needed for compare */
- unsigned mark; /**< the mark, a bitmask of enum adr_marker_t */
-} address_mark_entry_t;
-
-typedef char const *op_id_t;
-
-/**
- * An entry for ir_nodes, used in ir_graph statistics.
- */
-typedef struct node_entry_t {
- counter_t cnt_alive; /**< amount of nodes in this entry */
- counter_t new_node; /**< amount of new nodes for this entry */
- counter_t into_Id; /**< amount of nodes that turned into Id's for this entry */
- counter_t normalized; /**< amount of nodes that normalized for this entry */
- op_id_t op_id; /**< the op for this entry */
-} node_entry_t;
-
-enum leaf_call_state_t {
- LCS_UNKNOWN = 0, /**< state is unknown yet */
- LCS_LEAF_CALL = 1, /**< only leaf functions will be called */
- LCS_NON_LEAF_CALL = 2, /**< at least one non-leaf function will be called or indetermined */
-};
-
-/**
- * Graph counter indexes. The first one are accumulated once, the other are always deleted before an
- * snapshot is taken.
- */
-enum graph_counter_names {
- gcnt_acc_walked, /**< walker walked over the graph, accumulated */
- gcnt_acc_walked_blocks, /**< walker walked over the graph blocks, accumulated */
- gcnt_acc_was_inlined, /**< number of times other graph were inlined, accumulated */
- gcnt_acc_got_inlined, /**< number of times this graph was inlined, accumulated */
- gcnt_acc_strength_red, /**< number of times strength reduction was successful on this graph, accumulated */
- gcnt_acc_real_func_call, /**< number real function call optimization, accumulated */
-
- /* --- non-accumulated values from here */
- _gcnt_non_acc, /**< first non-accumulated counter */
-
- gcnt_edges = _gcnt_non_acc, /**< number of DF edges in this graph */
- gcnt_all_calls, /**< number of all calls */
- gcnt_call_with_cnst_arg, /**< number of calls with const args */
- gcnt_call_with_all_cnst_arg, /**< number of calls with all const args */
- gcnt_call_with_local_adr, /**< number of calls with address of local var args */
- gcnt_indirect_calls, /**< number of indirect calls */
- gcnt_external_calls, /**< number of external calls */
- gcnt_pure_adr_ops, /**< number of pure address operation */
- gcnt_all_adr_ops, /**< number of all address operation */
- gcnt_global_adr, /**< number of global load/store addresses. */
- gcnt_local_adr, /**< number of local load/store addresses. */
- gcnt_param_adr, /**< number of parameter load/store addresses. */
- gcnt_this_adr, /**< number of this load/store addresses. */
- gcnt_other_adr, /**< number of other load/store addresses. */
-
- /* --- must be the last enum constant --- */
- _gcnt_last = gcnt_other_adr /**< number of counters */
-};
-
-/**
- * An entry for ir_graphs. These numbers are calculated for every IR graph.
- */
-typedef struct graph_entry_t {
- struct obstack recalc_cnts; /**< obstack containing the counters that are recalculated */
- HASH_MAP(node_entry_t) *opcode_hash; /**< hash map containing the opcode counter */
- HASH_MAP(block_entry_t) *block_hash; /**< hash map containing the block counter */
- HASH_MAP(be_block_entry_t) *be_block_hash; /**< hash map containing backend block information */
- counter_t cnt[_gcnt_last]; /**< counter */
- unsigned num_tail_recursion; /**< number of tail recursion optimizations */
- HASH_MAP(opt_entry_t) *opt_hash[FS_OPT_MAX]; /**< hash maps containing opcode counter for optimizations */
- ir_graph *irg; /**< the graph of this object */
- ir_entity *ent; /**< the entity of this graph if one exists */
- set *address_mark; /**< a set containing the address marks of the nodes */
- unsigned is_deleted:1; /**< set if this irg was deleted */
- unsigned is_leaf:1; /**< set, if this irg is a leaf function */
- unsigned is_leaf_call:2; /**< set, if this irg calls only leaf functions */
- unsigned is_recursive:1; /**< set, if this irg has recursive calls */
- unsigned is_chain_call:1; /**< set, if this irg is a chain call */
- unsigned is_strict:1; /**< set, if this irg represents a strict program */
- unsigned is_analyzed:1; /**< helper: set, if this irg was already analysed */
-} graph_entry_t;
-
-/**
- * An entry for optimized ir_nodes
- */
-typedef struct opt_entry_t {
- counter_t count; /**< optimization counter */
- op_id_t op_id; /**< the op for this entry */
-} opt_entry_t;
-
-/**
- * An entry for register pressure.
- */
-typedef struct reg_pressure_entry_t {
- const char *class_name; /**< name of the register class */
- int pressure; /**< the register pressure for this class */
-} reg_pressure_entry_t;
-
-/**
- * An entry for a block or extended block in a ir-graph
- */
-typedef struct be_block_entry_t {
- long block_nr; /**< block nr */
- /**< the highest register pressures for this block for each register class */
- HASH_MAP(reg_pressure_entry_t) *reg_pressure;
-} be_block_entry_t;
-
-/**
- * Block counter indexes. The first one are accumulated once, the other are always deleted before an
- * snapshot is taken.
- */
-enum block_counter_names {
- bcnt_nodes, /**< the counter of nodes in this block */
- bcnt_edges, /**< the counter of edges in this block */
- bcnt_in_edges, /**< the counter of edges incoming from other blocks to this block */
- bcnt_out_edges, /**< the counter of edges outgoing from this block to other blocks */
- bcnt_phi_data, /**< the counter of data Phi nodes in this block */
-
- /* --- must be the last enum constant --- */
- _bcnt_last /**< number of counters */
-};
-
-/**
- * An entry for a block or extended block in a ir-graph
- */
-typedef struct block_entry_t {
- counter_t cnt[_bcnt_last]; /**< counter */
- long block_nr; /**< block nr */
- unsigned is_start:1; /**< set, if it's the Start block. */
- unsigned is_end:1; /**< set, if it's the End block. */
-} block_entry_t;
-
-/**
- * Some potential interesting float values
- */
-typedef enum float_classify_t {
- STAT_FC_0, /**< the float value 0.0 */
- STAT_FC_1, /**< the float value 1.0 */
- STAT_FC_2, /**< the float value 2.0 */
- STAT_FC_0_5, /**< the float value 0.5 */
- STAT_FC_POWER_OF_TWO, /**< another 2^x value */
- STAT_FC_OTHER, /**< all other values */
- STAT_FC_MAX /**< last value */
-} float_classify_t;
-
-/**
- * constant info
- */
-typedef struct constant_info_t {
- counter_t int_bits_count[32]; /**< distribution of bit sizes of integer constants */
- counter_t floats[STAT_FC_MAX]; /**< floating point constants */
- counter_t others; /**< all other constants */
-} constant_info_t;
-
-/** forward */
-typedef struct dumper_t dumper_t;
-
-/**
- * handler for dumping an IRG
- *
- * @param dmp the dumper
- * @param entry the IR-graph hash map entry
- */
-typedef void dump_graph_FUNC(dumper_t *dmp, graph_entry_t *entry);
-
-/**
- * handler for dumper a constant info table
- *
- * @param dmp the dumper
- */
-typedef void dump_const_table_FUNC(dumper_t *dmp, const constant_info_t *tbl);
-
-/**
- * dumps the parameter distribution table
- */
-typedef void dump_param_tbl_FUNC(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global);
-
-/**
- * dumps the optimizations counter
- */
-typedef void dump_opt_cnt_FUNC(dumper_t *dumper, const counter_t *tbl, unsigned len);
-
-/**
- * handler for dumper init
- *
- * @param dmp the dumper
- * @param name name of the file to dump to
- */
-typedef void dump_init_FUNC(dumper_t *dmp, const char *name);
-
-/**
- * handler for dumper finish
- *
- * @param dmp the dumper
- */
-typedef void dump_finish_FUNC(dumper_t *dmp);
-
-/**
- * statistics info
- */
-typedef struct statistic_info_t {
- unsigned stat_options; /**< statistic options: field must be first */
- struct obstack cnts; /**< obstack containing the counters that are incremented */
- struct obstack be_data; /**< obstack containing backend statistics data */
- HASH_MAP(graph_entry_t) *irg_hash; /**< hash map containing the counter for irgs */
- HASH_MAP(ir_op) *ir_op_hash; /**< hash map containing all ir_ops (accessible by op_codes) */
- pdeq *wait_q; /**< wait queue for leaf call decision */
- unsigned recursive:1; /**< flag for detecting recursive hook calls */
- unsigned in_dead_node_elim:1; /**< flag for dead node elimination runs */
- op_id_t op_Phi0; /**< pseudo op for Phi0 */
- op_id_t op_PhiM; /**< pseudo op for memory Phi */
- op_id_t op_ProjM; /**< pseudo op for memory Proj */
- op_id_t op_MulC; /**< pseudo op for multiplication by const */
- op_id_t op_DivC; /**< pseudo op for division by const */
- op_id_t op_ModC; /**< pseudo op for modulo by const */
- op_id_t op_SelSel; /**< pseudo op for Sel(Sel) */
- op_id_t op_SelSelSel; /**< pseudo op for Sel(Sel(Sel)) */
- dumper_t *dumper; /**< list of dumper */
- int reassoc_run; /**< if set, reassociation is running */
- constant_info_t const_info; /**< statistic info for constants */
- distrib_tbl_t *dist_param_cnt; /**< distribution table for call parameters */
-
- counter_t num_opts[FS_OPT_MAX];/**< count optimizations */
-} stat_info_t;
-
-/**
- * a dumper description
- */
-struct dumper_t {
- dump_graph_FUNC *dump_graph; /**< handler for dumping an irg */
- dump_const_table_FUNC *dump_const_tbl; /**< handler for dumping a const table */
- dump_param_tbl_FUNC *dump_param_tbl; /**< handler for dumping the Call parameter table */
- dump_opt_cnt_FUNC *dump_opt_cnt; /**< handler for dumping the optimization table. */
- dump_init_FUNC *init; /**< handler for init */
- dump_finish_FUNC *finish; /**< handler for finish */
- FILE *f; /**< the file to dump to */
- stat_info_t *status; /**< access to the global status */
- dumper_t *next; /**< link to the next dumper */
- unsigned tag; /**< the id tag of the dumper */
-};
-
-/**
- * internal init function, mainly registers commandline arguments.
- * (The use still has to call firm_init_stat() later
- */
-void init_stat(void);
-
-/**
- * helper: get an ir_op from an opcode
- */
-ir_op *stat_get_op_from_opcode(unsigned code);
-
-/* API for distribution tables */
-
-/**
- * creates a new distribution table.
- *
- * @param cmp_func Compare function for objects in the distribution
- * @param hash_func Hash function for objects in the distribution
- */
-distrib_tbl_t *stat_new_distrib_tbl(pset_cmp_fun cmp_func, distrib_hash_fun hash_func);
-
-/**
- * creates a new distribution table for an integer distribution.
- */
-distrib_tbl_t *stat_new_int_distrib_tbl(void);
-
-/**
- * destroys a distribution table.
- */
-void stat_delete_distrib_tbl(distrib_tbl_t *tbl);
-
-/**
- * increases object count by one
- */
-void stat_inc_distrib_tbl(distrib_tbl_t *tbl, const void *object);
-
-/**
- * increases key count by one
- */
-void stat_inc_int_distrib_tbl(distrib_tbl_t *tbl, int key);
-
-/** evaluates each entry of a distribution table. */
-typedef void (*eval_distrib_entry_fun)(const distrib_entry_t *entry, void *env);
-
-/**
- * iterates over all entries in a distribution table
- */
-void stat_iterate_distrib_tbl(const distrib_tbl_t *tbl, eval_distrib_entry_fun eval, void *env);
-
-/**
- * update info on Consts.
- *
- * @param node The Const node
- * @param graph The graph entry containing the call
- */
-void stat_update_const(stat_info_t *status, ir_node *node, graph_entry_t *graph);
-
-/**
- * clears the const statistics for a new snapshot.
- */
-void stat_const_clear(stat_info_t *status);
-
-/**
- * initialize the Const statistic.
- */
-void stat_init_const_cnt(stat_info_t *status);
-
-/**
- * return a human readable name for an float classification
- */
-const char *stat_fc_name(float_classify_t classification);
-
-/**
- * Update the register pressure of a block
- *
- * @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
- */
-void stat_be_block_regpressure(ir_graph *irg, ir_node *block, int pressure, const char *class_name);
-
-#endif
diff --git a/ir/stat/pattern.c b/ir/stat/pattern.c
deleted file mode 100644
index 53505a1..0000000
--- a/ir/stat/pattern.c
+++ /dev/null
@@ -1,911 +0,0 @@
-/*
- * This file is part of libFirm.
- * Copyright (C) 2012 University of Karlsruhe.
- */
-
-/**
- * @file
- * @brief Statistics for Firm. Pattern history.
- * @author Michael Beck
- */
-#include <assert.h>
-#include <stdlib.h>
-#include <limits.h>
-
-#include "util.h"
-#include "pattern.h"
-#include "ident.h"
-#include "irnode_t.h"
-#include "irgwalk.h"
-#include "irprog.h"
-#include "set.h"
-#include "pset.h"
-#include "counter.h"
-#include "pattern_dmp.h"
-#include "hashptr.h"
-#include "panic.h"
-
-/*
- * just be make some things clear :-), the
- * poor man "generics"
- */
-#define HASH_MAP(type) pset_##type
-
-typedef pset pset_pattern_entry_t;
-
-typedef unsigned char BYTE;
-
-/** Maximum size of the pattern store. */
-#define PATTERN_STORE_SIZE 2048
-
-
-/**
- * The code buffer.
- */
-typedef struct code_buf_t {
- BYTE *next; /**< Next byte address to be written. */
- BYTE *end; /**< End address of the buffer. */
- BYTE *start; /**< Start address of the buffer. */
- unsigned hash; /**< The hash value for the buffer content. */
- unsigned overrun; /**< flag set if the buffer was overrun */
-} CODE_BUFFER;
-
-/**
- * Reserved VLC codes.
- */
-enum vlc_code_t {
- VLC_7BIT = 0x00, /**< 8 bit code, carrying 7 bits payload */
- VLC_14BIT = 0x80, /**< 16 bit code, carrying 14 bits payload */
- VLC_21BIT = 0xC0, /**< 24 bit code, carrying 21 bits payload */
- VLC_28BIT = 0xE0, /**< 32 bit code, carrying 28 bits payload */
- VLC_32BIT = 0xF0, /**< 40 bit code, carrying 32 bits payload */
-
- VLC_TAG_FIRST = 0xF1, /**< First possible tag value. */
- VLC_TAG_ICONST = 0xFB, /**< Encodes an integer constant. */
- VLC_TAG_EMPTY = 0xFC, /**< Encodes an empty entity. */
- VLC_TAG_OPTION = 0xFD, /**< Options exists. */
- VLC_TAG_REF = 0xFE, /**< Special tag, next code is an ID. */
- VLC_TAG_END = 0xFF, /**< End tag. */
-};
-
-/*
- * An entry for holding one pattern.
- */
-typedef struct pattern_entry_t {
- counter_t count; /**< Amount of pattern occurance. */
- size_t len; /**< The length of the VLC encoded buffer. */
- BYTE buf[1]; /**< The buffer containing the VLC encoded pattern. */
-} pattern_entry_t;
-
-/**
- * Current options for the pattern matcher.
- */
-enum options_t {
- OPT_WITH_MODE = 0x00000001, /**< use modes */
- OPT_ENC_DAG = 0x00000002, /**< encode DAGs, not terms */
- OPT_WITH_ICONST = 0x00000004, /**< encode integer constants */
- OPT_PERSIST_PATTERN = 0x00000008, /**< persistent pattern hash */
-};
-
-
-/**
- * Pattern info.
- */
-typedef struct pattern_info_t {
- int enable; /**< If non-zero, this module is enabled. */
- struct obstack obst; /**< An obstack containing the counters. */
- HASH_MAP(pattern_entry_t) *pattern_hash; /**< A hash map containing the pattern. */
- unsigned bound; /**< Lowest value for pattern output. */
- unsigned options; /**< Current option mask. */
- unsigned min_depth; /**< Minimum pattern depth. */
- unsigned max_depth; /**< Maximum pattern depth. */
-} pattern_info_t;
-
-/*
- * global status
- */
-static pattern_info_t _status, *status = &_status;
-
-/**
- * Compare two pattern for its occurance counter.
- */
-static int pattern_count_cmp(const void *elt, const void *key)
-{
- int cmp;
-
- pattern_entry_t **e1 = (pattern_entry_t **)elt;
- pattern_entry_t **e2 = (pattern_entry_t **)key;
-
- /* we want it sorted in descending order */
- cmp = cnt_cmp(&(*e2)->count, &(*e1)->count);
-
- return cmp;
-}
-
-/**
- * Compare two pattern for its pattern hash.
- */
-static int pattern_cmp(const void *elt, const void *key)
-{
- const pattern_entry_t *e1 = (const pattern_entry_t*)elt;
- const pattern_entry_t *e2 = (const pattern_entry_t*)key;
-
- if (e1->len == e2->len)
- return memcmp(e1->buf, e2->buf, e1->len);
-
- return e1->len < e2->len ? -1 : +1;
-}
-
-/**
- * Initialize a code buffer.
- *
- * @param buf the code buffer
- * @param data a buffer address
- * @param len the length of the data buffer
- */
-static void init_buf(CODE_BUFFER *buf, BYTE *data, size_t len)
-{
- buf->start =
- buf->next = data;
- buf->end = data + len;
- buf->hash = 0x2BAD4; /* An arbitrary seed. */
- buf->overrun = 0;
-}
-
-/**
- * Put a byte into the buffer.
- *
- * @param buf the code buffer
- * @param byte the byte to write
- *
- * The hash value for the buffer content is updated.
- */
-static inline void put_byte(CODE_BUFFER *buf, BYTE byte)
-{
- if (buf->next < buf->end) {
- *buf->next++ = byte;
- buf->hash = (buf->hash * 9) ^ byte;
- } else {
- buf->overrun = 1;
- }
-}
-
-/**
- * Returns the current length of a buffer.
- *
- * @param buf the code buffer
- *
- * @return the length of the buffer content
- */
-static size_t buf_lenght(const CODE_BUFFER *buf)
-{
- return buf->next - buf->start;
-}
-
-/**
- * Returns the current content of a buffer.
- *
- * @param buf the code buffer
- *
- * @return the start address of the buffer content
- */
-static const BYTE *buf_content(const CODE_BUFFER *buf)
-{
- return buf->start;
-}
-
-/**
- * Returns the hash value of a buffer.
- *
- * @param buf the code buffer
- *
- * @return the hash value of the buffer content
- */
-static unsigned buf_hash(const CODE_BUFFER *buf)
-{
- return buf->hash;
-}
-
-/**
- * Returns non-zero if a buffer overrun has occurred.
- *
- * @param buf the code buffer
- */
-static unsigned buf_overrun(const CODE_BUFFER *buf)
-{
- return buf->overrun;
-}
-
-/**
- * Returns the next byte from the buffer WITHOUT dropping.
- *
- * @param buf the code buffer
- *
- * @return the next byte from the code buffer
- */
-static inline BYTE look_byte(CODE_BUFFER *buf)
-{
- if (buf->next < buf->end)
- return *buf->next;
- return VLC_TAG_END;
-}
-
-/**
- * Returns the next byte from the buffer WITH dropping.
- *
- * @param buf the code buffer
- *
- * @return the next byte from the code buffer
- */
-static inline BYTE get_byte(CODE_BUFFER *buf)
-{
- if (buf->next < buf->end)
- return *buf->next++;
- return VLC_TAG_END;
-}
-
-#define BITS(n) (1 << (n))
-
-/**
- * Put a 32bit value into the buffer.
- *
- * @param buf the code buffer
- * @param code the code to be written into the buffer
- */
-static void put_code(CODE_BUFFER *buf, unsigned code)
-{
- if (code < BITS(7)) {
- put_byte(buf, VLC_7BIT | code);
- } else if (code < BITS(6 + 8)) {
- put_byte(buf, VLC_14BIT | (code >> 8));
- put_byte(buf, code);
- } else if (code < BITS(5 + 8 + 8)) {
- put_byte(buf, VLC_21BIT | (code >> 16));
- put_byte(buf, code >> 8);
- put_byte(buf, code);
- } else if (code < BITS(4 + 8 + 8 + 8)) {
- put_byte(buf, VLC_28BIT | (code >> 24));
- put_byte(buf, code >> 16);
- put_byte(buf, code >> 8);
- put_byte(buf, code);
- } else {
- put_byte(buf, VLC_32BIT);
- put_byte(buf, code >> 24);
- put_byte(buf, code >> 16);
- put_byte(buf, code >> 8);
- put_byte(buf, code);
- }
-}
-
-#define BIT_MASK(n) ((1 << (n)) - 1)
-
-/**
- * Get 32 bit from the buffer.
- *
- * @param buf the code buffer
- *
- * @return next 32bit value from the code buffer
- */
-static unsigned get_code(CODE_BUFFER *buf)
-{
- unsigned code = get_byte(buf);
-
- if (code < VLC_14BIT)
- return code;
- if (code < VLC_21BIT)
- return ((code & BIT_MASK(6)) << 8) | get_byte(buf);
- if (code < VLC_28BIT) {
- code = ((code & BIT_MASK(5)) << 16) | (get_byte(buf) << 8);
- code |= get_byte(buf);
- return code;
- }
- if (code < VLC_32BIT) {
- code = ((code & BIT_MASK(4)) << 24) | (get_byte(buf) << 16);
- code |= get_byte(buf) << 8;
- code |= get_byte(buf);
- return code;
- }
- if (code == VLC_32BIT) {
- code = get_byte(buf) << 24;
- code |= get_byte(buf) << 16;
- code |= get_byte(buf) << 8;
- code |= get_byte(buf);
- return code;
- }
- /* should not happen */
- panic("wrong code in buffer");
-}
-
-/**
- * Put a tag into the buffer.
- *
- * @param buf the code buffer
- * @param tag the tag to write to the code buffer
- */
-static void put_tag(CODE_BUFFER *buf, BYTE tag)
-{
- assert(tag >= VLC_TAG_FIRST && "invalid tag");
-
- put_byte(buf, tag);
-}
-
-/**
- * Returns the next tag or zero if the next code isn't a tag.
- *
- * @param buf the code buffer
- *
- * @return the next tag in the code buffer
- */
-static BYTE next_tag(CODE_BUFFER *buf)
-{
- BYTE b = look_byte(buf);
-
- if (b >= VLC_TAG_FIRST)
- return get_byte(buf);
- return 0;
-}
-
-/**
- * An Environment for the pattern encoder.
- */
-typedef struct codec_enc_t {
- CODE_BUFFER *buf; /**< The current code buffer. */
- set *id_set; /**< A set containing all already seen Firm nodes. */
- unsigned curr_id; /**< The current node id. */
- unsigned options; /**< The encoding options. */
- pattern_dumper_t *dmp; /**< The dumper for the decoder. */
-} codec_env_t;
-
-/**
- * An address entry.
- */
-typedef struct addr_entry_t {
- void *addr; /**< the address */
- unsigned id; /**< associated ID */
-} addr_entry_t;
-
-/**
- * Compare two addresses.
- */
-static int addr_cmp(const void *p1, const void *p2, size_t size)
-{
- const addr_entry_t *e1 = (const addr_entry_t*)p1;
- const addr_entry_t *e2 = (const addr_entry_t*)p2;
- (void) size;
-
- return e1->addr != e2->addr;
-}
-
-/**
- * Return the index of a (existing) mode.
- */
-static size_t find_mode_index(const ir_mode *mode)
-{
- size_t i, n = ir_get_n_modes();
-
- for (i = 0; i < n; ++i) {
- if (ir_get_mode(i) == mode)
- return i;
- }
- /* should really not happen */
- panic("could not find index of mode");
-}
-
-/**
- * Encodes an IR-node, recursive worker.
- *
- * @return reached depth
- */
-static int _encode_node(ir_node *node, int max_depth, codec_env_t *env)
-{
- addr_entry_t entry, *r_entry;
- set_entry *s_entry;
- int res, depth;
-
- unsigned code = get_irn_opcode(node);
-
- /* insert the node into our ID map */
- entry.addr = node;
- entry.id = env->curr_id;
-
- s_entry = set_hinsert(env->id_set, &entry, sizeof(entry), hash_ptr(node));
- r_entry = (addr_entry_t *)s_entry->dptr;
-
- if (r_entry->id != env->curr_id) {
- /* already in the map, add an REF */
- put_tag(env->buf, VLC_TAG_REF);
- put_code(env->buf, r_entry->id);
-
- return max_depth;
- } else {
- /* a new entry, proceed */
- ++env->curr_id;
- }
-
- put_code(env->buf, (unsigned)code);
-
- /* do we need the mode ? */
- if (env->options & OPT_WITH_MODE) {
- ir_mode *mode = get_irn_mode(node);
-
- if (mode)
- put_code(env->buf, find_mode_index(mode));
- else
- put_tag(env->buf, VLC_TAG_EMPTY);
- }
-
- /* do we need integer constants */
- if (env->options & OPT_WITH_ICONST) {
- if (code == iro_Const) {
- ir_tarval *tv = get_Const_tarval(node);
-
- if (tarval_is_long(tv)) {
- long v = get_tarval_long(tv);
-
- put_tag(env->buf, VLC_TAG_ICONST);
- put_code(env->buf, v);
- }
- }
- }
-
- --max_depth;
-
- if (max_depth <= 0) {
- put_code(env->buf, 0);
- return max_depth;
- }
-
- int const preds = get_irn_arity(node);
- put_code(env->buf, preds);
-
- res = INT_MAX;
- if (is_op_commutative(get_irn_op(node))) {
- ir_node *l = get_binop_left(node);
- ir_node *r = get_binop_right(node);
- int opcode_diff = (int)get_irn_opcode(l) - (int)get_irn_opcode(r);
-
- if (opcode_diff > 0) {
- ir_node *t = l;
- l = r;
- r = t;
- } else if (opcode_diff == 0 && l != r) {
- /* Both nodes have the same opcode, but are different.
- Need a better method here to decide which goes to the left side. */
- }
-
- /* special handling for commutative operators */
- depth = _encode_node(l, max_depth, env);
- if (depth < res)
- res = depth;
- depth = _encode_node(r, max_depth, env);
- if (depth < res)
- res = depth;
- } else {
- foreach_irn_in(node, i, n) {
- depth = _encode_node(n, max_depth, env);
- if (depth < res)
- res = depth;
- }
- }
- return res;
-}
-
-/**
- * Encode a DAG starting by the IR-node node.
- *
- * @param node The root node of the graph
- * @param buf The code buffer to store the bitstring in
- * @param max_depth The maximum depth for descending
- *
- * @return The depth of the encoded graph (without cycles)
- */
-static int encode_node(ir_node *node, CODE_BUFFER *buf, int max_depth)
-{
- codec_env_t env;
- int res;
-
- /* initialize the encoder environment */
- env.buf = buf;
- env.curr_id = 1; /* 0 is used for special purpose */
- env.options = status->options;
- env.dmp = NULL;
-
- if (env.options & OPT_ENC_DAG)
- env.id_set = new_set(addr_cmp, 32);
- else
- env.id_set = NULL;
-
- /* encode options if any for the decoder */
- if (env.options) {
- put_tag(buf, VLC_TAG_OPTION);
- put_code(buf, env.options);
- }
-
- res = _encode_node(node, max_depth, &env);
-
- if (env.id_set != NULL)
- del_set(env.id_set);
-
- return max_depth - res;
-}
-
-/**
- * Decode an IR-node, recursive walker.
- */
-static void _decode_node(unsigned parent, int position, codec_env_t *env)
-{
- unsigned code;
- unsigned op_code;
- unsigned mode_code = 0;
- long iconst;
- void *attr = NULL;
-
- code = next_tag(env->buf);
- if (code == VLC_TAG_REF) { /* it's a REF */
- code = get_code(env->buf);
-
- /* dump the edge */
- if (parent) {
- int edge_mode = 0;
- /*
- * the mode of a Firm edge can be either computed from its target or
- * from its source and position. We must take the second approach because
- * we don't know the target here, it's a ref.
- */
- pattern_dump_edge(env->dmp, code, parent, position, edge_mode);
- }
-
- /* dump the node ref */
- pattern_dump_ref(env->dmp, code);
-
- return;
- }
-
- /* get the opcode */
- op_code = get_code(env->buf);
-
- /* get the mode if encoded */
- if (env->options & OPT_WITH_MODE) {
- if (next_tag(env->buf) != VLC_TAG_EMPTY) {
- mode_code = get_code(env->buf);
- }
- }
-
- /* check, if a ICONST attribute is given */
- if (next_tag(env->buf) == VLC_TAG_ICONST) {
- iconst = get_code(env->buf);
- attr = &iconst;
- }
-
- /* dump the edge */
- if (parent) {
- int edge_mode = 0;
-
- /*
- * the mode of a Firm edge can be either computed from its target or
- * from its source and position. We take the second approach because
- * we need it anyway for ref's.
- */
- pattern_dump_edge(env->dmp, env->curr_id, parent, position, edge_mode);
- }
-
- /* dump the node */
- parent = env->curr_id;
- pattern_dump_node(env->dmp, parent, op_code, mode_code, attr);
-
- /* ok, we have a new ID */
- ++env->curr_id;
-
- code = next_tag(env->buf);
- if (code != VLC_TAG_END) {
- /* more info, do recursion */
- int i, preds;
-
- preds = get_code(env->buf);
- if (preds > 0) {
- pattern_start_children(env->dmp, parent);
- for (i = 0; i < preds; ++i) {
- _decode_node(parent, i, env);
- }
- pattern_finish_children(env->dmp, parent);
- }
- }
-}
-
-/**
- * Decode an IR-node.
- */
-static void decode_node(BYTE *b, size_t len, pattern_dumper_t *dump)
-{
- codec_env_t env;
- CODE_BUFFER buf;
- unsigned code, options = 0;
-
- init_buf(&buf, b, len);
-
- env.buf = &buf;
- env.curr_id = 1; /* 0 is used for special purpose */
- env.dmp = dump;
-
- /* decode options */
- code = next_tag(&buf);
- if (code == VLC_TAG_OPTION) {
- options = get_code(&buf);
- }
- env.options = options;
-
- _decode_node(0, 0, &env);
-}
-
-/**
- * The environment for the pattern calculation.
- */
-typedef struct pattern_env {
- int max_depth; /**< maximum depth for pattern generation. */
-} pattern_env_t;
-
-/**
- * Returns the associates pattern_entry_t for a CODE_BUF.
- *
- * @param buf the code buffer
- * @param set the hash table containing all pattern entries
- *
- * @return the associated pattern_entry_t for the given code buffer
- *
- * If the code content was never seen before, a new pattern_entry is created
- * and returned.
- */
-static pattern_entry_t *pattern_get_entry(CODE_BUFFER *buf, pset *set)
-{
- pattern_entry_t *key, *elem;
- size_t len = buf_lenght(buf);
- unsigned hash;
-
- key = OALLOCF(&status->obst, pattern_entry_t, buf, len);
- key->len = len;
- memcpy(key->buf, buf_content(buf), len);
-
- hash = buf_hash(buf);
-
- elem = (pattern_entry_t*)pset_find(set, key, hash);
- if (elem != NULL) {
- obstack_free(&status->obst, key);
- return elem;
- }
-
- cnt_clr(&key->count);
- return (pattern_entry_t*)pset_insert(set, key, hash);
-}
-
-/**
- * Increase the count for a pattern.
- *
- * @param buf the code buffer containing the pattern
- * @param depth the pattern depth
- *
- * @note Single node patterns are ignored
- */
-static void count_pattern(CODE_BUFFER *buf, int depth)
-{
- pattern_entry_t *entry;
-
- /* ignore single node pattern (i.e. constants) */
- if (depth > 1) {
- entry = pattern_get_entry(buf, status->pattern_hash);
-
- /* increase count */
- cnt_inc(&entry->count);
- }
-}
-
-/**
- * Pre-walker for nodes pattern calculation.
- */
-static void calc_nodes_pattern(ir_node *node, void *ctx)
-{
- pattern_env_t *env = (pattern_env_t*)ctx;
- BYTE buffer[PATTERN_STORE_SIZE];
- CODE_BUFFER buf;
- int depth;
-
- init_buf(&buf, buffer, sizeof(buffer));
- depth = encode_node(node, &buf, env->max_depth);
-
- if (buf_overrun(&buf)) {
- fprintf(stderr, "Pattern store: buffer overrun at size %zu. Pattern ignored.\n", sizeof(buffer));
- } else
- count_pattern(&buf, depth);
-}
-
-/**
- * Store all collected patterns.
- *
- * @param fname filename for storage
- */
-static void store_pattern(const char *fname)
-{
- FILE *f;
- size_t count = pset_count(status->pattern_hash);
-
- if (count <= 0)
- return;
-
- f = fopen(fname, "wb");
- if (! f) {
- perror(fname);
- return;
- }
-
- fwrite("FPS1", 4, 1, f);
- fwrite(&count, sizeof(count), 1, f);
-
- foreach_pset(status->pattern_hash, pattern_entry_t, entry) {
- fwrite(entry, offsetof(pattern_entry_t, buf) + entry->len, 1, f);
- }
- fclose(f);
-}
-
-/**
- * Read collected patterns from a file.
- *
- * @param fname filename
- */
-static HASH_MAP(pattern_entry_t) *read_pattern(const char *fname)
-{
- FILE *f;
- pattern_entry_t *entry, tmp;
- size_t i, count;
- unsigned j;
- char magic[4];
- HASH_MAP(pattern_entry_t) *pattern_hash = new_pset(pattern_cmp, 8);
- BYTE buffer[PATTERN_STORE_SIZE];
- CODE_BUFFER buf;
- int res;
-
- f = fopen(fname, "rb");
- if (! f) {
- perror(fname);
- return NULL;
- }
-
- res = fread(magic, 4, 1, f);
- if (res != 1)
- goto read_error;
- count = 0;
- res = fread(&count, sizeof(count), 1, f);
- if (res != 1 || memcmp(magic, "FPS1", 4) != 0 || count <= 0)
- goto read_error;
-
- /* read all pattern entries and put them into the hash table. */
- for (i = 0; i < count; ++i) {
- init_buf(&buf, buffer, sizeof(buffer));
- res = fread(&tmp, offsetof(pattern_entry_t, buf), 1, f);
- if (res != 1)
- goto read_error;
- for (j = 0; j < tmp.len; ++j)
- put_byte(&buf, fgetc(f));
- entry = pattern_get_entry(&buf, pattern_hash);
- entry->count = tmp.count;
- }
- fclose(f);
-
- printf("Read %zu pattern from %s\n", count, fname);
- assert(pset_count(pattern_hash) == count);
-
- return pattern_hash;
-
-read_error:
- fprintf(stderr, "Error: %s is not a Firm pattern store. Ignored.\n", fname);
- fclose(f);
- return NULL;
-}
-
-/**
- * Write the collected patterns to a VCG file for inspection.
- *
- * @param fname name of the VCG file to create
- */
-static void pattern_output(const char *fname)
-{
- pattern_entry_t **pattern_arr;
- pattern_dumper_t *dump;
- size_t i, count = pset_count(status->pattern_hash);
-
- printf("\n%zu pattern detected\n", count);
-
- if (count == 0)
- return;
-
- /* creates a dumper */
- dump = new_vcg_dumper(fname, 100);
-
- pattern_arr = XMALLOCN(pattern_entry_t*, count);
- i = 0;
- foreach_pset(status->pattern_hash, pattern_entry_t, entry) {
- pattern_arr[i++] = entry;
- }
- assert(count == i);
- count = i;
-
- /* sort it */
- QSORT(pattern_arr, count, pattern_count_cmp);
-
- for (i = 0; i < count; ++i) {
- pattern_entry_t *const entry = pattern_arr[i];
- if (cnt_to_uint(&entry->count) < status->bound)
- continue;
-
- /* dump a pattern */
- pattern_dump_new_pattern(dump, &entry->count);
- decode_node(entry->buf, entry->len, dump);
- pattern_dump_finish_pattern(dump);
- }
-
- /* destroy it */
- pattern_end(dump);
-}
-
-/*
- * Calculates the pattern history.
- */
-void stat_calc_pattern_history(ir_graph *irg)
-{
- pattern_env_t env;
- unsigned i;
-
- if (! status->enable)
- return;
-
- /* do NOT count the const code IRG */
- if (irg == get_const_code_irg())
- return;
-
- for (i = status->min_depth; i <= status->max_depth; ++i) {
- env.max_depth = i;
- irg_walk_graph(irg, calc_nodes_pattern, NULL, &env);
- }
-}
-
-/*
- * Initializes the pattern history.
- */
-void stat_init_pattern_history(int enable)
-{
- HASH_MAP(pattern_entry_t) *pattern_hash = NULL;
-
- status->enable = enable;
- if (! enable)
- return;
-
- status->bound = 10;
- status->options = /* OPT_WITH_MODE | */ OPT_ENC_DAG | OPT_WITH_ICONST | OPT_PERSIST_PATTERN;
- status->min_depth = 3;
- status->max_depth = 5;
-
- obstack_init(&status->obst);
-
- /* create the hash-table */
- if (status->options & OPT_PERSIST_PATTERN)
- pattern_hash = read_pattern("pattern.fps");
- if (pattern_hash == NULL)
- pattern_hash = new_pset(pattern_cmp, 8);
- status->pattern_hash = pattern_hash;
-}
-
-/*
- * Finish the pattern history.
- */
-void stat_finish_pattern_history(const char *fname)
-{
- (void) fname;
- if (! status->enable)
- return;
-
- store_pattern("pattern.fps");
- pattern_output("pattern.vcg");
-
- del_pset(status->pattern_hash);
- obstack_free(&status->obst, NULL);
-
- status->enable = 0;
-}
diff --git a/ir/stat/pattern.h b/ir/stat/pattern.h
deleted file mode 100644
index 2b60054..0000000
--- a/ir/stat/pattern.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * This file is part of libFirm.
- * Copyright (C) 2012 University of Karlsruhe.
- */
-
-/**
- * @file
- * @brief Statistics for Firm. Pattern history.
- * @author Michael Beck
- */
-#ifndef FIRM_STAT_PATTERN_H
-#define FIRM_STAT_PATTERN_H
-
-#include "firm_types.h"
-
-/**
- * Calculates the pattern history.
- *
- * @param irg The IR-graph
- */
-void stat_calc_pattern_history(ir_graph *irg);
-
-/**
- * Initializes the pattern history.
- *
- * @param enable Enable flag.
- */
-void stat_init_pattern_history(int enable);
-
-/**
- * Finish the pattern history.
- */
-void stat_finish_pattern_history(const char *fname);
-
-#endif
diff --git a/ir/stat/pattern_dmp.c b/ir/stat/pattern_dmp.c
deleted file mode 100644
index 29a542a..0000000
--- a/ir/stat/pattern_dmp.c
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * This file is part of libFirm.
- * Copyright (C) 2012 University of Karlsruhe.
- */
-
-/**
- * @file
- * @brief Statistics for Firm. Dumping patterns.
- * @author Michael Beck
- */
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "ident.h"
-#include "irop_t.h"
-#include "irmode_t.h"
-#include "firmstat_t.h"
-#include "pattern_dmp.h"
-
-/* dumper operations */
-typedef void (*DUMP_NEW_PATTERN_FUNC)(pattern_dumper_t *self, counter_t *cnt);
-typedef void (*DUMP_FINISH_PATTERN_FUNC)(pattern_dumper_t *self);
-typedef void (*DUMP_NODE_FUNC)(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr);
-typedef void (*DUMP_REF_FUNC)(pattern_dumper_t *self, unsigned id);
-typedef void (*DUMP_EDGE_FUNC)(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code);
-typedef void (*DUMP_START_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
-typedef void (*DUMP_FINISH_CHILDREN_FUNC)(pattern_dumper_t *self, unsigned id);
-typedef void (*DUMP_START_FUNC)(pattern_dumper_t *self);
-typedef void (*DUMP_END_FUNC)(pattern_dumper_t *self);
-
-/**
- * the pattern dumper
- */
-struct pattern_dumper_t {
- DUMP_NEW_PATTERN_FUNC dump_new_pattern;
- DUMP_FINISH_PATTERN_FUNC dump_finish_pattern;
- DUMP_NODE_FUNC dump_node;
- DUMP_REF_FUNC dump_ref;
- DUMP_EDGE_FUNC dump_edge;
- DUMP_START_CHILDREN_FUNC dump_start_children;
- DUMP_FINISH_CHILDREN_FUNC dump_finish_children;
- DUMP_START_FUNC dump_start;
- DUMP_END_FUNC dump_end;
- void *data;
-};
-
-/**
- * VCG private data
- */
-typedef struct vcg_private_t {
- FILE *f; /**< file to dump to */
- unsigned pattern_id; /**< ID of the pattern */
- unsigned max_pattern; /**< maximum number of pattern to be dumped */
-} vcg_private_t;
-
-/**
- * Starts a new VCG graph.
- */
-static void vcg_dump_start(pattern_dumper_t *self)
-{
- vcg_private_t *priv = (vcg_private_t*)self->data;
-
- fprintf(priv->f,
- "graph: { title: \"Most found pattern\"\n"
- " display_edge_labels: no\n"
- " layoutalgorithm: mindepth\n"
- " manhattan_edges: yes\n"
- " port_sharing: no\n"
- " orientation: bottom_to_top\n"
- );
-}
-
-/**
- * Ends a new VCG graph.
- */
-static void vcg_dump_end(pattern_dumper_t *self)
-{
- vcg_private_t *priv = (vcg_private_t*)self->data;
-
- fprintf(priv->f, "}\n");
- fclose(priv->f);
-}
-
-/**
- * Starts a new pattern.
- */
-static void vcg_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
-{
- vcg_private_t *priv = (vcg_private_t*)self->data;
- static unsigned nr = 0;
-
- if (priv->pattern_id > priv->max_pattern)
- return;
-
- fprintf(priv->f,
- " graph: { title: \"g%u\" label: \"pattern %u\" status:clustered color:yellow\n",
- priv->pattern_id, priv->pattern_id );
-
- /* add a pseudo node for the count of this pattern */
- fprintf(priv->f,
- " node: {title: \"c%u\" label: \"cnt: %u\" color:red }\n",
- ++nr, cnt_to_uint(cnt)
- );
-}
-
-/**
- * Finish the current pattern.
- */
-static void vcg_dump_finish_pattern(pattern_dumper_t *self)
-{
- vcg_private_t *priv = (vcg_private_t*)self->data;
-
- if (priv->pattern_id > priv->max_pattern)
- return;
-
- fprintf(priv->f, " }\n");
-
- if (priv->pattern_id > 0)
- fprintf(priv->f, " edge: { sourcename: \"g%u\" targetname: \"g%u\" linestyle:invisible}\n",
- priv->pattern_id,
- priv->pattern_id - 1);
-
- ++priv->pattern_id;
-}
-
-/**
- * Dumps a node.
- */
-static void vcg_dump_node(pattern_dumper_t *self, unsigned id,
- unsigned op_code, unsigned mode_code, void *attr)
-{
- vcg_private_t *priv = (vcg_private_t*)self->data;
- ir_op *op = stat_get_op_from_opcode(op_code);
- ir_mode *mode = ir_get_mode(mode_code);
- long l = attr ? *(long *)attr : 0;
-
- if (priv->pattern_id > priv->max_pattern)
- return;
-
- if (attr) {
- fprintf(priv->f, " node: {title: \"n%u_%u\" label: \"%s%s %ld n%u\" }\n",
- priv->pattern_id, id, get_id_str(op->name), mode ? get_mode_name(mode) : "", l, id);
- } else {
- fprintf(priv->f, " node: {title: \"n%u_%u\" label: \"%s%s n%u\" }\n",
- priv->pattern_id, id, get_id_str(op->name), mode ? get_mode_name(mode) : "", id);
- }
-}
-
-/**
- * Dumps an edge.
- */
-static void vcg_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
-{
- vcg_private_t *priv = (vcg_private_t*)self->data;
- (void) mode_code;
-
- if (priv->pattern_id > priv->max_pattern)
- return;
-
- fprintf(priv->f, " edge: { sourcename: \"n%u_%u\" targetname: \"n%u_%u\" label: \"%u\" }\n",
- priv->pattern_id, src,
- priv->pattern_id, tgt,
- pos
- );
-}
-
-/**
- * The VCG dumper.
- */
-static pattern_dumper_t vcg_dump = {
- vcg_dump_new_pattern,
- vcg_dump_finish_pattern,
- vcg_dump_node,
- NULL,
- vcg_dump_edge,
- NULL,
- NULL,
- vcg_dump_start,
- vcg_dump_end,
- NULL
-};
-
-/**
- * Starts a new pattern.
- */
-static void stdout_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
-{
- FILE *f = (FILE*)self->data;
-
- fprintf(f, "%8u ", cnt_to_uint(cnt));
-}
-
-
-/**
- * Finish the current pattern.
- */
-static void stdout_dump_finish_pattern(pattern_dumper_t *self)
-{
- FILE *f = (FILE*)self->data;
-
- fprintf(f, "\n");
-}
-
-/**
- * Dumps a node.
- */
-static void stdout_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
-{
- FILE *f = (FILE*)self->data;
- ir_op *op = stat_get_op_from_opcode(op_code);
- ir_mode *mode = ir_get_mode(mode_code);
- (void) attr;
-
- /* if (env->options & OPT_ENC_GRAPH) */
- fprintf(f, "%u:", id);
-
- fprintf(f, "%s", get_id_str(op->name));
-
- if (mode)
- fprintf(f, "%s", get_mode_name(mode));
-}
-
-/**
- * Dump a ref
- */
-static void stdout_dump_ref(pattern_dumper_t *self, unsigned id)
-{
- FILE *f = (FILE*)self->data;
-
- fprintf(f, "REF:%u", id);
-}
-
-/**
- * Dump an edge.
- */
-static void stdout_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
-{
- FILE *f = (FILE*)self->data;
- (void) tgt;
- (void) src;
- (void) pos;
- (void) mode_code;
-
- if (pos > 0)
- fprintf(f, ", ");
-}
-
-/**
- * Start the children dumper.
- */
-static void stdout_start_children(pattern_dumper_t *self, unsigned id)
-{
- FILE *f = (FILE*)self->data;
- (void) id;
-
- fprintf(f, "(");
-}
-
-/**
- * Finish the children dumper.
- */
-static void stdout_finish_children(pattern_dumper_t *self, unsigned id)
-{
- FILE *f = (FILE*)self->data;
- (void) id;
-
- fprintf(f, ")");
-}
-
-/**
- * The stdout dumper.
- */
-static const pattern_dumper_t stdout_dump = {
- stdout_dump_new_pattern,
- stdout_dump_finish_pattern,
- stdout_dump_node,
- stdout_dump_ref,
- stdout_dump_edge,
- stdout_start_children,
- stdout_finish_children,
- NULL,
- NULL,
- NULL
-};
-
-/* ------------------------------------ API ------------------------------------- */
-
-/*
- * Starts a new pattern.
- */
-void pattern_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt)
-{
- if (self->dump_new_pattern)
- self->dump_new_pattern(self, cnt);
-}
-
-
-/*
- * Finish the current pattern.
- */
-void pattern_dump_finish_pattern(pattern_dumper_t *self)
-{
- if (self->dump_finish_pattern)
- self->dump_finish_pattern(self);
-}
-
-
-/*
- * Dumps a node.
- */
-void pattern_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr)
-{
- if (self->dump_node)
- self->dump_node(self, id, op_code, mode_code, attr);
-}
-
-/*
- * Dump a ref.
- */
-void pattern_dump_ref(pattern_dumper_t *self, unsigned id)
-{
- if (self->dump_ref)
- self->dump_ref(self, id);
-}
-
-/*
- * Dump an edge.
- */
-void pattern_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code)
-{
- if (self->dump_edge)
- self->dump_edge(self, tgt, src, pos, mode_code);
-}
-
-/*
- * Start the children dumper.
- */
-void pattern_start_children(pattern_dumper_t *self, unsigned id)
-{
- if (self->dump_start_children)
- self->dump_start_children(self, id);
-}
-
-/*
- * Finish the the children dumper.
- */
-void pattern_finish_children(pattern_dumper_t *self, unsigned id)
-{
- if (self->dump_finish_children)
- self->dump_finish_children(self, id);
-}
-
-/*
- * Finish the the dumper.
- */
-void pattern_end(pattern_dumper_t *self)
-{
- if (self->dump_end)
- self->dump_end(self);
-
- free(self);
-}
-
-/**
- * pattern dumper factory for text dumper
- */
-pattern_dumper_t *new_text_dumper(void)
-{
- pattern_dumper_t *res = XMALLOC(pattern_dumper_t);
-
- *res = stdout_dump;
- res->data = stdout;
-
- if (res->dump_start)
- res->dump_start(res);
- return res;
-}
-
-/**
- * pattern dumper factory for vcg dumper
- */
-pattern_dumper_t *new_vcg_dumper(const char *vcg_name, unsigned max_pattern)
-{
- pattern_dumper_t *res = (pattern_dumper_t*)malloc(sizeof(*res) + sizeof(vcg_private_t));
- vcg_private_t *priv;
-
- if (res) {
- FILE *f;
-
- *res = vcg_dump;
-
- priv = (vcg_private_t *)(res + 1);
- memset(priv, 0, sizeof(*priv));
-
- f = fopen(vcg_name, "w");
- priv->f = f;
- priv->pattern_id = 0;
- priv->max_pattern = max_pattern ? max_pattern : (unsigned)-1;
- res->data = priv;
-
- if (res->dump_start)
- res->dump_start(res);
- }
-
- return res;
-}
diff --git a/ir/stat/pattern_dmp.h b/ir/stat/pattern_dmp.h
deleted file mode 100644
index 9c434f6..0000000
--- a/ir/stat/pattern_dmp.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * This file is part of libFirm.
- * Copyright (C) 2012 University of Karlsruhe.
- */
-
-/**
- * @file
- * @brief Statistics for Firm. Dumping patterns.
- * @author Michael Beck
- */
-#ifndef FIRM_STAT_PATTERN_DMP_H
-#define FIRM_STAT_PATTERN_DMP_H
-
-#include "counter.h"
-
-typedef struct pattern_dumper_t pattern_dumper_t;
-
-/**
- * Starts a new pattern.
- */
-void pattern_dump_new_pattern(pattern_dumper_t *self, counter_t *cnt);
-
-/**
- * Finish the current pattern.
- */
-void pattern_dump_finish_pattern(pattern_dumper_t *self);
-
-/**
- * Dumps a node.
- */
-void pattern_dump_node(pattern_dumper_t *self, unsigned id, unsigned op_code, unsigned mode_code, void *attr);
-
-/**
- * Dump a ref.
- */
-void pattern_dump_ref(pattern_dumper_t *self, unsigned id);
-
-/**
- * Dump an edge.
- *
- * @param tgt The target ID
- * @param src The source ID
- * @param pos The edge position
- * @param mode_code The mode_code of the edge
- */
-void pattern_dump_edge(pattern_dumper_t *self, unsigned tgt, unsigned src, unsigned pos, unsigned mode_code);
-
-/**
- * Start the children dumper.
- */
-void pattern_start_children(pattern_dumper_t *self, unsigned id);
-
-/**
- * Finish the children dumper.
- */
-void pattern_finish_children(pattern_dumper_t *self, unsigned id);
-
-/**
- * Finish the dumper, destroys the dumper object
- */
-void pattern_end(pattern_dumper_t *self);
-
-/**
- * Pattern dumper factory for text dumper.
- */
-pattern_dumper_t *new_text_dumper(void);
-
-/**
- * Pattern dumper factory for vcg dumper.
- *
- * @param vcg_name name of the VCG file
- * @param max_pattern maximum number of pattern to be dumped
- */
-pattern_dumper_t *new_vcg_dumper(const char *vcg_name, unsigned max_pattern);
-
-#endif
diff --git a/ir/stat/stat_dmp.c b/ir/stat/stat_dmp.c
deleted file mode 100644
index 81cbfe9..0000000
--- a/ir/stat/stat_dmp.c
+++ /dev/null
@@ -1,663 +0,0 @@
-/*
- * This file is part of libFirm.
- * Copyright (C) 2012 University of Karlsruhe.
- */
-
-/**
- * @file
- * @brief Statistics for Firm. Dumping.
- * @author Michael Beck
- */
-#include "stat_dmp.h"
-#include "irhooks.h"
-#include "util.h"
-#include "fourcc.h"
-
-/**
- * names of the optimizations
- */
-static const struct {
- hook_opt_kind kind;
- const char *name;
-} opt_names[] = {
- { HOOK_OPT_DEAD_BLOCK, "dead block elimination" },
- { HOOK_OPT_STG, "straightening optimization" },
- { HOOK_OPT_IFSIM, "if simplification" },
- { HOOK_OPT_CONST_EVAL, "constant evaluation" },
- { HOOK_OPT_ALGSIM, "algebraic simplification" },
- { HOOK_OPT_PHI, "Phi optmization" },
- { HOOK_OPT_SYNC, "Sync optmization" },
- { HOOK_OPT_WAW, "Write-After-Write optimization" },
- { HOOK_OPT_WAR, "Write-After-Read optimization" },
- { HOOK_OPT_RAW, "Read-After-Write optimization" },
- { HOOK_OPT_RAR, "Read-After-Read optimization" },
- { HOOK_OPT_RC, "Read-a-Const optimization" },
- { HOOK_OPT_TUPLE, "Tuple optimization" },
- { HOOK_OPT_ID, "ID optimization" },
- { HOOK_OPT_CSE, "Common subexpression elimination" },
- { HOOK_OPT_STRENGTH_RED, "Strength reduction" },
- { HOOK_OPT_ARCH_DEP, "Architecture dependant optimization" },
- { HOOK_OPT_REASSOC, "Reassociation optimization" },
- { HOOK_OPT_POLY_CALL, "Polymorphic call optimization" },
- { HOOK_OPT_IF_CONV, "an if conversion was tried" },
- { HOOK_OPT_FUNC_CALL, "Real function call optimization" },
- { HOOK_OPT_CONFIRM, "Confirm-based optimization: replacement" },
- { HOOK_OPT_CONFIRM_C, "Confirm-based optimization: replaced by const" },
- { HOOK_OPT_CONFIRM_E, "Confirm-based optimization: evaluated" },
- { HOOK_OPT_EXC_REM, "a exception edge was removed due to a Confirmation prove" },
- { HOOK_OPT_NORMALIZE, "a commutative node was normalized" },
- { HOOK_LOWERED, "Lowered" },
- { HOOK_BACKEND, "Backend transformation" },
- { (hook_opt_kind)FS_OPT_NEUTRAL_0, "algebraic simplification: a op 0 = 0 op a = a" },
- { (hook_opt_kind)FS_OPT_NEUTRAL_1, "algebraic simplification: a op 1 = 1 op a = a" },
- { (hook_opt_kind)FS_OPT_ADD_A_A, "algebraic simplification: a + a = a * 2" },
- { (hook_opt_kind)FS_OPT_ADD_A_MINUS_B, "algebraic simplification: a + -b = a - b" },
- { (hook_opt_kind)FS_OPT_ADD_SUB, "algebraic simplification: (a + x) - x = (a - x) + x = a" },
- { (hook_opt_kind)FS_OPT_ADD_MUL_A_X_A, "algebraic simplification: a * x + a = a * (x + 1)" },
- { (hook_opt_kind)FS_OPT_SUB_0_A, "algebraic simplification: 0 - a = -a" },
- { (hook_opt_kind)FS_OPT_MINUS_SUB, "algebraic simplification: -(a - b) = b - a" },
- { (hook_opt_kind)FS_OPT_SUB_MINUS, "algebraic simplification: a - (-b) = a + b" },
- { (hook_opt_kind)FS_OPT_SUB_MUL_A_X_A, "algebraic simplification: a * x - a = a * (x - 1)" },
- { (hook_opt_kind)FS_OPT_SUB_SUB_X_Y_Z, "algebraic simplification: (x - y) - z = x - (y + z)" },
- { (hook_opt_kind)FS_OPT_SUB_C_NOT_X, "algebraic simplification: c - ~a = a + (c+1)" },
- { (hook_opt_kind)FS_OPT_SUB_TO_ADD, "algebraic simplification: (-a) - b = -(a + b), a - (b - c) = a + (c - b), a - (b * C) = a + (b * -C)" },
- { (hook_opt_kind)FS_OPT_SUB_TO_NOT, "algebraic simplification: -1 - x -> ~x" },
- { (hook_opt_kind)FS_OPT_SUB_TO_CONV, "algebraic simplification: a - NULL = (int)a" },
- { (hook_opt_kind)FS_OPT_MUL_MINUS, "algebraic simplification: (-a) * (b - c) = a * (c - b)" },
- { (hook_opt_kind)FS_OPT_MUL_MINUS_1, "algebraic simplification: a * -1 = -a" },
- { (hook_opt_kind)FS_OPT_MINUS_MUL_C, "algebraic simplification: (-a) * C = a * (-C)" },
- { (hook_opt_kind)FS_OPT_MUL_MINUS_MINUS,"algebraic simplification: (-a) * (-b) = a * b" },
- { (hook_opt_kind)FS_OPT_OR, "algebraic simplification: a | a = a | 0 = 0 | a = a" },
- { (hook_opt_kind)FS_OPT_AND, "algebraic simplification: a & 0b1...1 = 0b1...1 & a = a & a = (a|X) & a = a" },
- { (hook_opt_kind)FS_OPT_TO_EOR, "algebraic simplification: (a|b) & ~(a&b) = a^b" },
- { (hook_opt_kind)FS_OPT_EOR_A_A, "algebraic simplification: a ^ a = 0" },
- { (hook_opt_kind)FS_OPT_EOR_A_B_A, "algebraic simplification: (a ^ b) ^ a = b" },
- { (hook_opt_kind)FS_OPT_EOR_TO_NOT_BOOL,"boolean simplification: bool ^ 1 = !bool" },
- { (hook_opt_kind)FS_OPT_EOR_TO_NOT, "algebraic simplification: x ^ 0b1..1 = ~x, (a ^ b) & b = ~a & b" },
- { (hook_opt_kind)FS_OPT_NOT_CMP, "algebraic simplification: !(a cmp b) = a !cmp b" },
- { (hook_opt_kind)FS_OPT_REASSOC_SHIFT, "algebraic simplification: (x SHF c1) SHF c2 = x SHF (c1+c2)" },
- { (hook_opt_kind)FS_OPT_SHIFT_AND, "algebraic simplification: (a SHF c) AND (b SHF c) = (a AND b) SHF c" },
- { (hook_opt_kind)FS_OPT_SHIFT_OR, "algebraic simplification: (a SHF c) OR (b SHF c) = (a OR b) SHF c" },
- { (hook_opt_kind)FS_OPT_SHIFT_EOR, "algebraic simplification: (a SHF c) XOR (b SHF c) = (a XOR b) SHF c" },
- { (hook_opt_kind)FS_OPT_CONV, "algebraic simplification: Conv could be removed" },
- { (hook_opt_kind)FS_OPT_MIN_MAX_EQ, "algebraic simplification: Min(a,a) = Max(a,a) = a" },
- { (hook_opt_kind)FS_OPT_MUX_COMBINE, "boolean simplification: two Mux nodes where combined into one" },
- { (hook_opt_kind)FS_OPT_MUX_CONV, "boolean simplification: MuxI(sel, 1, 0) = (I)sel" },
- { (hook_opt_kind)FS_OPT_MUX_BOOL, "boolean simplification: Muxb(sel, true, false) = sel" },
- { (hook_opt_kind)FS_OPT_MUX_NOT_BOOL, "boolean simplification: Muxb(sel, false, true) = Not(sel)" },
- { (hook_opt_kind)FS_OPT_MUX_OR_BOOL, "boolean simplification: Muxb(sel, true, x) = Or(sel, x)" },
- { (hook_opt_kind)FS_OPT_MUX_ORNOT_BOOL, "boolean simplification: Muxb(sel, x, true) = Or(Not(sel), x)" },
- { (hook_opt_kind)FS_OPT_MUX_AND_BOOL, "boolean simplification: Muxb(sel, x, false) = And(sel, x)" },
- { (hook_opt_kind)FS_OPT_MUX_ANDNOT_BOOL,"boolean simplification: Muxb(sel, false, x) = And(Not(sel), x)" },
- { (hook_opt_kind)FS_OPT_MUX_C, "algebraic simplification: Mux(C, f, t) = C ? t : f" },
- { (hook_opt_kind)FS_OPT_MUX_EQ, "algebraic simplification: Mux(v, x, x) = x" },
- { (hook_opt_kind)FS_OPT_MUX_TRANSFORM, "algebraic simplification: Mux(t ==/!= f, t, f) = f/t, Mux(t ==/!= 0, -t, t) = -t/t" },
- { (hook_opt_kind)FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
- { (hook_opt_kind)FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
- { (hook_opt_kind)FS_OPT_MUX_TO_BITOP, "algebraic simplification: Mux((a & 2^x) ==/!= 0, 2^x, 0) = (a & 2^x) (xor 2^x)" },
- { (hook_opt_kind)FS_OPT_INVOLUTION, "algebraic simplification: OP(OP(x)) = x" },
- { (hook_opt_kind)FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
- { (hook_opt_kind)FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
- { (hook_opt_kind)FS_OPT_NOT_PLUS_C, "algebraic simplification: ~x + C = (C - 1) - x" },
- { (hook_opt_kind)FS_OPT_ADD_X_NOT_X, "algebraic simplification: ~x + x = -1" },
- { (hook_opt_kind)FS_OPT_FP_INV_MUL, "algebraic simplification: x / y = x * (1.0/y)" },
- { (hook_opt_kind)FS_OPT_CONST_PHI, "constant evaluation on Phi node" },
- { (hook_opt_kind)FS_OPT_PREDICATE, "predicate optimization" },
- { (hook_opt_kind)FS_OPT_DEMORGAN, "optimization using DeMorgan's law" },
- { (hook_opt_kind)FS_OPT_CMP_OP_OP, "CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y)" },
- { (hook_opt_kind)FS_OPT_CMP_OP_C, "CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2)" },
- { (hook_opt_kind)FS_OPT_CMP_CONV_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y)" },
- { (hook_opt_kind)FS_OPT_CMP_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y)" },
- { (hook_opt_kind)FS_OPT_CMP_TO_BOOL, "CMP optimization: Cmp(x, y) = BoolOP(x, y)" },
- { (hook_opt_kind)FS_OPT_CMP_CNST_MAGN, "CMP optimization: reduced magnitude of a const" },
- { (hook_opt_kind)FS_OPT_CMP_SHF_TO_AND, "CMP optimization: transformed shift into And" },
- { (hook_opt_kind)FS_OPT_CMP_MOD_TO_AND, "CMP optimization: transformed Mod into And" },
- { (hook_opt_kind)FS_OPT_NOP, "the operation is a NOP" },
- { (hook_opt_kind)FS_OPT_GVN_FOLLOWER, "GVN-PRE: replaced a follower" },
- { (hook_opt_kind)FS_OPT_GVN_FULLY, "GVN-PRE: replaced by fully redundant value" },
- { (hook_opt_kind)FS_OPT_GVN_PARTLY, "GVN-PRE: replaced by partly redundant value" },
- { (hook_opt_kind)FS_OPT_COMBO_CONST, "Combo: evaluated into Constant" },
- { (hook_opt_kind)FS_OPT_COMBO_CF, "Combo: removed conditional control flow" },
- { (hook_opt_kind)FS_OPT_COMBO_FOLLOWER, "Combo: removed a follower" },
- { (hook_opt_kind)FS_OPT_COMBO_CONGRUENT,"Combo: replaced by congruent" },
- { (hook_opt_kind)FS_OPT_JUMPTHREADING, "Jump threading: removed conditional control flow" },
- { (hook_opt_kind)FS_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_SYMMETRIC, "RTS optimization: call to symmetric function f(-x) replaced by f(x)" },
- { (hook_opt_kind)FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_STRCPY, "RTS optimization: call to strcpy() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_MEMPCPY, "RTS optimization: call to mempcpy() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_MEMMOVE, "RTS optimization: call to memmove() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
- { (hook_opt_kind)FS_OPT_RTS_MEMCMP, "RTS optimization: call to memcmp() replaced" },
-};
-
-/**
- * dumps a opcode hash into human readable form
- */
-static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
-{
- counter_t f_alive;
- counter_t f_new_node;
- counter_t f_Id;
- counter_t f_normlized;
-
- cnt_clr(&f_alive);
- cnt_clr(&f_new_node);
- cnt_clr(&f_Id);
- cnt_clr(&f_normlized);
-
- fprintf(dmp->f, "%-16s %-8s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id", "normalized");
- foreach_pset(set, node_entry_t, entry) {
- fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n",
- entry->op_id,
- cnt_to_uint(&entry->cnt_alive),
- cnt_to_uint(&entry->new_node),
- cnt_to_uint(&entry->into_Id),
- cnt_to_uint(&entry->normalized)
- );
-
- cnt_add(&f_alive, &entry->cnt_alive);
- cnt_add(&f_new_node, &entry->new_node);
- cnt_add(&f_Id, &entry->into_Id);
- cnt_add(&f_normlized, &entry->normalized);
- }
- fprintf(dmp->f, "-------------------------------------------\n");
- fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n", "Sum",
- cnt_to_uint(&f_alive),
- cnt_to_uint(&f_new_node),
- cnt_to_uint(&f_Id),
- cnt_to_uint(&f_normlized)
- );
-}
-
-/**
- * Return the name of an optimization.
- */
-static const char *get_opt_name(int index)
-{
- assert(index < (int) ARRAY_SIZE(opt_names) && "index out of range");
- assert((int) opt_names[index].kind == index && "opt_names broken");
- return opt_names[index].name;
-}
-
-/**
- * dumps an optimization hash into human readable form
- */
-static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
-{
- if (pset_count(set) > 0) {
- const char *name = get_opt_name(index);
-
- fprintf(dmp->f, "\n%s:\n", name);
- fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
-
- foreach_pset(set, opt_entry_t, entry) {
- fprintf(dmp->f, "%-16s %8u\n", entry->op_id, cnt_to_uint(&entry->count));
- }
- }
-}
-
-/**
- * dumps the register pressure for each block and for each register class
- */
-static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
-{
- /* return if no be statistic information available */
- be_block_entry_t *const b_first = pset_first(be_block_entry_t, entry->be_block_hash);
- if (!b_first)
- return;
-
- fprintf(dmp->f, "\nREG PRESSURE:\n");
- fprintf(dmp->f, "%12s", "Block Nr");
-
- /* print table head (register class names) */
- foreach_pset(b_first->reg_pressure, reg_pressure_entry_t, rp_entry)
- fprintf(dmp->f, "%15s", rp_entry->class_name);
- fprintf(dmp->f, "\n");
-
- /* print the reg pressure for all blocks and register classes */
- foreach_pset(entry->block_hash, be_block_entry_t, b_entry) {
- fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
-
- foreach_pset(b_entry->reg_pressure, reg_pressure_entry_t, rp_entry)
- fprintf(dmp->f, "%15d", rp_entry->pressure);
- fprintf(dmp->f, "\n");
- }
-}
-
-/**
- * dumps the number of real_function_call optimization
- */
-static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
-{
- if (! dmp->f)
- return;
-
- if (! cnt_eq(cnt, 0)) {
- fprintf(dmp->f, "\nReal Function Calls optimized:\n");
- fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
- }
-}
-
-/**
- * dumps the number of tail_recursion optimization
- */
-static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
-{
- if (! dmp->f)
- return;
-
- if (num_tail_recursion > 0) {
- fprintf(dmp->f, "\nTail recursion optimized:\n");
- fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
- }
-}
-
-/**
- * dumps the edges count
- */
-static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
-{
- if (! dmp->f)
- return;
-
- fprintf(dmp->f, "%-16s %8u\n", "Edges", cnt_to_uint(cnt));
-}
-
-/**
- * dumps the IRG
- */
-static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
-{
- int dump_opts = 1;
-
- if (! dmp->f)
- return;
-
- if (entry->irg) {
- ir_graph *const_irg = get_const_code_irg();
- if (entry->irg == const_irg) {
- fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
- } else {
- if (entry->ent)
- fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
- else
- fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
- }
-
- fprintf(dmp->f, " %swalked %u over blocks %u:\n"
- " was inlined : %u\n"
- " got inlined : %u\n"
- " strength red : %u\n"
- " leaf function : %s\n"
- " calls only leaf functions : %s\n"
- " recursive : %s\n"
- " chain call : %s\n"
- " strict : %s\n"
- " calls : %u\n"
- " indirect calls : %u\n"
- " external calls : %u\n",
- entry->is_deleted ? "DELETED " : "",
- cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
- cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
- cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
- cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
- entry->is_leaf ? "YES" : "NO",
- entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
- entry->is_recursive ? "YES" : "NO",
- entry->is_chain_call ? "YES" : "NO",
- entry->is_strict ? "YES" : "NO",
- cnt_to_uint(&entry->cnt[gcnt_all_calls]),
- cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
- cnt_to_uint(&entry->cnt[gcnt_external_calls])
- );
- } else {
- fprintf(dmp->f, "\nGlobals counts:\n");
- fprintf(dmp->f, "--------------\n");
- dump_opts = 0;
- }
-
- /* address ops */
- fprintf(dmp->f,
- " pure address calc ops : %u\n"
- " all address calc ops : %u\n",
- cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
- cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
- );
-
- /* Load/Store address classification */
- fprintf(dmp->f,
- " global Ld/St address : %u\n"
- " local Ld/St address : %u\n"
- " this Ld/St address : %u\n"
- " param Ld/St address : %u\n"
- " other Ld/St address : %u\n",
- cnt_to_uint(&entry->cnt[gcnt_global_adr]),
- cnt_to_uint(&entry->cnt[gcnt_local_adr]),
- cnt_to_uint(&entry->cnt[gcnt_this_adr]),
- cnt_to_uint(&entry->cnt[gcnt_param_adr]),
- cnt_to_uint(&entry->cnt[gcnt_other_adr])
- );
-
- simple_dump_opcode_hash(dmp, entry->opcode_hash);
- simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
-
- /* effects of optimizations */
- if (dump_opts) {
- size_t i;
-
- simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
- simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
-
- for (i = 0; i != ARRAY_SIZE(entry->opt_hash); ++i) {
- simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
- }
-
- /* dump block info */
- fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
- foreach_pset(entry->block_hash, block_entry_t, b_entry) {
- fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
- b_entry->block_nr,
- cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
- cnt_to_uint(&b_entry->cnt[bcnt_edges]),
- cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
- cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
- cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
- cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
- b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
- );
- }
-
- /* dump block reg pressure */
- simple_dump_be_block_reg_pressure(dmp, entry);
- }
-}
-
-/**
- * dumps the constant table
- */
-static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
-{
- size_t i;
- counter_t sum;
-
- if (! dmp->f)
- return;
-
- cnt_clr(&sum);
-
- fprintf(dmp->f, "\nConstant Information:\n");
- fprintf(dmp->f, "---------------------\n");
-
- fprintf(dmp->f, "\nBit usage for integer constants\n");
- fprintf(dmp->f, "-------------------------------\n");
-
- for (i = 0; i < ARRAY_SIZE(tbl->int_bits_count); ++i) {
- fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
- cnt_add(&sum, &tbl->int_bits_count[i]);
- }
- fprintf(dmp->f, "-------------------------------\n");
-
- fprintf(dmp->f, "\nFloating point constants classification\n");
- fprintf(dmp->f, "--------------------------------------\n");
- for (i = 0; i < ARRAY_SIZE(tbl->floats); ++i) {
- fprintf(dmp->f, "%-10s %12u\n", stat_fc_name((float_classify_t)i), cnt_to_uint(&tbl->floats[i]));
- cnt_add(&sum, &tbl->floats[i]);
- }
- fprintf(dmp->f, "--------------------------------------\n");
-
- fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
- cnt_add(&sum, &tbl->others);
- fprintf(dmp->f, "-------------------------------\n");
-
- fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
-}
-
-/**
- * Dumps a line of the parameter table
- */
-static void dump_tbl_line(const distrib_entry_t *entry, void *env)
-{
- dumper_t *dmp = (dumper_t*)env;
-
- fprintf(dmp->f, "%ld : %u\n", (long int)PTR_TO_INT(entry->object),
- cnt_to_uint(&entry->cnt));
-}
-
-/**
- * dumps the parameter distribution table
- */
-static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global)
-{
- fprintf(dmp->f, "\nCall parameter Information:\n");
- fprintf(dmp->f, "---------------------\n");
-
- stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
- fprintf(dmp->f, "-------------------------------\n");
-
- fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
- fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
- fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
- fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
- fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
- fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
-}
-
-/**
- * dumps the optimization counter table
- */
-static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len)
-{
- unsigned i;
-
- fprintf(dmp->f, "\nOptimization counts:\n");
- fprintf(dmp->f, "---------------------\n");
-
- for (i = 0; i < len; ++i) {
- unsigned cnt = cnt_to_uint(&tbl[i]);
-
- if (cnt > 0) {
- fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
- }
- }
-}
-
-/**
- * initialize the simple dumper
- */
-static void simple_init(dumper_t *dmp, const char *name)
-{
- char fname[2048];
-
- snprintf(fname, sizeof(fname), "%s.txt", name);
- dmp->f = fopen(fname, "w");
- if (! dmp->f) {
- perror(fname);
- }
-}
-
-/**
- * finishes the simple dumper
- */
-static void simple_finish(dumper_t *dmp)
-{
- if (dmp->f)
- fclose(dmp->f);
- dmp->f = NULL;
-}
-
-/**
- * the simple human readable dumper
- */
-const dumper_t simple_dumper = {
- simple_dump_graph,
- simple_dump_const_tbl,
- simple_dump_param_tbl,
- simple_dump_opt_cnt,
- simple_init,
- simple_finish,
- NULL,
- NULL,
- NULL,
- FOURCC('S', 'M', 'P', 'L'),
-};
-
-/* ---------------------------------------------------------------------- */
-
-/**
- * count the nodes as needed:
- *
- * 1 normal (data) Phi's
- * 2 memory Phi's
- * 3 Proj
- * 0 all other nodes
- */
-static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
-{
- int i;
-
- for (i = 0; i < 4; ++i)
- cnt_clr(&cnt[i]);
-
- foreach_pset(graph->opcode_hash, node_entry_t, entry) {
- op_id_t const op_id = entry->op_id;
- if (op_id == get_op_name(op_Phi)) {
- /* normal Phi */
- cnt_add(&cnt[1], &entry->cnt_alive);
- } else if (op_id == dmp->status->op_PhiM) {
- /* memory Phi */
- cnt_add(&cnt[2], &entry->cnt_alive);
- } else if (op_id == get_op_name(op_Proj)) {
- /* Proj */
- cnt_add(&cnt[3], &entry->cnt_alive);
- } else {
- /* all other nodes */
- cnt_add(&cnt[0], &entry->cnt_alive);
- }
- }
-}
-
-/**
- * dumps the IRG
- */
-static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
-{
- const char *name;
- counter_t cnt[4];
-
- if (! dmp->f)
- return;
-
- if (entry->irg && !entry->is_deleted) {
- ir_graph *const_irg = get_const_code_irg();
-
- if (entry->irg == const_irg) {
- return;
- } else {
- if (entry->ent)
- name = get_entity_name(entry->ent);
- else
- name = "<UNKNOWN IRG>";
- }
-
- csv_count_nodes(dmp, entry, cnt);
-
- fprintf(dmp->f, "%-40s, %p, %u, %u, %u, %u\n",
- name,
- (void *)entry->irg,
- cnt_to_uint(&cnt[0]),
- cnt_to_uint(&cnt[1]),
- cnt_to_uint(&cnt[2]),
- cnt_to_uint(&cnt[3])
- );
- }
-}
-
-/**
- * dumps the IRG
- */
-static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
-{
- (void) dmp;
- (void) tbl;
- /* FIXME: NYI */
-}
-
-/**
- * dumps the parameter distribution table
- */
-static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global)
-{
- (void) dmp;
- (void) tbl;
- (void) global;
- /* FIXME: NYI */
-}
-
-/**
- * dumps the optimization counter
- */
-static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len)
-{
- (void) dmp;
- (void) tbl;
- (void) len;
- /* FIXME: NYI */
-}
-
-/**
- * initialize the simple dumper
- */
-static void csv_init(dumper_t *dmp, const char *name)
-{
- char fname[2048];
-
- snprintf(fname, sizeof(fname), "%s.csv", name);
- dmp->f = fopen(fname, "a");
- if (! dmp->f)
- perror(fname);
-}
-
-/**
- * finishes the simple dumper
- */
-static void csv_finish(dumper_t *dmp)
-{
- if (dmp->f)
- fclose(dmp->f);
- dmp->f = NULL;
-}
-
-/**
- * the simple human readable dumper
- */
-const dumper_t csv_dumper = {
- csv_dump_graph,
- csv_dump_const_tbl,
- csv_dump_param_tbl,
- csv_dump_opt_cnt,
- csv_init,
- csv_finish,
- NULL,
- NULL,
- NULL,
- FOURCC('C', 'S', 'V', '\0')
-};
diff --git a/ir/stat/stat_dmp.h b/ir/stat/stat_dmp.h
deleted file mode 100644
index 21dc460..0000000
--- a/ir/stat/stat_dmp.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * This file is part of libFirm.
- * Copyright (C) 2012 University of Karlsruhe.
- */
-
-/**
- * @file
- * @brief Statistics for Firm. Dumping.
- * @author Michael Beck
- */
-#ifndef FIRM_STAT_STAT_DMP_H
-#define FIRM_STAT_STAT_DMP_H
-
-#include "firmstat_t.h"
-
-/**
- * The simple human readable dumper.
- */
-extern const dumper_t simple_dumper;
-
-/**
- * the comma separated list dumper
- *
- * @note Limited capabilities, mostly for the Firm paper
- */
-extern const dumper_t csv_dumper;
-
-#endif