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
25 { HOOK_OPT_STG, "straightening optimization" },
26 { HOOK_OPT_IFSIM, "if simplification" },
27 { HOOK_OPT_CONST_EVAL, "constant evaluation" },
28 { HOOK_OPT_ALGSIM, "algebraic simplification" },
29 { HOOK_OPT_PHI, "Phi optmization" },
30 { HOOK_OPT_WAW, "Write-After-Write optimization" },
31 { HOOK_OPT_WAR, "Write-After-Read optimization" },
32 { HOOK_OPT_RAW, "Read-After-Write optimization" },
33 { HOOK_OPT_RAR, "Read-After-Read optimization" },
34 { HOOK_OPT_RC, "Read-a-Const optimization" },
35 { HOOK_OPT_TUPLE, "Tuple optimization" },
36 { HOOK_OPT_ID, "ID optimization" },
37 { HOOK_OPT_CSE, "Common subexpression elimination" },
38 { HOOK_OPT_STRENGTH_RED, "Strength reduction" },
39 { HOOK_OPT_ARCH_DEP, "Architecture dependant optimization" },
40 { HOOK_OPT_REASSOC, "Reassociation optimization" },
41 { HOOK_OPT_POLY_CALL, "Polymorphic call optimization" },
42 { HOOK_OPT_IF_CONV, "an if conversion was tried" },
43 { HOOK_OPT_FUNC_CALL, "Real function call optimization" },
44 { HOOK_OPT_CONFIRM, "Confirm-based optimization: replacement" },
45 { HOOK_OPT_CONFIRM_C, "Confirm-based optimization: replaced by const" },
46 { HOOK_OPT_CONFIRM_E, "Confirm-based optimization: evaluated" },
47 { HOOK_LOWERED, "Lowered" },
50 static const char *if_conv_names[IF_RESULT_LAST] = {
52 "if conv side effect ",
53 "if conv Phi node found ",
54 "if conv to deep DAG's ",
55 "if conv bad control flow ",
56 "if conv denied by arch ",
60 * dumps a opcode hash into human readable form
62 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
73 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
74 for (entry = pset_first(set); entry; entry = pset_next(set)) {
75 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
76 get_id_str(entry->op->name), entry->cnt_alive.cnt[0], entry->new_node.cnt[0], entry->into_Id.cnt[0]);
78 cnt_add(&f_alive, &entry->cnt_alive);
79 cnt_add(&f_new_node, &entry->new_node);
80 cnt_add(&f_Id, &entry->into_Id);
82 fprintf(dmp->f, "-------------------------------------------\n");
83 fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
90 * dumps an optimization hash into human readable form
92 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
94 opt_entry_t *entry = pset_first(set);
96 assert(index < ARR_SIZE(opt_names) && "index out of range");
97 assert(opt_names[index].kind == index && "opt_names broken");
99 fprintf(dmp->f, "\n%s:\n", opt_names[index].name);
100 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
102 for (; entry; entry = pset_next(set)) {
103 fprintf(dmp->f, "%-16s %8u\n",
104 get_id_str(entry->op->name), entry->count.cnt[0]);
110 * dumps the number of real_function_call optimization
112 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
114 if (! cnt_eq(cnt, 0)) {
115 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
116 fprintf(dmp->f, "%-16s %8u\n",
117 "Call", cnt->cnt[0]);
122 * dumps the number of tail_recursion optimization
124 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
126 if (num_tail_recursion > 0) {
127 fprintf(dmp->f, "\nTail recursion optimized:\n");
128 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
133 * dumps the edges count
135 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
137 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt->cnt[0]);
143 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
145 int i, dump_opts = 1;
146 block_entry_t *b_entry;
149 ir_graph *const_irg = get_const_code_irg();
151 if (entry->irg == const_irg) {
152 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
156 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
158 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
161 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
162 " was inlined : %u\n"
163 " got inlined : %u\n"
164 " strength red : %u\n"
165 " leaf function : %s\n"
166 " calls only leaf functions : %s\n"
170 " indirect calls : %u\n",
171 entry->is_deleted ? "DELETED " : "",
172 entry->cnt_walked.cnt[0], entry->cnt_walked_blocks.cnt[0],
173 entry->cnt_was_inlined.cnt[0],
174 entry->cnt_got_inlined.cnt[0],
175 entry->cnt_strength_red.cnt[0],
176 entry->is_leaf ? "YES" : "NO",
177 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
178 entry->is_recursive ? "YES" : "NO",
179 entry->is_chain_call ? "YES" : "NO",
180 entry->cnt_all_calls.cnt[0],
181 entry->cnt_indirect_calls.cnt[0]
184 for (i = 0; i < sizeof(entry->cnt_if_conv)/sizeof(entry->cnt_if_conv[0]); ++i) {
185 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], entry->cnt_if_conv[i].cnt[0]);
190 fprintf(dmp->f, "\nGlobals counts:\n");
191 fprintf(dmp->f, "--------------\n");
195 simple_dump_opcode_hash(dmp, entry->opcode_hash);
196 simple_dump_edges(dmp, &entry->cnt_edges);
198 /* effects of optimizations */
202 simple_dump_real_func_calls(dmp, &entry->cnt_real_func_call);
203 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
205 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
206 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
209 /* dump block info */
210 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
211 for (b_entry = pset_first(entry->block_hash);
213 b_entry = pset_next(entry->block_hash)) {
214 fprintf(dmp->f, "BLK %12ld %12u %12u %12u %12u %12u %4.8f\n",
216 b_entry->cnt_nodes.cnt[0],
217 b_entry->cnt_edges.cnt[0],
218 b_entry->cnt_in_edges.cnt[0],
219 b_entry->cnt_out_edges.cnt[0],
220 b_entry->cnt_phi_data.cnt[0],
221 (double)b_entry->cnt_edges.cnt[0] / (double)b_entry->cnt_nodes.cnt[0]
230 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
237 fprintf(dmp->f, "\nConstant Information:\n");
238 fprintf(dmp->f, "---------------------\n");
240 fprintf(dmp->f, "\nBit usage for integer constants\n");
241 fprintf(dmp->f, "-------------------------------\n");
243 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
244 fprintf(dmp->f, "%5d %12u\n", i + 1, tbl->int_bits_count[i].cnt[0]);
245 cnt_add(&sum, &tbl->int_bits_count[i]);
247 fprintf(dmp->f, "-------------------------------\n");
249 fprintf(dmp->f, "\nFloating point constants classification\n");
250 fprintf(dmp->f, "--------------------------------------\n");
251 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
252 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), tbl->floats[i].cnt[0]);
253 cnt_add(&sum, &tbl->floats[i]);
255 fprintf(dmp->f, "--------------------------------------\n");
257 fprintf(dmp->f, "other %12u\n", tbl->others.cnt[0]);
258 cnt_add(&sum, &tbl->others);
259 fprintf(dmp->f, "-------------------------------\n");
261 fprintf(dmp->f, "sum %12u\n", sum.cnt[0]);
265 * initialize the simple dumper
267 static void simple_init(dumper_t *dmp, const char *name)
271 snprintf(fname, sizeof(fname), "%s.txt", name);
272 dmp->f = fopen(fname, "w");
276 * finishes the simple dumper
278 static void simple_finish(dumper_t *dmp)
285 * the simple human readable dumper
287 const dumper_t simple_dumper = {
289 simple_dump_const_tbl,
297 /* ---------------------------------------------------------------------- */
300 * count the nodes as needed:
302 * 1 normal (data) Phi's
307 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
312 for (i = 0; i < 4; ++i)
315 for (entry = pset_first(graph->opcode_hash); entry; entry = pset_next(graph->opcode_hash)) {
316 if (entry->op == op_Phi) {
318 cnt_add(&cnt[1], &entry->cnt_alive);
320 else if (entry->op == dmp->status->op_PhiM) {
322 cnt_add(&cnt[2], &entry->cnt_alive);
324 else if (entry->op == op_Proj) {
326 cnt_add(&cnt[3], &entry->cnt_alive);
329 /* all other nodes */
330 cnt_add(&cnt[0], &entry->cnt_alive);
338 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
344 if (entry->irg && !entry->is_deleted) {
345 ir_graph *const_irg = get_const_code_irg();
347 if (entry->irg == const_irg) {
348 name = "<Const code Irg>";
353 name = get_entity_name(entry->ent);
355 name = "<UNKNOWN IRG>";
358 csv_count_nodes(dmp, entry, cnt);
360 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
374 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
380 * initialize the simple dumper
382 static void csv_init(dumper_t *dmp, const char *name)
386 snprintf(fname, sizeof(fname), "%s.csv", name);
387 dmp->f = fopen(fname, "a");
391 * finishes the simple dumper
393 static void csv_finish(dumper_t *dmp)
400 * the simple human readable dumper
402 const dumper_t csv_dumper = {