3 * File name: ir/ir/stat_dmp.c
4 * Purpose: Statistics for Firm.
8 * Copyright: (c) 2004 Universität Karlsruhe
9 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
19 * names of the optimizations
21 static const char *opt_names[] = {
22 "straightening optimization",
24 "constant evaluation",
25 "algebraic simplification",
27 "Write-After-Write optimization",
28 "Write-After-Read optimization",
29 "Read-After-Write optimization",
30 "Read-After-Read optimization",
31 "Read-a-Const optimization",
34 "Common subexpression elimination",
36 "Architecture dependant optimization",
37 "Reassociation optimization",
38 "Polymorphic call optimization",
39 "an if conversion was tried",
43 static const char *if_conv_names[IF_RESULT_LAST] = {
45 "if conv side effect ",
46 "if conv Phi node found ",
47 "if conv to deep DAG's ",
48 "if conv bad control flow ",
49 "if conv denied by arch ",
53 * dumps a opcode hash into human readable form
55 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
66 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
67 for (entry = pset_first(set); entry; entry = pset_next(set)) {
68 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
69 get_id_str(entry->op->name), entry->cnt_alive.cnt[0], entry->new_node.cnt[0], entry->into_Id.cnt[0]);
71 cnt_add(&f_alive, &entry->cnt_alive);
72 cnt_add(&f_new_node, &entry->new_node);
73 cnt_add(&f_Id, &entry->into_Id);
75 fprintf(dmp->f, "-------------------------------------------\n");
76 fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
83 * dumps an optimization hash into human readable form
85 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
87 opt_entry_t *entry = pset_first(set);
90 fprintf(dmp->f, "\n%s:\n", opt_names[index]);
91 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
93 for (; entry; entry = pset_next(set)) {
94 fprintf(dmp->f, "%-16s %8u\n",
95 get_id_str(entry->op->name), entry->count.cnt[0]);
101 * dumps the number of real_function_call optimization
103 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
105 if (! cnt_eq(cnt, 0)) {
106 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
107 fprintf(dmp->f, "%-16s %8u\n",
108 "Call", cnt->cnt[0]);
113 * dumps the number of tail_recursion optimization
115 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
117 if (num_tail_recursion > 0) {
118 fprintf(dmp->f, "\nTail recursion optimized:\n");
119 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
124 * dumps the edges count
126 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
128 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt->cnt[0]);
134 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
136 int i, dump_opts = 1;
137 block_entry_t *b_entry;
140 ir_graph *const_irg = get_const_code_irg();
142 if (entry->irg == const_irg) {
143 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
147 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
149 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
152 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
153 " was inlined : %u\n"
154 " got inlined : %u\n"
155 " strength red : %u\n"
156 " leaf function : %s\n"
157 " calls only leaf functions : %s\n"
161 " indirect calls : %u\n",
162 entry->is_deleted ? "DELETED " : "",
163 entry->cnt_walked.cnt[0], entry->cnt_walked_blocks.cnt[0],
164 entry->cnt_was_inlined.cnt[0],
165 entry->cnt_got_inlined.cnt[0],
166 entry->cnt_strength_red.cnt[0],
167 entry->is_leaf ? "YES" : "NO",
168 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
169 entry->is_recursive ? "YES" : "NO",
170 entry->is_chain_call ? "YES" : "NO",
171 entry->cnt_all_calls.cnt[0],
172 entry->cnt_indirect_calls.cnt[0]
175 for (i = 0; i < sizeof(entry->cnt_if_conv)/sizeof(entry->cnt_if_conv[0]); ++i) {
176 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], entry->cnt_if_conv[i].cnt[0]);
181 fprintf(dmp->f, "\nGlobals counts:\n");
182 fprintf(dmp->f, "--------------\n");
186 simple_dump_opcode_hash(dmp, entry->opcode_hash);
187 simple_dump_edges(dmp, &entry->cnt_edges);
189 /* effects of optimizations */
193 simple_dump_real_func_calls(dmp, &entry->cnt_real_func_call);
194 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
196 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
197 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
200 /* dump block info */
201 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
202 for (b_entry = pset_first(entry->block_hash);
204 b_entry = pset_next(entry->block_hash)) {
205 fprintf(dmp->f, "BLK %12ld %12u %12u %12u %12u %12u %4.8f\n",
207 b_entry->cnt_nodes.cnt[0],
208 b_entry->cnt_edges.cnt[0],
209 b_entry->cnt_in_edges.cnt[0],
210 b_entry->cnt_out_edges.cnt[0],
211 b_entry->cnt_phi_data.cnt[0],
212 (double)b_entry->cnt_edges.cnt[0] / (double)b_entry->cnt_nodes.cnt[0]
221 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
228 fprintf(dmp->f, "\nConstant Information:\n");
229 fprintf(dmp->f, "---------------------\n");
231 fprintf(dmp->f, "\nBit usage for integer constants\n");
232 fprintf(dmp->f, "-------------------------------\n");
234 for (i = 0; i < ARR_SIZE(tbl->bits_count); ++i) {
235 fprintf(dmp->f, "%5d %12u\n", i + 1, tbl->bits_count[i].cnt[0]);
236 cnt_add(&sum, &tbl->bits_count[i]);
238 fprintf(dmp->f, "other %12u\n", tbl->others.cnt[0]);
239 cnt_add(&sum, &tbl->others);
240 fprintf(dmp->f, "-------------------------------\n");
241 fprintf(dmp->f, "sum %12u\n", sum.cnt[0]);
245 * initialize the simple dumper
247 static void simple_init(dumper_t *dmp, const char *name)
251 snprintf(fname, sizeof(fname), "%s.txt", name);
252 dmp->f = fopen(fname, "w");
256 * finishes the simple dumper
258 static void simple_finish(dumper_t *dmp)
265 * the simple human readable dumper
267 const dumper_t simple_dumper = {
269 simple_dump_const_tbl,
277 /* ---------------------------------------------------------------------- */
280 * count the nodes as needed:
282 * 1 normal (data) Phi's
287 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
292 for (i = 0; i < 4; ++i)
295 for (entry = pset_first(graph->opcode_hash); entry; entry = pset_next(graph->opcode_hash)) {
296 if (entry->op == op_Phi) {
298 cnt_add(&cnt[1], &entry->cnt_alive);
300 else if (entry->op == dmp->status->op_PhiM) {
302 cnt_add(&cnt[2], &entry->cnt_alive);
304 else if (entry->op == op_Proj) {
306 cnt_add(&cnt[3], &entry->cnt_alive);
309 /* all other nodes */
310 cnt_add(&cnt[0], &entry->cnt_alive);
318 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
324 if (entry->irg && !entry->is_deleted) {
325 ir_graph *const_irg = get_const_code_irg();
327 if (entry->irg == const_irg) {
328 name = "<Const code Irg>";
333 name = get_entity_name(entry->ent);
335 name = "<UNKNOWN IRG>";
338 csv_count_nodes(dmp, entry, cnt);
340 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
354 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
360 * initialize the simple dumper
362 static void csv_init(dumper_t *dmp, const char *name)
366 snprintf(fname, sizeof(fname), "%s.csv", name);
367 dmp->f = fopen(fname, "a");
371 * finishes the simple dumper
373 static void csv_finish(dumper_t *dmp)
380 * the simple human readable dumper
382 const dumper_t csv_dumper = {