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.
16 #ifdef FIRM_STATISTICS
22 #include "firmstat_t.h"
27 * names of the optimizations
29 static const char *opt_names[] = {
30 "straightening optimization",
32 "algebraic simplification",
34 "Write-After-Write optimization",
35 "Write-After-Read optimization",
36 "Read-After-Write optimization",
37 "Read-After-Read optimization",
40 "Constant evaluation",
41 "Common subexpression elimination",
43 "Architecture dependant optimization",
44 "Reassociation optimization",
49 * need this to be static:
50 * Special pseudo Opcodes that we need to count some interesting cases
54 * The Phi0, a node that is created during SSA construction
56 static ir_op _op_Phi0;
58 /** The PhiM, just to count memorty Phi's. */
59 static ir_op _op_PhiM;
61 /** The Mul by Const node. */
62 static ir_op _op_MulC;
64 /** The Div by Const node. */
65 static ir_op _op_DivC;
67 /** The Div by Const node. */
68 static ir_op _op_ModC;
70 /** The Div by Const node. */
71 static ir_op _op_DivModC;
73 /* ---------------------------------------------------------------------------------- */
75 #define STAT_ENTER ++status->recursive
76 #define STAT_LEAVE --status->recursive
77 #define STAT_ENTER_SINGLE do { if (status->recursive > 0) return; ++status->recursive; } while (0)
82 static stat_info_t _status, *status = &_status;
85 * compare two elements of the opcode hash
87 static int opcode_cmp(const void *elt, const void *key)
89 const node_entry_t *e1 = elt;
90 const node_entry_t *e2 = key;
92 return e1->op->code - e2->op->code;
96 * compare two elements of the graph hash
98 static int graph_cmp(const void *elt, const void *key)
100 const graph_entry_t *e1 = elt;
101 const graph_entry_t *e2 = key;
103 return e1->irg != e2->irg;
107 * compare two elements of the optimization hash
109 static int opt_cmp(const void *elt, const void *key)
111 const opt_entry_t *e1 = elt;
112 const opt_entry_t *e2 = key;
114 return e1->op->code != e2->op->code;
118 * compare two elements of the block hash
120 static int block_cmp(const void *elt, const void *key)
122 const block_entry_t *e1 = elt;
123 const block_entry_t *e2 = key;
125 return e1->block_nr != e2->block_nr;
129 * compare two elements of the ir_op hash
131 static int opcode_cmp_2(const void *elt, const void *key)
133 const ir_op *e1 = elt;
134 const ir_op *e2 = key;
136 return e1->code != e2->code;
140 * clears all counter in a node_entry_t
142 static void opcode_clear_entry(node_entry_t *elem)
144 cnt_clr(&elem->cnt_alive);
145 cnt_clr(&elem->new_node);
146 cnt_clr(&elem->into_Id);
150 * Returns the associates node_entry_t for an ir_op
152 static node_entry_t *opcode_get_entry(const ir_op *op, pset *set)
159 elem = pset_find(set, &key, op->code);
163 elem = obstack_alloc(&status->cnts, sizeof(*elem));
166 opcode_clear_entry(elem);
170 return pset_insert(set, elem, op->code);
174 * Returns the associates ir_op for an opcode
176 static ir_op *opcode_find_entry(opcode code, pset *set)
181 return pset_find(set, &key, code);
185 * calculates a hash value for an irg
186 * Addresses are typically aligned at 32bit, so we ignore the lowest bits
188 static INLINE unsigned irg_hash(const ir_graph *irg)
190 return (unsigned)irg >> 3;
194 * clears all counter in a graph_entry_t
196 static void graph_clear_entry(graph_entry_t *elem)
198 cnt_clr(&elem->cnt_walked);
199 cnt_clr(&elem->cnt_walked_blocks);
200 cnt_clr(&elem->cnt_was_inlined);
201 cnt_clr(&elem->cnt_got_inlined);
202 cnt_clr(&elem->cnt_strength_red);
203 cnt_clr(&elem->cnt_edges);
207 * Returns the acssociates graph_entry_t for an irg
209 static graph_entry_t *graph_get_entry(ir_graph *irg, pset *set)
217 elem = pset_find(set, &key, irg_hash(irg));
221 elem = obstack_alloc(&status->cnts, sizeof(*elem));
224 graph_clear_entry(elem);
226 /* new hash table for opcodes here */
227 elem->opcode_hash = new_pset(opcode_cmp, 5);
228 elem->block_hash = new_pset(block_cmp, 5);
231 for (i = 0; i < sizeof(elem->opt_hash)/sizeof(elem->opt_hash[0]); ++i)
232 elem->opt_hash[i] = new_pset(opt_cmp, 4);
234 return pset_insert(set, elem, irg_hash(irg));
238 * clears all counter in an opt_entry_t
240 static void opt_clear_entry(opt_entry_t *elem)
242 cnt_clr(&elem->count);
246 * Returns the associates opt_entry_t for an ir_op
248 static opt_entry_t *opt_get_entry(const ir_op *op, pset *set)
255 elem = pset_find(set, &key, op->code);
259 elem = obstack_alloc(&status->cnts, sizeof(*elem));
261 /* clear new counter */
262 opt_clear_entry(elem);
266 return pset_insert(set, elem, op->code);
270 * clears all counter in a block_entry_t
272 static void block_clear_entry(block_entry_t *elem)
274 cnt_clr(&elem->cnt_nodes);
275 cnt_clr(&elem->cnt_edges);
276 cnt_clr(&elem->cnt_in_edges);
277 cnt_clr(&elem->cnt_out_edges);
281 * Returns the associates block_entry_t for an block
283 static block_entry_t *block_get_entry(long block_nr, pset *set)
288 key.block_nr = block_nr;
290 elem = pset_find(set, &key, block_nr);
294 elem = obstack_alloc(&status->cnts, sizeof(*elem));
296 /* clear new counter */
297 block_clear_entry(elem);
299 elem->block_nr = block_nr;
301 return pset_insert(set, elem, block_nr);
306 * Returns the ir_op for an IR-node,
307 * handles special cases and return pseudo op codes
309 static ir_op *stat_get_irn_op(ir_node *node)
311 ir_op *op = get_irn_op(node);
313 if (op->code == iro_Phi && get_irn_arity(node) == 0) {
314 /* special case, a Phi0 node, count on extra counter */
315 op = status->op_Phi0;
317 else if (op->code == iro_Phi && get_irn_mode(node) == mode_M) {
318 /* special case, a Memory Phi node, count on extra counter */
319 op = status->op_PhiM;
321 else if (op->code == iro_Mul &&
322 (get_irn_op(get_Mul_left(node)) == op_Const || get_irn_op(get_Mul_right(node)) == op_Const)) {
323 /* special case, a Multiply by a const, count on extra counter */
324 op = status->op_MulC ? status->op_MulC : op_Mul;
326 else if (op->code == iro_Div && get_irn_op(get_Div_right(node)) == op_Const) {
327 /* special case, a division by a const, count on extra counter */
328 op = status->op_DivC ? status->op_DivC : op_Div;
330 else if (op->code == iro_Mod && get_irn_op(get_Mod_right(node)) == op_Const) {
331 /* special case, a module by a const, count on extra counter */
332 op = status->op_ModC ? status->op_ModC : op_Mod;
334 else if (op->code == iro_DivMod && get_irn_op(get_DivMod_right(node)) == op_Const) {
335 /* special case, a division/modulo by a const, count on extra counter */
336 op = status->op_DivModC ? status->op_DivModC : op_DivMod;
343 * update the block counter
345 static void count_block_info(ir_node *node, graph_entry_t *graph)
347 ir_op *op = get_irn_op(node);
349 block_entry_t *b_entry;
352 /* check for block */
353 if (op == op_Block) {
354 arity = get_irn_arity(node);
355 b_entry = block_get_entry(get_irn_node_nr(node), graph->block_hash);
357 /* count all incoming edges */
358 for (i = 0; i < arity; ++i) {
359 ir_node *pred = get_irn_n(node, i);
360 ir_node *other_block = get_nodes_block(pred);
361 block_entry_t *b_entry_other = block_get_entry(get_irn_node_nr(other_block), graph->block_hash);
363 cnt_inc(&b_entry->cnt_in_edges); /* an edge coming from another block */
364 cnt_inc(&b_entry_other->cnt_out_edges);
368 else if (op == op_Call) {
372 block = get_nodes_block(node);
373 b_entry = block_get_entry(get_irn_node_nr(block), graph->block_hash);
375 /* we have a new nodes */
376 cnt_inc(&b_entry->cnt_nodes);
378 arity = get_irn_arity(node);
380 for (i = 0; i < arity; ++i) {
381 ir_node *pred = get_irn_n(node, i);
382 ir_node *other_block;
384 if (get_irn_op(pred) == op_Block)
387 other_block = get_nodes_block(pred);
389 if (other_block == block)
390 cnt_inc(&b_entry->cnt_edges); /* a in block edge */
392 block_entry_t *b_entry_other = block_get_entry(get_irn_node_nr(other_block), graph->block_hash);
394 cnt_inc(&b_entry->cnt_in_edges); /* an edge coming from another block */
395 cnt_inc(&b_entry_other->cnt_out_edges);
401 * update info on calls
403 static void count_call(ir_node *call, graph_entry_t *graph)
405 ir_node *ptr = get_Call_ptr(call);
408 /* found a call, is not a leaf function */
411 if (get_irn_op(ptr) == op_SymConst) {
412 if (get_SymConst_kind(ptr) == symconst_addr_ent) {
413 /* ok, we seems to know the entity */
414 ent = get_SymConst_entity(ptr);
416 if (get_entity_irg(ent) == graph->irg)
417 graph->is_recursive = 1;
421 /* check, if it's a chain-call: Then, the call-block
422 * must dominate the end block. */
424 ir_node *curr = get_irg_end_block(graph->irg);
425 ir_node *block = get_nodes_block(call);
426 int depth = get_Block_dom_depth(block);
428 for (; curr != block && get_Block_dom_depth(curr) > depth;) {
429 curr = get_Block_idom(curr);
431 if (! curr || is_no_Block(curr))
436 graph->is_chain_call = 0;
441 * walker for reachable nodes count
443 static void count_nodes(ir_node *node, void *env)
445 graph_entry_t *graph = env;
448 ir_op *op = stat_get_irn_op(node);
449 int arity = get_irn_arity(node);
451 entry = opcode_get_entry(op, graph->opcode_hash);
453 cnt_inc(&entry->cnt_alive);
454 cnt_add_i(&graph->cnt_edges, arity);
456 /* count block edges */
457 count_block_info(node, graph);
459 /* check for leaf functions */
460 if (get_irn_op(node) == op_Call)
461 count_call(node, graph);
465 * count all alive nodes and edges in a graph
467 static void count_nodes_in_graph(graph_entry_t *global, graph_entry_t *graph)
471 /* clear first the alive counter in the graph */
472 for (entry = pset_first(graph->opcode_hash); entry; entry = pset_next(graph->opcode_hash)) {
473 cnt_clr(&entry->cnt_alive);
476 /* set pessimistic values */
478 graph->is_recursive = 0;
479 graph->is_chain_call = 1;
481 /* we need dominator info */
482 if (graph->irg != get_const_code_irg())
483 if (get_irg_dom_state(graph->irg) != dom_consistent)
484 compute_doms(graph->irg);
486 /* count the nodes in the graph */
487 irg_walk_graph(graph->irg, count_nodes, NULL, graph);
490 entry = opcode_get_entry(op_Call, graph->opcode_hash);
492 /* check if we have more than 1 call */
493 if (cnt_gt(entry->cnt_alive, 1))
494 graph->is_chain_call = 0;
497 /* recursive functions are never chain calls, leafs don't have calls */
498 if (graph->is_recursive || graph->is_leaf)
499 graph->is_chain_call = 0;
501 /* assume we walk every graph only ONCE, we could sum here the global count */
502 for (entry = pset_first(graph->opcode_hash); entry; entry = pset_next(graph->opcode_hash)) {
503 node_entry_t *g_entry = opcode_get_entry(entry->op, global->opcode_hash);
505 /* update the node counter */
506 cnt_add(&g_entry->cnt_alive, &entry->cnt_alive);
509 /* update the edge counter */
510 cnt_add(&global->cnt_edges, &graph->cnt_edges);
516 static void stat_register_dumper(dumper_t *dumper)
518 dumper->next = status->dumper;
519 status->dumper = dumper;
525 static void dump_graph(graph_entry_t *entry)
529 for (dumper = status->dumper; dumper; dumper = dumper->next) {
530 if (dumper->dump_graph)
531 dumper->dump_graph(dumper, entry);
536 * initialise the dumper
538 static void dump_init(const char *name)
542 for (dumper = status->dumper; dumper; dumper = dumper->next) {
544 dumper->init(dumper, name);
551 static void dump_finish(void)
555 for (dumper = status->dumper; dumper; dumper = dumper->next) {
557 dumper->finish(dumper);
561 /* ---------------------------------------------------------------------- */
564 * dumps a opcode hash into human readable form
566 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
570 counter_t f_new_node;
574 cnt_clr(&f_new_node);
577 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
578 for (entry = pset_first(set); entry; entry = pset_next(set)) {
579 fprintf(dmp->f, "%-16s %8d %8d %8d\n",
580 get_id_str(entry->op->name), entry->cnt_alive.cnt[0], entry->new_node.cnt[0], entry->into_Id.cnt[0]);
582 cnt_add(&f_alive, &entry->cnt_alive);
583 cnt_add(&f_new_node, &entry->new_node);
584 cnt_add(&f_Id, &entry->into_Id);
586 fprintf(dmp->f, "-------------------------------------------\n");
587 fprintf(dmp->f, "%-16s %8d %8d %8d\n", "Sum",
594 * dumps a optimization hash into human readable form
596 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
598 opt_entry_t *entry = pset_first(set);
601 fprintf(dmp->f, "\n%s:\n", opt_names[index]);
602 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
604 for (; entry; entry = pset_next(set)) {
605 fprintf(dmp->f, "%-16s %8d\n",
606 get_id_str(entry->op->name), entry->count.cnt[0]);
612 * dumps the endges count
614 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
616 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt->cnt[0]);
622 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
625 block_entry_t *b_entry;
628 ir_graph *const_irg = get_const_code_irg();
630 if (entry->irg == const_irg) {
631 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
635 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_name(entry->ent), (void *)entry->irg);
637 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
640 fprintf(dmp->f, " %swalked %d over blocks %d:\n"
643 " strength red: %d\n"
644 " leaf function: %s\n"
646 " chain call : %s\n",
647 entry->is_deleted ? "DELETED " : "",
648 entry->cnt_walked.cnt[0], entry->cnt_walked_blocks.cnt[0],
649 entry->cnt_was_inlined.cnt[0],
650 entry->cnt_got_inlined.cnt[0],
651 entry->cnt_strength_red.cnt[0],
652 entry->is_leaf ? "YES" : "NO",
653 entry->is_recursive ? "YES" : "NO",
654 entry->is_chain_call ? "YES" : "NO"
658 fprintf(dmp->f, "\nGlobals counts:\n");
659 fprintf(dmp->f, "--------------\n");
663 simple_dump_opcode_hash(dmp, entry->opcode_hash);
664 simple_dump_edges(dmp, &entry->cnt_edges);
666 /* effects of optimizations */
670 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
671 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
674 /* dump block info */
675 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "quot");
676 for (b_entry = pset_first(entry->block_hash);
678 b_entry = pset_next(entry->block_hash)) {
679 fprintf(dmp->f, "BLK %12ld %12u %12u %12u %12u %4.8f\n",
681 b_entry->cnt_nodes.cnt[0],
682 b_entry->cnt_edges.cnt[0],
683 b_entry->cnt_in_edges.cnt[0],
684 b_entry->cnt_out_edges.cnt[0],
685 (double)b_entry->cnt_edges.cnt[0] / (double)b_entry->cnt_nodes.cnt[0]
692 * initialise the simple dumper
694 static void simple_init(dumper_t *dmp, const char *name)
698 snprintf(fname, sizeof(fname), "%s.txt", name);
699 dmp->f = fopen(fname, "w");
703 * finishes the simple dumper
705 static void simple_finish(dumper_t *dmp)
712 * the simple human readable dumper
714 static dumper_t simple_dumper = {
722 /* ---------------------------------------------------------------------- */
725 * count the nodes as needed:
727 * 1 normal (data) Phi's
732 static void csv_count_nodes(graph_entry_t *graph, counter_t cnt[])
737 for (i = 0; i < 4; ++i)
740 for (entry = pset_first(graph->opcode_hash); entry; entry = pset_next(graph->opcode_hash)) {
741 if (entry->op == op_Phi) {
743 cnt_add(&cnt[1], &entry->cnt_alive);
745 else if (entry->op == status->op_PhiM) {
747 cnt_add(&cnt[2], &entry->cnt_alive);
749 else if (entry->op == op_Proj) {
751 cnt_add(&cnt[3], &entry->cnt_alive);
754 /* all other nodes */
755 cnt_add(&cnt[0], &entry->cnt_alive);
763 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
769 if (entry->irg && !entry->is_deleted) {
770 ir_graph *const_irg = get_const_code_irg();
772 if (entry->irg == const_irg) {
773 name = "<Const code Irg>";
778 name = get_entity_name(entry->ent);
780 name = "<UNKNOWN IRG>";
783 csv_count_nodes(entry, cnt);
785 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
797 * initialise the simple dumper
799 static void csv_init(dumper_t *dmp, const char *name)
803 snprintf(fname, sizeof(fname), "%s.csv", name);
804 dmp->f = fopen(fname, "a");
808 * finishes the simple dumper
810 static void csv_finish(dumper_t *dmp)
817 * the simple human readable dumper
819 static dumper_t csv_dumper = {
828 /* ---------------------------------------------------------------------- */
831 * helper: get an ir_op from an opcode
833 ir_op *stat_get_op_from_opcode(opcode code)
835 return opcode_find_entry(code, status->ir_op_hash);
838 /* initialize the statistics module. */
839 void init_stat(unsigned enable_options)
841 #define X(a) a, sizeof(a)-1
845 /* enable statistics */
846 status->enable = enable_options & FIRMSTAT_ENABLED;
848 if (! status->enable)
851 obstack_init(&status->cnts);
853 /* build the pseudo-ops */
854 _op_Phi0.code = --pseudo_id;
855 _op_Phi0.name = new_id_from_chars(X("Phi0"));
857 _op_PhiM.code = --pseudo_id;
858 _op_PhiM.name = new_id_from_chars(X("PhiM"));
860 _op_MulC.code = --pseudo_id;
861 _op_MulC.name = new_id_from_chars(X("MulC"));
863 _op_DivC.code = --pseudo_id;
864 _op_DivC.name = new_id_from_chars(X("DivC"));
866 _op_ModC.code = --pseudo_id;
867 _op_ModC.name = new_id_from_chars(X("ModC"));
869 _op_DivModC.code = --pseudo_id;
870 _op_DivModC.name = new_id_from_chars(X("DivModC"));
872 /* create the hash-tables */
873 status->irg_hash = new_pset(graph_cmp, 8);
874 status->ir_op_hash = new_pset(opcode_cmp_2, 1);
876 status->op_Phi0 = &_op_Phi0;
877 status->op_PhiM = &_op_PhiM;
879 if (enable_options & FIRMSTAT_COUNT_STRONG_OP) {
880 status->op_MulC = &_op_MulC;
881 status->op_DivC = &_op_DivC;
882 status->op_ModC = &_op_ModC;
883 status->op_DivModC = &_op_DivModC;
886 status->op_MulC = NULL;
887 status->op_DivC = NULL;
888 status->op_ModC = NULL;
889 status->op_DivModC = NULL;
892 stat_register_dumper(&simple_dumper);
893 stat_register_dumper(&csv_dumper);
895 /* initialize the pattern hash */
896 stat_init_pattern_history(enable_options & FIRMSTAT_PATTERN_ENABLED);
900 /* A new IR op is registered. */
901 void stat_new_ir_op(const ir_op *op)
903 if (! status->enable)
908 graph_entry_t *graph = graph_get_entry(NULL, status->irg_hash);
910 /* execute for side effect :-) */
911 opcode_get_entry(op, graph->opcode_hash);
913 pset_insert(status->ir_op_hash, op, op->code);
918 /* An IR op is freed. */
919 void stat_free_ir_op(const ir_op *op)
921 if (! status->enable)
930 /* A new node is created. */
931 void stat_new_node(ir_node *node)
933 if (! status->enable)
936 /* do NOT count during dead node elimination */
937 if (status->in_dead_node_elim > 0)
943 graph_entry_t *graph;
944 ir_op *op = stat_get_irn_op(node);
946 /* increase global value */
947 graph = graph_get_entry(NULL, status->irg_hash);
948 entry = opcode_get_entry(op, graph->opcode_hash);
949 cnt_inc(&entry->new_node);
951 /* increase local value */
952 graph = graph_get_entry(current_ir_graph, status->irg_hash);
953 entry = opcode_get_entry(op, graph->opcode_hash);
954 cnt_inc(&entry->new_node);
959 /* A node is changed into a Id node */
960 void stat_turn_into_id(ir_node *node)
962 if (! status->enable)
968 graph_entry_t *graph;
969 ir_op *op = stat_get_irn_op(node);
971 /* increase global value */
972 graph = graph_get_entry(NULL, status->irg_hash);
973 entry = opcode_get_entry(op, graph->opcode_hash);
974 cnt_inc(&entry->into_Id);
976 /* increase local value */
977 graph = graph_get_entry(current_ir_graph, status->irg_hash);
978 entry = opcode_get_entry(op, graph->opcode_hash);
979 cnt_inc(&entry->into_Id);
984 /* A new graph was created */
985 void stat_new_graph(ir_graph *irg, entity *ent)
987 if (! status->enable)
992 /* execute for side effect :-) */
993 graph_entry_t * graph = graph_get_entry(irg, status->irg_hash);
996 graph->is_deleted = 0;
998 graph->is_recursive = 0;
999 graph->is_chain_call = 0;
1005 * A graph was deleted
1007 void stat_free_graph(ir_graph *irg)
1009 if (! status->enable)
1014 graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
1015 graph_entry_t *global = graph_get_entry(NULL, status->irg_hash);
1017 graph->is_deleted = 1;
1019 /* count the nodes of the graph yet, it will be destroyed later */
1020 count_nodes_in_graph(global, graph);
1022 /* count the DAG's */
1023 // count_dags_in_graph(global, graph);
1025 /* calculate the pattern */
1026 stat_calc_pattern_history(irg);
1032 * A walk over a graph is initiated. Do not count walks from statistic code.
1034 void stat_irg_walk(ir_graph *irg, void *pre, void *post)
1036 if (! status->enable)
1041 graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
1043 cnt_inc(&graph->cnt_walked);
1049 * A walk over a graph in block-wise order is initiated. Do not count walks from statistic code.
1051 void stat_irg_walk_blkwise(ir_graph *irg, void *pre, void *post)
1053 /* for now, do NOT differentiate between blockwise and normal */
1054 stat_irg_walk(irg, pre, post);
1058 * A walk over the graph's blocks is initiated. Do not count walks from statistic code.
1060 void stat_irg_block_walk(ir_graph *irg, const ir_node *node, void *pre, void *post)
1062 if (! status->enable)
1067 graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
1069 cnt_inc(&graph->cnt_walked_blocks);
1075 * called for every node that is removed due to an optimization
1077 static void removed_due_opt(ir_node *n, pset *set)
1079 ir_op *op = stat_get_irn_op(n);
1080 opt_entry_t *entry = opt_get_entry(op, set);
1082 /* increase global value */
1083 cnt_inc(&entry->count);
1087 * Some nodes were optimized into some others due to an optimization
1089 void stat_merge_nodes(
1090 ir_node **new_node_array, int new_num_entries,
1091 ir_node **old_node_array, int old_num_entries,
1094 if (! status->enable)
1100 graph_entry_t *graph = graph_get_entry(current_ir_graph, status->irg_hash);
1102 if (status->reassoc_run)
1103 opt = STAT_OPT_REASSOC;
1105 for (i = 0; i < old_num_entries; ++i) {
1106 for (j = 0; j < new_num_entries; ++j)
1107 if (old_node_array[i] == new_node_array[j])
1110 /* nodes might be in new and old, these are NOT removed */
1111 if (j >= new_num_entries) {
1112 removed_due_opt(old_node_array[i], graph->opt_hash[opt]);
1120 * reassociation started/stopped.
1122 void stat_reassociate(int flag)
1124 if (! status->enable)
1129 status->reassoc_run = flag;
1135 * A node was lowered into other nodes
1137 void stat_lower(ir_node *node)
1139 if (! status->enable)
1144 graph_entry_t *graph = graph_get_entry(current_ir_graph, status->irg_hash);
1146 removed_due_opt(node, graph->opt_hash[STAT_LOWERED]);
1152 * A graph was inlined
1154 void stat_inline(ir_node *call, ir_graph *called_irg)
1156 if (! status->enable)
1161 ir_graph *irg = get_irn_irg(call);
1162 graph_entry_t *i_graph = graph_get_entry(called_irg, status->irg_hash);
1163 graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
1165 cnt_inc(&graph->cnt_got_inlined);
1166 cnt_inc(&i_graph->cnt_was_inlined);
1172 * A graph with tail-recursions was optimized.
1174 void stat_tail_rec(ir_graph *irg)
1176 if (! status->enable)
1186 * Strength reduction was performed on an iteration variable.
1188 void stat_strength_red(ir_graph *irg, ir_node *strong, ir_node *cmp)
1190 if (! status->enable)
1195 graph_entry_t *graph = graph_get_entry(irg, status->irg_hash);
1196 cnt_inc(&graph->cnt_strength_red);
1198 removed_due_opt(strong, graph->opt_hash[STAT_OPT_STRENGTH_RED]);
1204 * Start the dead node elimination.
1206 void stat_dead_node_elim_start(ir_graph *irg)
1208 if (! status->enable)
1211 ++status->in_dead_node_elim;
1215 * Stops the dead node elimination.
1217 void stat_dead_node_elim_stop(ir_graph *irg)
1219 if (! status->enable)
1222 --status->in_dead_node_elim;
1226 * A multiply was replaced by a series of Shifts/Adds/Subs
1228 void stat_arch_dep_replace_mul_with_shifts(ir_node *mul)
1230 if (! status->enable)
1235 graph_entry_t *graph = graph_get_entry(current_ir_graph, status->irg_hash);
1236 removed_due_opt(mul, graph->opt_hash[STAT_OPT_ARCH_DEP]);
1242 * A division was replaced by a series of Shifts/Muls
1244 void stat_arch_dep_replace_div_by_const(ir_node *div)
1246 if (! status->enable)
1251 graph_entry_t *graph = graph_get_entry(current_ir_graph, status->irg_hash);
1252 removed_due_opt(div, graph->opt_hash[STAT_OPT_ARCH_DEP]);
1258 * A modulo was replaced by a series of Shifts/Muls
1260 void stat_arch_dep_replace_mod_by_const(ir_node *mod)
1262 if (! status->enable)
1267 graph_entry_t *graph = graph_get_entry(current_ir_graph, status->irg_hash);
1268 removed_due_opt(mod, graph->opt_hash[STAT_OPT_ARCH_DEP]);
1274 * A DivMod was replaced by a series of Shifts/Muls
1276 void stat_arch_dep_replace_DivMod_by_const(ir_node *divmod)
1278 if (! status->enable)
1283 graph_entry_t *graph = graph_get_entry(current_ir_graph, status->irg_hash);
1284 removed_due_opt(divmod, graph->opt_hash[STAT_OPT_ARCH_DEP]);
1289 /* Finish the statistics */
1290 void stat_finish(const char *name)
1292 if (! status->enable)
1297 graph_entry_t *entry;
1298 graph_entry_t *global = graph_get_entry(NULL, status->irg_hash);
1302 /* dump per graph */
1303 for (entry = pset_first(status->irg_hash); entry; entry = pset_next(status->irg_hash)) {
1305 if (entry->irg == NULL) {
1306 /* special entry for the global count */
1310 if (! entry->is_deleted) {
1311 /* the graph is still alive, count the nodes on it */
1312 count_nodes_in_graph(global, entry);
1314 /* count the DAG's */
1315 // count_dags_in_graph(global, entry);
1317 /* calculate the pattern */
1318 stat_calc_pattern_history(entry->irg);
1323 /* clear the counter here:
1324 * we need only the edge counter to be cleared, all others are cumulative
1326 cnt_clr(&entry->cnt_edges);
1333 stat_finish_pattern_history();
1335 /* clear the global counter here */
1337 node_entry_t *entry;
1339 for (entry = pset_first(global->opcode_hash); entry; entry = pset_next(global->opcode_hash)) {
1340 opcode_clear_entry(entry);
1342 graph_clear_entry(global);
1346 // status->enable = 0;
1353 /* need this for prototypes */
1354 #define FIRM_STATISTICS
1355 #include "firmstat.h"
1357 void init_stat(unsigned enable_options) {}
1359 void stat_finish(const char *name) {}
1361 void stat_new_ir_op(const ir_op *op) {}
1363 void stat_free_ir_op(const ir_op *op) {}
1365 void stat_new_node(ir_node *node) {}
1367 void stat_turn_into_id(ir_node *node) {}
1369 void stat_new_graph(ir_graph *irg, entity *ent) {}
1371 void stat_free_graph(ir_graph *irg) {}
1373 void stat_irg_walk(ir_graph *irg, void *pre, void *post) {}
1375 void stat_irg_block_walk(ir_graph *irg, const ir_node *node, void *pre, void *post) {}
1377 void stat_merge_nodes(
1378 ir_node **new_node_array, int new_num_entries,
1379 ir_node **old_node_array, int old_num_entries,
1380 stat_opt_kind opt) {}
1382 void stat_reassociate(int start) {}
1384 void stat_lower(ir_node *node) {}
1386 void stat_inline(ir_node *call, ir_graph *irg) {}
1388 void stat_tail_rec(ir_graph *irg) {}
1390 void stat_strength_red(ir_graph *irg, ir_node *strong, ir_node *cmp) {}
1392 void stat_dead_node_elim_start(ir_graph *irg) {}
1394 void stat_dead_node_elim_stop(ir_graph *irg) {}
1396 void stat_arch_dep_replace_mul_with_shifts(ir_node *mul) {}
1398 void stat_arch_dep_replace_div_by_const(ir_node *div) {}
1400 void stat_arch_dep_replace_mod_by_const(ir_node *mod) {}
1402 void stat_arch_dep_replace_DivMod_by_const(ir_node *divmod) {}