From: Michael Beck Date: Tue, 7 Dec 2004 12:08:30 +0000 (+0000) Subject: Added DAG statistic calculation X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=7f443d190f851ff3c38508253495470421fdb439;p=libfirm Added DAG statistic calculation [r4582] --- diff --git a/ir/stat/dags.c b/ir/stat/dags.c index bbca3ec16..5b3caeced 100644 --- a/ir/stat/dags.c +++ b/ir/stat/dags.c @@ -15,6 +15,8 @@ #include +#include "irprintf.h" +#include "irdump.h" #include "dags.h" enum dag_counting_options_t { @@ -53,25 +55,41 @@ struct _dag_entry_t { unsigned num_inner_nodes; /**< number of inner nodes in the DAG */ unsigned is_dead; /**< marks a dead entry */ dag_entry_t *next; /**< link all entries of a DAG */ + dag_entry_t *link; /**< if set, this entry is an ID */ }; /** - * a DAG Entry link, used to connect point - * from several places to the same DAG Entry + * return an DAG entry for the node n */ -typedef struct _dag_link_t { - dag_entry_t *entry; -} dag_link_t; +static dag_entry_t *get_irn_dag_entry(ir_node *n) +{ + dag_entry_t *res = get_irn_link(n); + + if (res) { + dag_entry_t *p; + + for (p = res; p->link; p = p->link); + + if (p != res) + set_irn_link(n, p); + + return p; + } + return NULL; +} + +#define set_irn_dag_entry(n, e) set_irn_link(n, e) /** * walker for connecting DAGs and counting. */ static void connect_dags(ir_node *node, void *env) { - dag_env_t *dag_env = env; - int i, arity; - ir_node *block; - dag_link_t *link; + dag_env_t *dag_env = env; + int i, arity; + ir_node *block; + dag_entry_t *entry; + ir_mode *mode; if (is_Block(node)) return; @@ -83,15 +101,20 @@ static void connect_dags(ir_node *node, void *env) block == get_irg_end_block(current_ir_graph)) return; - link = get_irn_link(node); + if (is_Phi(node)) + return; - if (! link) { - /* found a not assigned node, maybe a new root */ - dag_entry_t *entry = obstack_alloc(&dag_env->obst, sizeof(*entry)); + mode = get_irn_mode(node); + if (mode == mode_X || mode == mode_M) { + /* do NOT count mode_X nodes */ + return; + } + + entry = get_irn_dag_entry(node); - /* allocate a new link */ - link = obstack_alloc(&dag_env->obst, sizeof(*link)); - link->entry = entry; + if (! entry) { + /* found a not assigned node, maybe a new root */ + entry = obstack_alloc(&dag_env->obst, sizeof(*entry)); entry->num_nodes = 1; entry->num_roots = 1; @@ -99,17 +122,24 @@ static void connect_dags(ir_node *node, void *env) entry->root = node; entry->is_dead = 0; entry->next = dag_env->list_of_dags; + entry->link = NULL; ++dag_env->num_of_dags; dag_env->list_of_dags = entry; - set_irn_link(node, link); + set_irn_dag_entry(node, entry); } /* put the predecessors into the same DAG as the current */ for (i = 0, arity = get_irn_arity(node); i < arity; ++i) { - ir_node *prev = get_irn_n(node, i); - int special = 0; + ir_node *prev = get_irn_n(node, i); + 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 @@ -118,39 +148,61 @@ static void connect_dags(ir_node *node, void *env) */ if (dag_env->options & FIRMSTAT_COPY_CONSTANTS) { if (get_irn_op(prev) == op_Const || get_irn_op(prev) == op_SymConst) { - ++link->entry->num_nodes; - ++link->entry->num_inner_nodes; + ++entry->num_nodes; + ++entry->num_inner_nodes; } } - /* only nodes from teh same block goes into the DAG */ + /* only nodes from the same block goes into the DAG */ if (get_nodes_block(prev) == block) { - dag_link_t *prev_link = get_irn_link(prev); + dag_entry_t *prev_entry = get_irn_dag_entry(prev); - if (! prev_link) { + if (! prev_entry) { /* not assigned node, put it into the same DAG */ - set_irn_link(prev, link); - ++link->entry->num_nodes; - ++link->entry->num_inner_nodes; + set_irn_dag_entry(prev, entry); + ++entry->num_nodes; + ++entry->num_inner_nodes; } - else if (prev_link->entry != link->entry) { - /* two DAGs intersect */ - - assert(link->entry); + else { + if (prev_entry != entry) { - link->entry->num_roots += prev_link->entry->num_roots; - link->entry->num_nodes += prev_link->entry->num_nodes; - link->entry->num_inner_nodes += prev_link->entry->num_inner_nodes; + /* two DAGs intersect */ + entry->num_roots += prev_entry->num_roots; + entry->num_nodes += prev_entry->num_nodes; + entry->num_inner_nodes += prev_entry->num_inner_nodes; - --dag_env->num_of_dags; + --dag_env->num_of_dags; - prev_link->entry->is_dead = 1; - prev_link->entry = link->entry; + prev_entry->is_dead = 1; + prev_entry->link = entry; + } } } } } +/** + * a vcg attribute hook + */ +static int stat_dag_mark_hook(FILE *F, ir_node *n, 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 && (get_irn_op(l) == op_NoMem || get_irn_op(l) == op_Bad)) + return 0; + + entry = get_irn_dag_entry(n); + if (! entry) + return 0; + + fprintf(F, "color: %s info3: \"DAG id: %u\"", colors[entry->id & 7], entry->id); + + /* I know the color! */ + return 1; +} + /** * count the DAG's size of a graph */ @@ -190,6 +242,13 @@ void count_dags_in_graph(graph_entry_t *global, graph_entry_t *graph) get_irn_node_nr(entry->root)); } +#if 1 + /* dump for test */ + set_dump_node_vcgattr_hook(stat_dag_mark_hook); + dump_ir_block_graph(graph->irg, "-dag"); + set_dump_node_vcgattr_hook(NULL); +#endif + assert(id == root_env.num_of_dags); obstack_free(&root_env.obst, NULL); diff --git a/ir/stat/firmstat.c b/ir/stat/firmstat.c index 57e791b86..05a9307f9 100644 --- a/ir/stat/firmstat.c +++ b/ir/stat/firmstat.c @@ -491,8 +491,9 @@ static void set_adr_mark(graph_entry_t *graph, ir_node *node, unsigned val) /** * a vcg attribute hook */ -static int stat_adr_mark_hook(FILE *F, ir_node *n) +static int stat_adr_mark_hook(FILE *F, ir_node *node, ir_node *local) { + ir_node *n = local ? local : node; ir_graph *irg = get_irn_irg(n); graph_entry_t *graph = graph_get_entry(irg, status->irg_hash); unsigned mark = get_adr_mark(graph, n); @@ -500,7 +501,7 @@ static int stat_adr_mark_hook(FILE *F, ir_node *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: lightpurple"); + 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 @@ -545,7 +546,7 @@ static void mark_address_calc(ir_node *node, void *env) } } - /* makr all predecessors */ + /* mark all predecessors */ for (i = 0, n = get_irn_arity(node); i < n; ++i) { ir_node *pred = get_irn_n(node, i); @@ -749,6 +750,8 @@ void init_stat(unsigned enable_options) /* initialize the pattern hash */ stat_init_pattern_history(enable_options & FIRMSTAT_PATTERN_ENABLED); + + status->dag_options = enable_options & FIRMSTAT_COUNT_DAG; #undef X } @@ -875,7 +878,8 @@ void stat_free_graph(ir_graph *irg) update_graph_stat(global, graph); /* count the DAG's */ - //count_dags_in_graph(global, graph); + if (status->dag_options & FIRMSTAT_COUNT_DAG) + count_dags_in_graph(global, graph); /* calculate the pattern */ stat_calc_pattern_history(irg); @@ -1167,7 +1171,8 @@ void stat_finish(const char *name) update_graph_stat(global, entry); /* count the DAG's */ - //count_dags_in_graph(global, entry); + if (status->dag_options & FIRMSTAT_COUNT_DAG) + count_dags_in_graph(global, entry); /* calculate the pattern */ stat_calc_pattern_history(entry->irg); diff --git a/ir/stat/firmstat.h b/ir/stat/firmstat.h index 4bf145484..dd30efd4e 100644 --- a/ir/stat/firmstat.h +++ b/ir/stat/firmstat.h @@ -25,6 +25,7 @@ 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/DivMod by constant */ + FIRMSTAT_COUNT_DAG = 0x00000008, /**< if set, count DAG statistics */ FIRMSTAT_CSV_OUTPUT = 0x10000000 /**< CSV output of some mini-statistic */ }; diff --git a/ir/stat/firmstat_t.h b/ir/stat/firmstat_t.h index 70ccfc43c..9c1ef5059 100644 --- a/ir/stat/firmstat_t.h +++ b/ir/stat/firmstat_t.h @@ -152,6 +152,7 @@ typedef struct _statistic_info_t { dumper_t *dumper; /**< list of dumper */ int reassoc_run; /**< if set, reassociation is running */ int enable; /**< if set, statistic is enabled */ + int dag_options; /**< DAG counting options */ } stat_info_t; /**