2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Statistics for Firm. Dumping.
23 * @author Michael Beck
35 * names of the optimizations
41 { HOOK_OPT_DEAD_BLOCK, "dead block elimination" },
42 { HOOK_OPT_STG, "straightening optimization" },
43 { HOOK_OPT_IFSIM, "if simplification" },
44 { HOOK_OPT_CONST_EVAL, "constant evaluation" },
45 { HOOK_OPT_ALGSIM, "algebraic simplification" },
46 { HOOK_OPT_PHI, "Phi optmization" },
47 { HOOK_OPT_SYNC, "Sync optmization" },
48 { HOOK_OPT_WAW, "Write-After-Write optimization" },
49 { HOOK_OPT_WAR, "Write-After-Read optimization" },
50 { HOOK_OPT_RAW, "Read-After-Write optimization" },
51 { HOOK_OPT_RAR, "Read-After-Read optimization" },
52 { HOOK_OPT_RC, "Read-a-Const optimization" },
53 { HOOK_OPT_TUPLE, "Tuple optimization" },
54 { HOOK_OPT_ID, "ID optimization" },
55 { HOOK_OPT_CSE, "Common subexpression elimination" },
56 { HOOK_OPT_STRENGTH_RED, "Strength reduction" },
57 { HOOK_OPT_ARCH_DEP, "Architecture dependant optimization" },
58 { HOOK_OPT_REASSOC, "Reassociation optimization" },
59 { HOOK_OPT_POLY_CALL, "Polymorphic call optimization" },
60 { HOOK_OPT_IF_CONV, "an if conversion was tried" },
61 { HOOK_OPT_FUNC_CALL, "Real function call optimization" },
62 { HOOK_OPT_CONFIRM, "Confirm-based optimization: replacement" },
63 { HOOK_OPT_CONFIRM_C, "Confirm-based optimization: replaced by const" },
64 { HOOK_OPT_CONFIRM_E, "Confirm-based optimization: evaluated" },
65 { HOOK_OPT_EXC_REM, "a exception edge was removed due to a Confirmation prove" },
66 { HOOK_LOWERED, "Lowered" },
67 { HOOK_BACKEND, "Backend transformation" },
68 { FS_OPT_NEUTRAL_0, "algebraic simplification: a op 0 = 0 op a = a" },
69 { FS_OPT_NEUTRAL_1, "algebraic simplification: a op 1 = 1 op a = a" },
70 { FS_OPT_ADD_A_A, "algebraic simplification: a + a = a * 2" },
71 { FS_OPT_ADD_A_MINUS_B, "algebraic simplification: a + -b = a - b" },
72 { FS_OPT_ADD_SUB, "algebraic simplification: (a + x) - x = (a - x) + x = a" },
73 { FS_OPT_ADD_MUL_A_X_A, "algebraic simplification: a * x + a = a * (x + 1)" },
74 { FS_OPT_SUB_0_A, "algebraic simplification: 0 - a = -a" },
75 { FS_OPT_MINUS_SUB, "algebraic simplification: -(a - b) = b - a" },
76 { FS_OPT_SUB_MINUS, "algebraic simplification: a - (-b) = a + b" },
77 { FS_OPT_SUB_MUL_A_X_A, "algebraic simplification: a * x - a = a * (x - 1)" },
78 { FS_OPT_SUB_SUB_X_Y_Z, "algebraic simplification: (x - y) - z = x - (y + z)" },
79 { FS_OPT_SUB_C_NOT_X, "algebraic simplification: c - ~a = a + (c+1)" },
80 { FS_OPT_SUB_TO_ADD, "algebraic simplification: (-a) - b = -(a + b), a - (b - c) = a + (c - b), a - (b * C) = a + (b * -C)" },
81 { FS_OPT_SUB_TO_NOT, "algebraic simplification: -1 - x -> ~x" },
82 { FS_OPT_SUB_TO_CONV, "algebraic simplification: a - NULL = (int)a" },
83 { FS_OPT_MUL_MINUS, "algebraic simplification: (-a) * (b - c) = a * (c - b)" },
84 { FS_OPT_MUL_MINUS_1, "algebraic simplification: a * -1 = -a" },
85 { FS_OPT_MINUS_MUL_C, "algebraic simplification: (-a) * C = a * (-C)" },
86 { FS_OPT_MUL_MINUS_MINUS,"algebraic simplification: (-a) * (-b) = a * b" },
87 { FS_OPT_OR, "algebraic simplification: a | a = a | 0 = 0 | a = a" },
88 { FS_OPT_AND, "algebraic simplification: a & 0b1...1 = 0b1...1 & a = a & a = (a|X) & a = a" },
89 { FS_OPT_TO_EOR, "algebraic simplification: (a|b) & ~(a&b) = a^b" },
90 { FS_OPT_EOR_A_A, "algebraic simplification: a ^ a = 0" },
91 { FS_OPT_EOR_A_B_A, "algebraic simplification: (a ^ b) ^ a = b" },
92 { FS_OPT_EOR_TO_NOT_BOOL,"boolean simplification: bool ^ 1 = !bool" },
93 { FS_OPT_EOR_TO_NOT, "algebraic simplification: x ^ 0b1..1 = ~x, (a ^ b) & b = ~a & b" },
94 { FS_OPT_NOT_CMP, "algebraic simplification: !(a cmp b) = a !cmp b" },
95 { FS_OPT_OR_SHFT_TO_ROTL,"algebraic simplification: (x << c) | (x >> (bits - c)) == Rotl(x, c)" },
96 { FS_OPT_REASSOC_SHIFT, "algebraic simplification: (x SHF c1) SHF c2 = x SHF (c1+c2)" },
97 { FS_OPT_SHIFT_AND, "algebraic simplification: (a SHF c) AND (b SHF c) = (a AND b) SHF c" },
98 { FS_OPT_SHIFT_OR, "algebraic simplification: (a SHF c) OR (b SHF c) = (a OR b) SHF c" },
99 { FS_OPT_SHIFT_EOR, "algebraic simplification: (a SHF c) XOR (b SHF c) = (a XOR b) SHF c" },
100 { FS_OPT_CONV, "algebraic simplification: Conv could be removed" },
101 { FS_OPT_CAST, "algebraic simplification: a Cast could be removed" },
102 { FS_OPT_MIN_MAX_EQ, "algebraic simplification: Min(a,a) = Max(a,a) = a" },
103 { FS_OPT_MUX_BOOL, "boolean simplification: Muxb(sel, true, false) = sel" },
104 { FS_OPT_MUX_NOT_BOOL, "boolean simplification: Muxb(sel, false, true) = Not(sel)" },
105 { FS_OPT_MUX_OR_BOOL, "boolean simplification: Muxb(sel, true, x) = Or(sel, x)" },
106 { FS_OPT_MUX_ORNOT_BOOL, "boolean simplification: Muxb(sel, x, true) = Or(Not(sel), x)" },
107 { FS_OPT_MUX_AND_BOOL, "boolean simplification: Muxb(sel, x, false) = And(sel, x)" },
108 { FS_OPT_MUX_ANDNOT_BOOL,"boolean simplification: Muxb(sel, false, x) = And(Not(sel), x)" },
109 { FS_OPT_MUX_C, "algebraic simplification: Mux(C, f, t) = C ? t : f" },
110 { FS_OPT_MUX_EQ, "algebraic simplification: Mux(v, x, x) = x" },
111 { FS_OPT_MUX_TRANSFORM, "algebraic simplification: Mux(t ==/!= f, t, f) = f/t, Mux(t ==/!= 0, -t, t) = -t/t" },
112 { FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
113 { FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
114 { FS_OPT_MUX_TO_ABS, "algebraic simplification: Mux(a > 0, a, -a) = Abs(a)" },
115 { FS_OPT_IDEM_UNARY, "algebraic simplification: Idempotent unary operation" },
116 { FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
117 { FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
118 { FS_OPT_NOT_PLUS_1, "algebraic simplification: ~x + 1 = -x" },
119 { FS_OPT_ADD_X_NOT_X, "algebraic simplification: ~x + x = -1" },
120 { FS_OPT_FP_INV_MUL, "algebraic simplification: x / y = x * (1.0/y)" },
121 { FS_OPT_ABS_MINUS_X, "algebraic simplification: Abs(-x) = Abs(x)" },
122 { FS_OPT_CONST_PHI, "constant evaluation on Phi node" },
123 { FS_OPT_PREDICATE, "predicate optimization" },
124 { FS_OPT_DEMORGAN, "optimization using DeMorgan's law" },
125 { FS_OPT_CMP_OP_OP, "CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y)" },
126 { FS_OPT_CMP_OP_C, "CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2)" },
127 { FS_OPT_CMP_CONV_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y)" },
128 { FS_OPT_CMP_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y)" },
129 { FS_OPT_CMP_TO_BOOL, "CMP optimization: Cmp(x, y) = BoolOP(x, y)" },
130 { FS_OPT_CMP_CNST_MAGN, "CMP optimization: reduced magnitude of a const" },
131 { FS_OPT_CMP_SHF_TO_AND, "CMP optimization: transformed shift into And" },
132 { FS_OPT_CMP_MOD_TO_AND, "CMP optimization: transformed Mod into And" },
133 { FS_OPT_NOP, "the operation is a NOP" },
134 { FS_OPT_GVN_FOLLOWER, "GVN-PRE: replaced a follower" },
135 { FS_OPT_GVN_FULLY, "GVN-PRE: replaced by fully redundant value" },
136 { FS_OPT_GVN_PARTLY, "GVN-PRE: replaced by partly redundant value" },
137 { FS_OPT_COMBO_CONST, "Combo: evaluated into Constant" },
138 { FS_OPT_COMBO_CF, "Combo: removed conditional control flow" },
139 { FS_OPT_COMBO_FOLLOWER, "Combo: removed a follower" },
140 { FS_OPT_COMBO_CONGRUENT,"Combo: replaced by congruent" },
141 { FS_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
142 { FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
143 { FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
144 { FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
145 { FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
146 { FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
147 { FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
148 { FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
149 { FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
150 { FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
151 { FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
152 { FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
153 { FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
154 { FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
155 { FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
156 { FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
157 { FS_OPT_RTS_SYMMETRIC, "RTS optimization: call to symmetric function f(-x) replaced by f(x)" },
158 { FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
159 { FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
160 { FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
161 { FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
162 { FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
163 { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
164 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
165 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
166 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
167 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
168 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
169 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
170 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
171 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
172 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
173 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
176 static const char *if_conv_names[IF_RESULT_LAST] = {
178 "if conv side effect ",
179 "if conv Phi node found ",
180 "if conv to deep DAG's ",
181 "if conv bad control flow ",
182 "if conv denied by arch ",
186 * dumps a opcode hash into human readable form
188 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
192 counter_t f_new_node;
196 cnt_clr(&f_new_node);
199 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
200 foreach_pset(set, entry) {
201 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
202 get_id_str(entry->op->name),
203 cnt_to_uint(&entry->cnt_alive),
204 cnt_to_uint(&entry->new_node),
205 cnt_to_uint(&entry->into_Id)
208 cnt_add(&f_alive, &entry->cnt_alive);
209 cnt_add(&f_new_node, &entry->new_node);
210 cnt_add(&f_Id, &entry->into_Id);
212 fprintf(dmp->f, "-------------------------------------------\n");
213 fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
214 cnt_to_uint(&f_alive),
215 cnt_to_uint(&f_new_node),
218 } /* simple_dump_opcode_hash */
221 * Return the name of an optimization.
223 static const char *get_opt_name(int index) {
224 assert(index < (int) ARR_SIZE(opt_names) && "index out of range");
225 assert((int) opt_names[index].kind == index && "opt_names broken");
226 return opt_names[index].name;
230 * dumps an optimization hash into human readable form
232 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
234 if (pset_count(set) > 0) {
236 const char *name = get_opt_name(index);
238 fprintf(dmp->f, "\n%s:\n", name);
239 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
241 foreach_pset(set, entry) {
242 fprintf(dmp->f, "%-16s %8u\n",
243 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
246 } /* simple_dump_opt_hash */
249 * dumps the register pressure for each block and for each register class
251 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
253 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
254 reg_pressure_entry_t *rp_entry;
256 /* return if no be statistic information available */
260 fprintf(dmp->f, "\nREG PRESSURE:\n");
261 fprintf(dmp->f, "%12s", "Block Nr");
263 /* print table head (register class names) */
264 foreach_pset(b_entry->reg_pressure, rp_entry)
265 fprintf(dmp->f, "%15s", rp_entry->class_name);
266 fprintf(dmp->f, "\n");
268 /* print the reg pressure for all blocks and register classes */
269 for (/* b_entry is already initialized */ ;
271 b_entry = pset_next(entry->be_block_hash)) {
272 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
274 foreach_pset(b_entry->reg_pressure, rp_entry)
275 fprintf(dmp->f, "%15d", rp_entry->pressure);
276 fprintf(dmp->f, "\n");
278 } /* simple_dump_be_block_reg_pressure */
280 /** prints a distribution entry */
281 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
283 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
284 } /* simple_dump_distrib_entry */
287 * dumps the distribution of the amount of ready nodes for each block
289 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
291 if (pset_count(entry->be_block_hash) > 0) {
292 be_block_entry_t *b_entry;
295 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
296 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
297 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
299 foreach_pset(entry->be_block_hash, b_entry) {
300 /* this ensures that all keys from 1 to 5 are in the table */
301 for (i = 1; i < 6; ++i)
302 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
304 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
305 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
306 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
307 fprintf(dmp->f, "\n");
310 } /* simple_dump_be_block_sched_ready */
313 * Adds the counter for given entry to another distribution table.
315 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
316 distrib_tbl_t *sum_tbl = env;
318 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
319 } /* add_distrib_entry */
322 * dumps permutation statistics for one and block and one class
324 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
326 perm_stat_entry_t *ps_ent;
327 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
328 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
332 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
341 foreach_pset(entry->perm_stat, ps_ent) {
342 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
345 stat_get_count_distrib_tbl(ps_ent->chains),
346 stat_get_count_distrib_tbl(ps_ent->cycles),
351 /* sum up distribution table for chains */
352 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
354 /* sum up distribution table for cycles */
355 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
358 /* print chain distribution for all perms of this class in this block */
359 fprintf(dmp->f, "chain distribution:\n");
361 /* add all missing entries to chain distribution table */
362 for (i = 1; i <= entry->n_regs; i++) {
363 snprintf(buf, sizeof(buf), "length %d", i);
364 fprintf(dmp->f, "%12s", buf);
365 stat_insert_int_distrib_tbl(sum_chains, i);
367 fprintf(dmp->f, "\n");
368 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
369 fprintf(dmp->f, "\n");
371 /* print cycle distribution for all perms of this class in this block */
372 fprintf(dmp->f, "cycle distribution:\n");
374 /* add all missing entries to cycle distribution table */
375 for (i = 1; i <= entry->n_regs; i++) {
376 snprintf(buf, sizeof(buf), "length %d", i);
377 fprintf(dmp->f, "%12s", buf);
378 stat_insert_int_distrib_tbl(sum_cycles, i);
380 fprintf(dmp->f, "\n");
381 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
382 fprintf(dmp->f, "\n");
384 /* delete temporary sum distribution tables */
385 stat_delete_distrib_tbl(sum_chains);
386 stat_delete_distrib_tbl(sum_cycles);
388 } /* simple_dump_be_block_permstat_class */
391 * dumps statistics about perms
393 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
395 if (pset_count(entry->be_block_hash) > 0) {
396 be_block_entry_t *b_entry;
398 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
399 foreach_pset(entry->be_block_hash, b_entry) {
400 perm_class_entry_t *pc_ent;
402 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
404 if (b_entry->perm_class_stat) {
405 foreach_pset(b_entry->perm_class_stat, pc_ent) {
406 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
407 simple_dump_be_block_permstat_class(dmp, pc_ent);
412 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
414 } /* simple_dump_be_block_permstat */
417 * dumps the number of real_function_call optimization
419 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
424 if (! cnt_eq(cnt, 0)) {
425 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
426 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
428 } /* simple_dump_real_func_calls */
431 * dumps the number of tail_recursion optimization
433 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
438 if (num_tail_recursion > 0) {
439 fprintf(dmp->f, "\nTail recursion optimized:\n");
440 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
442 } /* simple_dump_tail_recursion */
445 * dumps the edges count
447 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
452 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
453 } /* simple_dump_edges */
458 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
460 int i, dump_opts = 1;
461 block_entry_t *b_entry;
462 extbb_entry_t *eb_entry;
468 ir_graph *const_irg = get_const_code_irg();
470 if (entry->irg == const_irg)
471 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
474 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
476 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
479 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
480 " was inlined : %u\n"
481 " got inlined : %u\n"
482 " strength red : %u\n"
483 " leaf function : %s\n"
484 " calls only leaf functions : %s\n"
488 " indirect calls : %u\n"
489 " external calls : %u\n",
490 entry->is_deleted ? "DELETED " : "",
491 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
492 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
493 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
494 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
495 entry->is_leaf ? "YES" : "NO",
496 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
497 entry->is_recursive ? "YES" : "NO",
498 entry->is_chain_call ? "YES" : "NO",
499 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
500 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
501 cnt_to_uint(&entry->cnt[gcnt_external_calls])
504 for (i = 0; i < IF_RESULT_LAST; ++i) {
505 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
508 fprintf(dmp->f, "\nGlobals counts:\n");
509 fprintf(dmp->f, "--------------\n");
515 " pure address calc ops : %u\n"
516 " all address calc ops : %u\n",
517 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
518 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
521 /* Load/Store address classification */
523 " global Ld/St address : %u\n"
524 " local Ld/St address : %u\n"
525 " this Ld/St address : %u\n"
526 " param Ld/St address : %u\n"
527 " other Ld/St address : %u\n",
528 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
529 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
530 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
531 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
532 cnt_to_uint(&entry->cnt[gcnt_other_adr])
535 simple_dump_opcode_hash(dmp, entry->opcode_hash);
536 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
538 /* effects of optimizations */
542 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
543 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
545 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
546 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
549 /* dump block info */
550 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
551 foreach_pset(entry->block_hash, b_entry) {
552 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
554 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
555 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
556 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
557 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
558 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
559 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
560 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
564 /* dump block reg pressure */
565 simple_dump_be_block_reg_pressure(dmp, entry);
567 /* dump block ready nodes distribution */
568 simple_dump_be_block_sched_ready(dmp, entry);
570 /* dump block permutation statistics */
571 simple_dump_be_block_permstat(dmp, entry);
573 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
574 /* dump extended block info */
575 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
576 foreach_pset(entry->extbb_hash, eb_entry) {
577 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
579 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
580 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
581 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
582 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
583 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
584 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
589 } /* simple_dump_graph */
592 * dumps the constant table
594 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
604 fprintf(dmp->f, "\nConstant Information:\n");
605 fprintf(dmp->f, "---------------------\n");
607 fprintf(dmp->f, "\nBit usage for integer constants\n");
608 fprintf(dmp->f, "-------------------------------\n");
610 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
611 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
612 cnt_add(&sum, &tbl->int_bits_count[i]);
614 fprintf(dmp->f, "-------------------------------\n");
616 fprintf(dmp->f, "\nFloating point constants classification\n");
617 fprintf(dmp->f, "--------------------------------------\n");
618 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
619 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
620 cnt_add(&sum, &tbl->floats[i]);
622 fprintf(dmp->f, "--------------------------------------\n");
624 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
625 cnt_add(&sum, &tbl->others);
626 fprintf(dmp->f, "-------------------------------\n");
628 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
629 } /* simple_dump_const_tbl */
632 * Dumps a line of the parameter table
634 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
637 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
638 } /* dump_tbl_line */
641 * dumps the parameter distribution table
643 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
644 fprintf(dmp->f, "\nCall parameter Information:\n");
645 fprintf(dmp->f, "---------------------\n");
647 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
648 fprintf(dmp->f, "-------------------------------\n");
650 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
651 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
652 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
653 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
654 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
655 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
656 } /* simple_dump_param_tbl */
659 * dumps the optimization counter table
661 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
664 fprintf(dmp->f, "\nOptimization counts:\n");
665 fprintf(dmp->f, "---------------------\n");
667 for (i = 0; i < len; ++i) {
668 unsigned cnt = cnt_to_uint(&tbl[i]);
671 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
674 } /* simple_dump_opt_cnt */
677 * initialize the simple dumper
679 static void simple_init(dumper_t *dmp, const char *name) {
682 snprintf(fname, sizeof(fname), "%s.txt", name);
683 dmp->f = fopen(fname, "w");
690 * finishes the simple dumper
692 static void simple_finish(dumper_t *dmp) {
696 } /* simple_finish */
699 * the simple human readable dumper
701 const dumper_t simple_dumper = {
703 simple_dump_const_tbl,
704 simple_dump_param_tbl,
712 FOURCC('S', 'M', 'P', 'L'),
715 /* ---------------------------------------------------------------------- */
718 * count the nodes as needed:
720 * 1 normal (data) Phi's
725 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
730 for (i = 0; i < 4; ++i)
733 foreach_pset(graph->opcode_hash, entry) {
734 if (entry->op == op_Phi) {
736 cnt_add(&cnt[1], &entry->cnt_alive);
737 } else if (entry->op == dmp->status->op_PhiM) {
739 cnt_add(&cnt[2], &entry->cnt_alive);
740 } else if (entry->op == op_Proj) {
742 cnt_add(&cnt[3], &entry->cnt_alive);
744 /* all other nodes */
745 cnt_add(&cnt[0], &entry->cnt_alive);
748 } /* csv_count_nodes */
753 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
761 if (entry->irg && !entry->is_deleted) {
762 ir_graph *const_irg = get_const_code_irg();
764 if (entry->irg == const_irg) {
765 name = "<Const code Irg>";
769 name = get_entity_name(entry->ent);
771 name = "<UNKNOWN IRG>";
774 csv_count_nodes(dmp, entry, cnt);
776 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
779 cnt_to_uint(&cnt[0]),
780 cnt_to_uint(&cnt[1]),
781 cnt_to_uint(&cnt[2]),
785 } /* csv_dump_graph */
790 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
795 } /* csv_dump_const_tbl */
798 * dumps the parameter distribution table
800 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
805 } /* csv_dump_param_tbl */
808 * dumps the optimization counter
810 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
815 } /* csv_dump_opt_cnt */
818 * initialize the simple dumper
820 static void csv_init(dumper_t *dmp, const char *name)
824 snprintf(fname, sizeof(fname), "%s.csv", name);
825 dmp->f = fopen(fname, "a");
831 * finishes the simple dumper
833 static void csv_finish(dumper_t *dmp)
841 * the simple human readable dumper
843 const dumper_t csv_dumper = {
854 FOURCC('C', 'S', 'V', '\0')