3 * File name: ir/ir/firmstat.c
4 * Purpose: Statistics for Firm.
8 * Copyright: (c) 2004 Universität Karlsruhe
9 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
21 #ifdef FIRM_STATISTICS
25 # include "irnode_t.h"
26 # include "irgraph_t.h"
34 * just be make some things clear :-), the
37 #define HASH_MAP(type) hmap_##type
39 typedef pset hmap_node_entry_t;
40 typedef pset hmap_graph_entry_t;
41 typedef pset hmap_opt_entry_t;
42 typedef pset hmap_block_entry_t;
43 typedef pset hmap_ir_op;
46 * An entry for ir_nodes, used in ir_graph statistics.
48 typedef struct _node_entry_t {
49 counter_t cnt_alive; /**< amount of nodes in this entry */
50 counter_t new_node; /**< amount of new nodes for this entry */
51 counter_t into_Id; /**< amount of nodes that turned into Id's for this entry */
52 const ir_op *op; /**< the op for this entry */
56 * An entry for ir_graphs
58 typedef struct _graph_entry_t {
59 HASH_MAP(node_entry_t) *opcode_hash; /**< hash map containing the opcode counter */
60 HASH_MAP(block_entry_t) *block_hash; /**< hash map countaining the block counter */
61 counter_t cnt_walked; /**< walker walked over the graph */
62 counter_t cnt_walked_blocks; /**< walker walked over the graph blocks */
63 counter_t cnt_was_inlined; /**< number of times other graph were inlined */
64 counter_t cnt_got_inlined; /**< number of times this graph was inlined */
65 counter_t cnt_edges; /**< number of DF edges in this graph */
66 HASH_MAP(opt_entry_t) *opt_hash[STAT_OPT_MAX]; /**< hash maps containing opcode counter for optimizations */
67 ir_graph *irg; /**< the graph of this object */
68 entity *ent; /**< the entity of this graph if one exists */
69 int deleted; /**< set if this irg was deleted */
73 * An entry for optimized ir_nodes
75 typedef struct _opt_entry_t {
76 counter_t count; /**< optimization counter */
77 const ir_op *op; /**< the op for this entry */
81 * An entry for a block in a ir-graph
83 typedef struct _block_entry_t {
84 counter_t cnt_nodes; /**< the counter of nodes in this block */
85 counter_t cnt_edges; /**< the counter of edges in this block */
86 counter_t cnt_in_edges; /**< the counter of edges incoming from other blocks to this block */
87 counter_t cnt_out_edges; /**< the counter of edges outgoing from this block to other blocks */
88 long block_nr; /**< block nr */
92 typedef struct _dumper_t dumper_t;
95 * handler for dumping an IRG
97 * @param dmp the dumper
98 * @param entry the IR-graph hash map entry
100 typedef void (*dump_graph_FUNC)(dumper_t *dmp, graph_entry_t *entry);
103 * handler for dumper init
105 * @param dmp the dumper
106 * @param name name of the file to dump to
108 typedef void (*dump_init_FUNC)(dumper_t *dmp, const char *name);
111 * handler for dumper finish
113 * @param dmp the dumper
115 typedef void (*dump_finish_FUNC)(dumper_t *dmp);
119 * a dumper description
122 dump_graph_FUNC dump_graph; /**< handler for dumping an irg */
123 dump_init_FUNC init; /**< handler for init */
124 dump_finish_FUNC finish; /**< handler for finish */
125 FILE *f; /**< the file to dump to */
126 dumper_t *next; /**< link to the next dumper */
132 typedef struct _statistic_info_t {
133 struct obstack cnts; /**< obstack containing the counters */
134 HASH_MAP(graph_entry_t) *irg_hash; /**< hash map containing the counter for irgs */
135 HASH_MAP(ir_op) *ir_op_hash; /**< hash map containing all ir_ops (accessible by op_codes) */
136 int recursive; /**< flag for detecting recursive hook calls */
137 int in_dead_node_elim; /**< set, if dead node elimination runs */
138 ir_op *op_Phi0; /**< needed pseudo op */
139 ir_op *op_PhiM; /**< needed pseudo op */
140 dumper_t *dumper; /**< list of dumper */
141 int enable; /**< if set, statistic is enabled */
145 * names of the optimizations
147 static const char *opt_names[] = {
148 "straightening optimization",
150 "algebraic simplification",
152 "Write-After-Write optimization",
153 "Write-After-Read optimization",
154 "Read-After-Write optimization",
155 "Tuple optimization",
157 "Constant evaluation",
162 * need this to be static
164 static ir_op _op_Phi0, _op_PhiM;
166 /* ---------------------------------------------------------------------------------- */
168 #define STAT_ENTER ++status->recursive
169 #define STAT_LEAVE --status->recursive
170 #define STAT_ENTER_SINGLE do { if (status->recursive > 0) return; ++status->recursive; } while (0)
175 static stat_info_t _status, *status = &_status;
178 * compare two elements of the opcode hash
180 static int opcode_cmp(const void *elt, const void *key)
182 const node_entry_t *e1 = elt;
183 const node_entry_t *e2 = key;
185 return e1->op->code - e2->op->code;
189 * compare two elements of the graph hash
191 static int graph_cmp(const void *elt, const void *key)
193 const graph_entry_t *e1 = elt;
194 const graph_entry_t *e2 = key;
196 return e1->irg != e2->irg;
200 * compare two elements of the optimization hash
202 static int opt_cmp(const void *elt, const void *key)
204 const opt_entry_t *e1 = elt;
205 const opt_entry_t *e2 = key;
207 return e1->op->code != e2->op->code;
211 * compare two elements of the block hash
213 static int block_cmp(const void *elt, const void *key)
215 const block_entry_t *e1 = elt;
216 const block_entry_t *e2 = key;
218 return e1->block_nr != e2->block_nr;
222 * compare two elements of the ir_op hash
224 static int opcode_cmp_2(const void *elt, const void *key)
226 const ir_op *e1 = elt;
227 const ir_op *e2 = key;
229 return e1->code != e2->code;
233 * Returns the associates node_entry_t for an ir_op
235 static node_entry_t *opcode_get_entry(const ir_op *op, pset *set)
242 elem = pset_find(set, &key, op->code);
246 elem = obstack_alloc(&status->cnts, sizeof(*elem));
249 cnt_clr(&elem->cnt_alive);
250 cnt_clr(&elem->new_node);
251 cnt_clr(&elem->into_Id);
255 return pset_insert(set, elem, op->code);
259 * Returns the associates ir_op for an opcode
261 static ir_op *opcode_find_entry(opcode code, pset *set)
266 return pset_find(set, &key, code);
270 * calculates a hash value for an irg
271 * Addresses are typically aligned at 32bit, so we ignore the lowest bits
273 static INLINE unsigned irg_hash(const ir_graph *irg)
275 return (unsigned)irg >> 3;
279 * Returns the acssociates graph_entry_t for an irg
281 static graph_entry_t *graph_get_entry(ir_graph *irg, pset *set)
289 elem = pset_find(set, &key, irg_hash(irg));
293 elem = obstack_alloc(&status->cnts, sizeof(*elem));
295 cnt_clr(&elem->cnt_walked);
296 cnt_clr(&elem->cnt_walked_blocks);
297 cnt_clr(&elem->cnt_got_inlined);
298 cnt_clr(&elem->cnt_was_inlined);
299 cnt_clr(&elem->cnt_edges);
301 /* new hash table for opcodes here */
302 elem->opcode_hash = new_pset(opcode_cmp, 5);
303 elem->block_hash = new_pset(block_cmp, 5);
306 for (i = 0; i < sizeof(elem->opt_hash)/sizeof(elem->opt_hash[0]); ++i)
307 elem->opt_hash[i] = new_pset(opt_cmp, 4);
309 return pset_insert(set, elem, irg_hash(irg));
313 * Returns the associates opt_entry_t for an ir_op
315 static opt_entry_t *opt_get_entry(const ir_op *op, pset *set)
322 elem = pset_find(set, &key, op->code);
326 elem = obstack_alloc(&status->cnts, sizeof(*elem));
328 /* clear new counter */
329 cnt_clr(&elem->count);
333 return pset_insert(set, elem, op->code);
337 * Returns the associates block_entry_t for an block
339 static block_entry_t *block_get_entry(long block_nr, pset *set)
344 key.block_nr = block_nr;
346 elem = pset_find(set, &key, block_nr);
350 elem = obstack_alloc(&status->cnts, sizeof(*elem));
352 /* clear new counter */
353 cnt_clr(&elem->cnt_nodes);
354 cnt_clr(&elem->cnt_edges);
355 cnt_clr(&elem->cnt_in_edges);
356 cnt_clr(&elem->cnt_out_edges);
358 elem->block_nr = block_nr;
360 return pset_insert(set, elem, block_nr);
365 * Returns the ir_op for an IR-node,
366 * handles special cases and return pseudo op codes
368 static ir_op *stat_get_irn_op(const ir_node *node)
370 ir_op *op = get_irn_op(node);
372 if (op->code == iro_Phi && get_irn_arity(node) == 0) {
373 /* special case, a Phi0 node, count on extra counter */
374 op = status->op_Phi0;
376 else if (op->code == iro_Phi && get_irn_mode(node) == mode_M) {
377 /* special case, a Memory Phi node, count on extra counter */
378 op = status->op_PhiM;
384 * update the block counter
386 static void count_block_info(ir_node *node, graph_entry_t *graph)
388 ir_op *op = get_irn_op(node);
390 block_entry_t *b_entry;
393 /* check for block */
394 if (op == op_Block) {
395 arity = get_irn_arity(node);
396 b_entry = block_get_entry(get_irn_node_nr(node), graph->block_hash);
398 /* count all incoming edges */
399 for (i = 0; i < arity; ++i) {
400 ir_node *pred = get_irn_n(node, i);
401 ir_node *other_block = get_nodes_Block(pred);
402 block_entry_t *b_entry_other = block_get_entry(get_irn_node_nr(other_block), graph->block_hash);
404 cnt_inc(&b_entry->cnt_in_edges); /* an edge coming from another block */
405 cnt_inc(&b_entry_other->cnt_out_edges);
409 else if (op == op_Call) {
413 block = get_nodes_Block(node);
414 b_entry = block_get_entry(get_irn_node_nr(block), graph->block_hash);
416 /* we have a new nodes */
417 cnt_inc(&b_entry->cnt_nodes);
419 arity = get_irn_arity(node);
421 for (i = 0; i < arity; ++i) {
422 ir_node *pred = get_irn_n(node, i);
423 ir_node *other_block;
425 if (get_irn_op(pred) == op_Block)
428 other_block = get_nodes_Block(pred);
430 if (other_block == block)
431 cnt_inc(&b_entry->cnt_edges); /* a in block edge */
433 block_entry_t *b_entry_other = block_get_entry(get_irn_node_nr(other_block), graph->block_hash);
435 cnt_inc(&b_entry->cnt_in_edges); /* an edge coming from another block */
436 cnt_inc(&b_entry_other->cnt_out_edges);
442 * walker for reachable nodes count
444 static void count_nodes(ir_node *node, void *env)
446 graph_entry_t *graph = env;
449 ir_op *op = stat_get_irn_op(node);
450 int arity = get_irn_arity(node);
452 entry = opcode_get_entry(op, graph->opcode_hash);
454 cnt_inc(&entry->cnt_alive);
455 cnt_add_i(&graph->cnt_edges, arity);
457 /* count block edges */
458 count_block_info(node, graph);
462 * count all alive nodes and edges in a graph
464 static void count_nodes_in_graph(graph_entry_t *global, graph_entry_t *graph)
468 irg_walk_graph(graph->irg, count_nodes, NULL, graph);
470 /* assume we walk every graph only ONCE, we could sum here the global count */
471 for (entry = pset_first(graph->opcode_hash); entry; entry = pset_next(graph->opcode_hash)) {
472 node_entry_t *g_entry = opcode_get_entry(entry->op, global->opcode_hash);
474 /* update the node counter */
475 cnt_add(&g_entry->cnt_alive, &entry->cnt_alive);
478 /* update the edge counter */
479 cnt_add(&global->cnt_edges, &graph->cnt_edges);
485 static void stat_register_dumper(dumper_t *dumper, const char *name)
487 dumper->next = status->dumper;
488 status->dumper = dumper;
491 dumper->init(dumper, name);
497 static void dump_graph(graph_entry_t *entry)
501 for (dumper = status->dumper; dumper; dumper = dumper->next) {
502 if (dumper->dump_graph)
503 dumper->dump_graph(dumper, entry);
510 static void dump_finish(void)
514 for (dumper = status->dumper; dumper; dumper = dumper->next) {
516 dumper->finish(dumper);
520 /* ---------------------------------------------------------------------- */
523 * dumps a opcode hash into human readable form
525 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
529 counter_t f_new_node;
533 cnt_clr(&f_new_node);
536 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
537 for (entry = pset_first(set); entry; entry = pset_next(set)) {
538 fprintf(dmp->f, "%-16s %8d %8d %8d\n",
539 get_id_str(entry->op->name), entry->cnt_alive.cnt[0], entry->new_node.cnt[0], entry->into_Id.cnt[0]);
541 cnt_add(&f_alive, &entry->cnt_alive);
542 cnt_add(&f_new_node, &entry->new_node);
543 cnt_add(&f_Id, &entry->into_Id);
545 fprintf(dmp->f, "-------------------------------------------\n");
546 fprintf(dmp->f, "%-16s %8d %8d %8d\n", "Sum",
553 * dumps a optimization hash into human readable form
555 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
557 opt_entry_t *entry = pset_first(set);
560 fprintf(dmp->f, "\n%s:\n", opt_names[index]);
561 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
563 for (; entry; entry = pset_next(set)) {
564 fprintf(dmp->f, "%-16s %8d\n",
565 get_id_str(entry->op->name), entry->count.cnt[0]);
571 * dumps the endges count
573 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
575 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt->cnt[0]);
581 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
584 block_entry_t *b_entry;
587 ir_graph *const_irg = get_const_code_irg();
589 if (entry->irg == const_irg) {
590 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
594 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_name(entry->ent), (void *)entry->irg);
596 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
599 fprintf(dmp->f, " %swalked %d over blocks %d was inlined %d got inlined %d:\n",
600 entry->deleted ? "DELETED " : "",
601 entry->cnt_walked.cnt[0], entry->cnt_walked_blocks.cnt[0],
602 entry->cnt_was_inlined.cnt[0],
603 entry->cnt_got_inlined.cnt[0]
607 fprintf(dmp->f, "\nGlobals counts:\n");
611 simple_dump_opcode_hash(dmp, entry->opcode_hash);
612 simple_dump_edges(dmp, &entry->cnt_edges);
614 /* effects of optimizations */
618 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
619 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
623 /* dump block info */
624 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern", "incoming", "outgoing", "quot");
625 for (b_entry = pset_first(entry->block_hash);
627 b_entry = pset_next(entry->block_hash)) {
628 fprintf(dmp->f, "%12ld %12u %12u %12u %12u %4.8f\n",
630 b_entry->cnt_nodes.cnt[0],
631 b_entry->cnt_edges.cnt[0],
632 b_entry->cnt_in_edges.cnt[0],
633 b_entry->cnt_out_edges.cnt[0],
634 (double)b_entry->cnt_edges.cnt[0] / (double)b_entry->cnt_nodes.cnt[0]
640 * initialise the simple dumper
642 static void simple_init(dumper_t *dmp, const char *name)
644 dmp->f = fopen(name, "w");
648 * finishes the simple dumper
650 static void simple_finish(dumper_t *dmp)
657 * the simple human readable dumper
659 static dumper_t simple_dumper = {
667 /* ---------------------------------------------------------------------- */
670 * count the nodes as needed:
672 * 1 normal (data) Phi's
677 static void csv_count_nodes(graph_entry_t *graph, counter_t cnt[])
682 for (i = 0; i < 4; ++i)
685 for (entry = pset_first(graph->opcode_hash); entry; entry = pset_next(graph->opcode_hash)) {
686 if (entry->op == op_Phi) {
688 cnt_add(&cnt[1], &entry->cnt_alive);
690 else if (entry->op == status->op_PhiM) {
692 cnt_add(&cnt[2], &entry->cnt_alive);
694 else if (entry->op == op_Proj) {
696 cnt_add(&cnt[3], &entry->cnt_alive);
699 /* all other nodes */
700 cnt_add(&cnt[0], &entry->cnt_alive);
708 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
715 ir_graph *const_irg = get_const_code_irg();
717 if (entry->irg == const_irg) {
718 name = "<Const code Irg>";
723 name = get_entity_name(entry->ent);
725 name = "<UNKNOWN IRG>";
728 csv_count_nodes(entry, cnt);
730 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
742 * initialise the simple dumper
744 static void csv_init(dumper_t *dmp, const char *name)
746 dmp->f = fopen(name, "a");
750 * finishes the simple dumper
752 static void csv_finish(dumper_t *dmp)
759 * the simple human readable dumper
761 static dumper_t csv_dumper = {
770 /* ---------------------------------------------------------------------- */
773 * helper: get an ir_op from an opcode
775 ir_op *stat_get_op_from_opcode(opcode code)
777 return opcode_find_entry(code, status->ir_op_hash);
780 /* initialize the statistics module. */
781 void stat_init(unsigned enable_options)
783 #define X(a) a, sizeof(a)-1
787 /* enable statistics */
788 status->enable = enable_options & FIRMSTAT_ENABLED;
790 if (! status->enable)
793 obstack_init(&status->cnts);
795 /* build the pseudo-ops */
796 _op_Phi0.code = --pseudo_id;
797 _op_Phi0.name = id_from_str(X("Phi0"));
799 _op_PhiM.code = --pseudo_id;
800 _op_PhiM.name = id_from_str(X("PhiM"));
802 /* create the hash-tables */
803 status->irg_hash = new_pset(graph_cmp, 8);
804 status->ir_op_hash = new_pset(opcode_cmp_2, 1);
806 status->op_Phi0 = &_op_Phi0;
807 status->op_PhiM = &_op_PhiM;
809 stat_register_dumper(&simple_dumper, "firmstat.txt");
810 stat_register_dumper(&csv_dumper, "firmstat.csv");
812 /* initialize the pattern hash */
813 stat_init_pattern_history(enable_options & FIRMSTAT_PATTERN_ENABLED);
817 /* A new IR op is registered. */
818 void stat_new_ir_op(const ir_op *op)
820 if (! status->enable)
825 graph_entry_t *graph = graph_get_entry(NULL, status->irg_hash);
827 /* execute for side effect :-) */
828 opcode_get_entry(op, graph->opcode_hash);
830 pset_insert(status->ir_op_hash, op, op->code);
835 /* An IR op is freed. */
836 void stat_free_ir_op(const ir_op *op)
838 if (! status->enable)
847 /* A new node is created. */
848 void stat_new_node(const ir_node *node)
850 if (! status->enable)
853 /* do NOT count during dead node elimination */
854 if (status->in_dead_node_elim > 0)
860 graph_entry_t *graph;
861 ir_op *op = stat_get_irn_op(node);
863 /* increase global value */
864 graph = graph_get_entry(NULL, status->irg_hash);
865 entry = opcode_get_entry(op, graph->opcode_hash);
866 cnt_inc(&entry->new_node);
868 /* increase local value */
869 graph = graph_get_entry(current_ir_graph, status->irg_hash);
870 entry = opcode_get_entry(op, graph->opcode_hash);
871 cnt_inc(&entry->new_node);
876 /* A node is changed into a Id node */
877 void stat_turn_into_id(const ir_node *node)
879 if (! status->enable)
885 graph_entry_t *graph;
886 ir_op *op = stat_get_irn_op(node);
888 /* increase global value */
889 graph = graph_get_entry(NULL, status->irg_hash);
890 entry = opcode_get_entry(op, graph->opcode_hash);
891 cnt_inc(&entry->into_Id);
893 /* increase local value */
894 graph = graph_get_entry(current_ir_graph, status->irg_hash);
895 entry = opcode_get_entry(op, graph->opcode_hash);
896 cnt_inc(&entry->into_Id);
901 /* A new graph was created */
902 void stat_new_graph(ir_graph *irg, entity *ent)
904 if (! status->enable)
909 /* execute for side effect :-) */
910 graph_entry_t * graph = graph_get_entry(irg, status->irg_hash);
919 * A graph was deleted
921 void stat_free_graph(ir_graph *irg)
923 if (! status->enable)
928 graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
929 graph_entry_t *global = graph_get_entry(NULL, status->irg_hash);
933 /* count the nodes of the graph yet, it will be destroyed later */
934 count_nodes_in_graph(global, graph);
936 /* calculate the pattern */
937 stat_calc_pattern_history(irg);
943 * A walk over a graph is initiated. Do not count walks from statistic code.
945 void stat_irg_walk(ir_graph *irg, void *pre, void *post)
947 if (! status->enable)
952 graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
954 cnt_inc(&graph->cnt_walked);
960 * A walk over a graph in block-wise order is initiated. Do not count walks from statistic code.
962 void stat_irg_walk_blkwise(ir_graph *irg, void *pre, void *post)
964 /* for now, do NOT differentiate between blockwise and normal */
965 stat_irg_walk(irg, pre, post);
969 * A walk over the graph's blocks is initiated. Do not count walks from statistic code.
971 void stat_irg_block_walk(ir_graph *irg, const ir_node *node, void *pre, void *post)
973 if (! status->enable)
978 graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
980 cnt_inc(&graph->cnt_walked_blocks);
986 * called for every node that is removed due to an optimization
988 static void removed_due_opt(ir_node *n, pset *set)
990 ir_op *op = get_irn_op(n);
991 opt_entry_t *entry = opt_get_entry(op, set);
993 /* increase global value */
994 cnt_inc(&entry->count);
998 * Some nodes were optimized into some others due to an optimization
1000 void stat_merge_nodes(
1001 ir_node **new_node_array, int new_num_entries,
1002 ir_node **old_node_array, int old_num_entries,
1005 if (! status->enable)
1011 graph_entry_t *graph = graph_get_entry(current_ir_graph, status->irg_hash);
1013 for (i = 0; i < old_num_entries; ++i) {
1014 for (j = 0; j < new_num_entries; ++j)
1015 if (old_node_array[i] == new_node_array[j])
1018 /* nodes might be in new and old, these are NOT removed */
1019 if (j >= new_num_entries) {
1020 removed_due_opt(old_node_array[i], graph->opt_hash[opt]);
1028 * A node was lowered into other nodes
1030 void stat_lower(ir_node *node)
1032 if (! status->enable)
1037 graph_entry_t *graph = graph_get_entry(current_ir_graph, status->irg_hash);
1039 removed_due_opt(node, graph->opt_hash[STAT_LOWERED]);
1045 * A graph was inlined
1047 void stat_inline(ir_node *call, ir_graph *called_irg)
1049 if (! status->enable)
1054 ir_graph *irg = get_irn_irg(call);
1055 graph_entry_t *i_graph = graph_get_entry(called_irg, status->irg_hash);
1056 graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
1058 cnt_inc(&graph->cnt_got_inlined);
1059 cnt_inc(&i_graph->cnt_was_inlined);
1065 * Start the dead node elimination.
1067 void stat_dead_node_elim_start(ir_graph *irg)
1069 if (! status->enable)
1072 ++status->in_dead_node_elim;
1076 * Stops the dead node elimination.
1078 void stat_dead_node_elim_stop(ir_graph *irg)
1080 if (! status->enable)
1083 --status->in_dead_node_elim;
1086 /* Finish the statistics */
1087 void stat_finish(void)
1089 if (! status->enable)
1094 graph_entry_t *entry;
1095 graph_entry_t *global = graph_get_entry(NULL, status->irg_hash);
1097 /* dump per graph */
1098 for (entry = pset_first(status->irg_hash); entry; entry = pset_next(status->irg_hash)) {
1100 if (entry->irg == NULL) {
1101 /* special entry for the global count */
1105 if (! entry->deleted) {
1106 /* the graph is still alive, count the nodes on it */
1107 count_nodes_in_graph(global, entry);
1109 /* calculate the pattern */
1110 stat_calc_pattern_history(entry->irg);
1120 stat_finish_pattern_history();
1130 /* need this for prototypes */
1131 #define FIRM_STATISTICS
1132 #include "firmstat.h"
1134 void stat_init(void) {}
1136 void stat_finish(void) {}
1138 void stat_new_ir_op(const ir_op *op) {}
1140 void stat_free_ir_op(const ir_op *op) {}
1142 void stat_new_node(const ir_node *node) {}
1144 void stat_turn_into_id(const ir_node *node) {}
1146 void stat_new_graph(ir_graph *irg, entity *ent) {}
1148 void stat_free_graph(ir_graph *irg) {}
1150 void stat_irg_walk(ir_graph *irg, void *pre, void *post) {}
1152 void stat_irg_block_walk(ir_graph *irg, const ir_node *node, void *pre, void *post) {}
1154 void stat_merge_nodes(
1155 ir_node **new_node_array, int new_num_entries,
1156 ir_node **old_node_array, int old_num_entries,
1157 stat_opt_kind opt) {}
1159 void stat_lower(ir_node *node) {}
1161 void stat_inline(ir_node *call, ir_graph *irg) {}
1163 void stat_dead_node_elim_start(ir_graph *irg) {}
1165 void stat_dead_node_elim_stop(ir_graph *irg) {}