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)
225 fprintf(dmp->f, "\nConstant Information:\n");
226 fprintf(dmp->f, "---------------------\n");
228 fprintf(dmp->f, "\nBit usage for integer constants\n");
229 fprintf(dmp->f, "-------------------------------\n");
231 for (i = 0; i < ARR_SIZE(tbl->bits_count); ++i)
232 fprintf(dmp->f, "%3d %12u\n", i + 1, tbl->bits_count[i].cnt[0]);
233 fprintf(dmp->f, "-------------------------------\n");
237 * initialize the simple dumper
239 static void simple_init(dumper_t *dmp, const char *name)
243 snprintf(fname, sizeof(fname), "%s.txt", name);
244 dmp->f = fopen(fname, "w");
248 * finishes the simple dumper
250 static void simple_finish(dumper_t *dmp)
257 * the simple human readable dumper
259 const dumper_t simple_dumper = {
261 simple_dump_const_tbl,
269 /* ---------------------------------------------------------------------- */
272 * count the nodes as needed:
274 * 1 normal (data) Phi's
279 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
284 for (i = 0; i < 4; ++i)
287 for (entry = pset_first(graph->opcode_hash); entry; entry = pset_next(graph->opcode_hash)) {
288 if (entry->op == op_Phi) {
290 cnt_add(&cnt[1], &entry->cnt_alive);
292 else if (entry->op == dmp->status->op_PhiM) {
294 cnt_add(&cnt[2], &entry->cnt_alive);
296 else if (entry->op == op_Proj) {
298 cnt_add(&cnt[3], &entry->cnt_alive);
301 /* all other nodes */
302 cnt_add(&cnt[0], &entry->cnt_alive);
310 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
316 if (entry->irg && !entry->is_deleted) {
317 ir_graph *const_irg = get_const_code_irg();
319 if (entry->irg == const_irg) {
320 name = "<Const code Irg>";
325 name = get_entity_name(entry->ent);
327 name = "<UNKNOWN IRG>";
330 csv_count_nodes(dmp, entry, cnt);
332 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
346 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
352 * initialize the simple dumper
354 static void csv_init(dumper_t *dmp, const char *name)
358 snprintf(fname, sizeof(fname), "%s.csv", name);
359 dmp->f = fopen(fname, "a");
363 * finishes the simple dumper
365 static void csv_finish(dumper_t *dmp)
372 * the simple human readable dumper
374 const dumper_t csv_dumper = {