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",
40 "a value was substituted due to a Confirm",
44 static const char *if_conv_names[IF_RESULT_LAST] = {
46 "if conv side effect ",
47 "if conv Phi node found ",
48 "if conv to deep DAG's ",
49 "if conv bad control flow ",
50 "if conv denied by arch ",
54 * dumps a opcode hash into human readable form
56 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
67 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
68 for (entry = pset_first(set); entry; entry = pset_next(set)) {
69 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
70 get_id_str(entry->op->name), entry->cnt_alive.cnt[0], entry->new_node.cnt[0], entry->into_Id.cnt[0]);
72 cnt_add(&f_alive, &entry->cnt_alive);
73 cnt_add(&f_new_node, &entry->new_node);
74 cnt_add(&f_Id, &entry->into_Id);
76 fprintf(dmp->f, "-------------------------------------------\n");
77 fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
84 * dumps an optimization hash into human readable form
86 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
88 opt_entry_t *entry = pset_first(set);
91 fprintf(dmp->f, "\n%s:\n", opt_names[index]);
92 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
94 for (; entry; entry = pset_next(set)) {
95 fprintf(dmp->f, "%-16s %8u\n",
96 get_id_str(entry->op->name), entry->count.cnt[0]);
102 * dumps the number of real_function_call optimization
104 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
106 if (! cnt_eq(cnt, 0)) {
107 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
108 fprintf(dmp->f, "%-16s %8u\n",
109 "Call", cnt->cnt[0]);
114 * dumps the number of tail_recursion optimization
116 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
118 if (num_tail_recursion > 0) {
119 fprintf(dmp->f, "\nTail recursion optimized:\n");
120 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
125 * dumps the edges count
127 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
129 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt->cnt[0]);
135 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
137 int i, dump_opts = 1;
138 block_entry_t *b_entry;
141 ir_graph *const_irg = get_const_code_irg();
143 if (entry->irg == const_irg) {
144 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
148 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
150 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
153 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
154 " was inlined : %u\n"
155 " got inlined : %u\n"
156 " strength red : %u\n"
157 " leaf function : %s\n"
158 " calls only leaf functions : %s\n"
162 " indirect calls : %u\n",
163 entry->is_deleted ? "DELETED " : "",
164 entry->cnt_walked.cnt[0], entry->cnt_walked_blocks.cnt[0],
165 entry->cnt_was_inlined.cnt[0],
166 entry->cnt_got_inlined.cnt[0],
167 entry->cnt_strength_red.cnt[0],
168 entry->is_leaf ? "YES" : "NO",
169 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
170 entry->is_recursive ? "YES" : "NO",
171 entry->is_chain_call ? "YES" : "NO",
172 entry->cnt_all_calls.cnt[0],
173 entry->cnt_indirect_calls.cnt[0]
176 for (i = 0; i < sizeof(entry->cnt_if_conv)/sizeof(entry->cnt_if_conv[0]); ++i) {
177 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], entry->cnt_if_conv[i].cnt[0]);
182 fprintf(dmp->f, "\nGlobals counts:\n");
183 fprintf(dmp->f, "--------------\n");
187 simple_dump_opcode_hash(dmp, entry->opcode_hash);
188 simple_dump_edges(dmp, &entry->cnt_edges);
190 /* effects of optimizations */
194 simple_dump_real_func_calls(dmp, &entry->cnt_real_func_call);
195 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
197 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
198 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
201 /* dump block info */
202 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
203 for (b_entry = pset_first(entry->block_hash);
205 b_entry = pset_next(entry->block_hash)) {
206 fprintf(dmp->f, "BLK %12ld %12u %12u %12u %12u %12u %4.8f\n",
208 b_entry->cnt_nodes.cnt[0],
209 b_entry->cnt_edges.cnt[0],
210 b_entry->cnt_in_edges.cnt[0],
211 b_entry->cnt_out_edges.cnt[0],
212 b_entry->cnt_phi_data.cnt[0],
213 (double)b_entry->cnt_edges.cnt[0] / (double)b_entry->cnt_nodes.cnt[0]
222 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
229 fprintf(dmp->f, "\nConstant Information:\n");
230 fprintf(dmp->f, "---------------------\n");
232 fprintf(dmp->f, "\nBit usage for integer constants\n");
233 fprintf(dmp->f, "-------------------------------\n");
235 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
236 fprintf(dmp->f, "%5d %12u\n", i + 1, tbl->int_bits_count[i].cnt[0]);
237 cnt_add(&sum, &tbl->int_bits_count[i]);
239 fprintf(dmp->f, "-------------------------------\n");
241 fprintf(dmp->f, "\nFloating point constants classification\n");
242 fprintf(dmp->f, "--------------------------------------\n");
243 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
244 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), tbl->floats[i].cnt[0]);
245 cnt_add(&sum, &tbl->floats[i]);
247 fprintf(dmp->f, "--------------------------------------\n");
249 fprintf(dmp->f, "other %12u\n", tbl->others.cnt[0]);
250 cnt_add(&sum, &tbl->others);
251 fprintf(dmp->f, "-------------------------------\n");
253 fprintf(dmp->f, "sum %12u\n", sum.cnt[0]);
257 * initialize the simple dumper
259 static void simple_init(dumper_t *dmp, const char *name)
263 snprintf(fname, sizeof(fname), "%s.txt", name);
264 dmp->f = fopen(fname, "w");
268 * finishes the simple dumper
270 static void simple_finish(dumper_t *dmp)
277 * the simple human readable dumper
279 const dumper_t simple_dumper = {
281 simple_dump_const_tbl,
289 /* ---------------------------------------------------------------------- */
292 * count the nodes as needed:
294 * 1 normal (data) Phi's
299 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
304 for (i = 0; i < 4; ++i)
307 for (entry = pset_first(graph->opcode_hash); entry; entry = pset_next(graph->opcode_hash)) {
308 if (entry->op == op_Phi) {
310 cnt_add(&cnt[1], &entry->cnt_alive);
312 else if (entry->op == dmp->status->op_PhiM) {
314 cnt_add(&cnt[2], &entry->cnt_alive);
316 else if (entry->op == op_Proj) {
318 cnt_add(&cnt[3], &entry->cnt_alive);
321 /* all other nodes */
322 cnt_add(&cnt[0], &entry->cnt_alive);
330 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
336 if (entry->irg && !entry->is_deleted) {
337 ir_graph *const_irg = get_const_code_irg();
339 if (entry->irg == const_irg) {
340 name = "<Const code Irg>";
345 name = get_entity_name(entry->ent);
347 name = "<UNKNOWN IRG>";
350 csv_count_nodes(dmp, entry, cnt);
352 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
366 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
372 * initialize the simple dumper
374 static void csv_init(dumper_t *dmp, const char *name)
378 snprintf(fname, sizeof(fname), "%s.csv", name);
379 dmp->f = fopen(fname, "a");
383 * finishes the simple dumper
385 static void csv_finish(dumper_t *dmp)
392 * the simple human readable dumper
394 const dumper_t csv_dumper = {