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_MUL_MINUS, "algebraic simplification: (-a) * (b - c) = a * (c - b)" },
82 { FS_OPT_MUL_MINUS_1, "algebraic simplification: a * -1 = -a" },
83 { FS_OPT_MINUS_MUL_C, "algebraic simplification: (-a) * C = a * (-C)" },
84 { FS_OPT_MUL_MINUS_MINUS,"algebraic simplification: (-a) * (-b) = a * b" },
85 { FS_OPT_OR, "algebraic simplification: a | a = a | 0 = 0 | a = a" },
86 { FS_OPT_AND, "algebraic simplification: a & 0b1...1 = 0b1...1 & a = a & a = (a|X) & a = a" },
87 { FS_OPT_TO_EOR, "algebraic simplification: (a|b) & ~(a&b) = a^b" },
88 { FS_OPT_EOR_A_A, "algebraic simplification: a ^ a = 0" },
89 { FS_OPT_EOR_TO_NOT_BOOL,"algebraic simplification: bool ^ 1 = !bool" },
90 { FS_OPT_EOR_TO_NOT, "algebraic simplification: x ^ 0b1..1 = ~x, (a ^ b) & b = ~a & b" },
91 { FS_OPT_NOT_CMP, "algebraic simplification: !(a cmp b) = a !cmp b" },
92 { FS_OPT_OR_SHFT_TO_ROT, "algebraic simplification: (x << c) | (x >> (bits - c)) == Rot(x, c)" },
93 { FS_OPT_REASSOC_SHIFT, "algebraic simplification: (x SHF c1) SHF c2 = x SHF (c1+c2)" },
94 { FS_OPT_SHIFT_AND, "algebraic simplification: (a SHF c) AND (b SHF c) = (a AND b) SHF c" },
95 { FS_OPT_SHIFT_OR, "algebraic simplification: (a SHF c) OR (b SHF c) = (a OR b) SHF c" },
96 { FS_OPT_SHIFT_EOR, "algebraic simplification: (a SHF c) XOR (b SHF c) = (a XOR b) SHF c" },
97 { FS_OPT_CONV, "algebraic simplification: Conv could be removed" },
98 { FS_OPT_CAST, "algebraic simplification: a Cast could be removed" },
99 { FS_OPT_MIN_MAX_EQ, "algebraic simplification: Min(a,a) = Max(a,a) = a" },
100 { FS_OPT_MUX_C, "algebraic simplification: Mux(C, f, t) = C ? t : f" },
101 { FS_OPT_MUX_EQ, "algebraic simplification: Mux(v, x, x) = x" },
102 { FS_OPT_MUX_TRANSFORM, "algebraic simplification: Mux(a, b, c) = b OR Mux(a,b, c) = c" },
103 { FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
104 { FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
105 { FS_OPT_MUX_TO_ABS, "algebraic simplification: Mux(a > b, a, b) = Abs(a,b)" },
106 { FS_OPT_MUX_TO_SHR, "algebraic simplification: Mux(a > b, a, b) = a >> b" },
107 { FS_OPT_IDEM_UNARY, "algebraic simplification: Idempotent unary operation" },
108 { FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
109 { FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
110 { FS_OPT_NOT_PLUS_1, "algebraic simplification: ~x + 1 = -x" },
111 { FS_OPT_ADD_X_NOT_X, "algebraic simplification: ~x + x = -1" },
112 { FS_OPT_FP_INV_MUL, "algebraic simplification: x / y = x * (1.0/y)" },
113 { FS_OPT_ABS_MINUS_X, "algebraic simplification: Abs(-x) = Abs(x)" },
114 { FS_OPT_CONST_PHI, "constant evaluation on Phi node" },
115 { FS_OPT_PREDICATE, "predicate optimization" },
116 { FS_OPT_DEMORGAN, "optimization using DeMorgan's law" },
117 { FS_OPT_CMP_OP_OP, "CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y)" },
118 { FS_OPT_CMP_OP_C, "CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2)" },
119 { FS_OPT_CMP_CONV_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y)" },
120 { FS_OPT_CMP_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y)" },
121 { FS_OPT_CMP_TO_BOOL, "CMP optimization: Cmp(x, y) = BoolOP(x, y)" },
122 { FS_OPT_CMP_CNST_MAGN, "CMP optimization: reduced magnitude of a const" },
123 { FS_OPT_CMP_SHF_TO_AND, "CMP optimization: transformed shift into And" },
124 { FS_OPT_CMP_MOD_TO_AND, "CMP optimization: transformed Mod into And" },
125 { FS_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
126 { FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
127 { FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
128 { FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
129 { FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
130 { FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
131 { FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
132 { FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
133 { FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
134 { FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
135 { FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
136 { FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
137 { FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
138 { FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
139 { FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
140 { FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
141 { FS_OPT_RTS_SYMMETRIC, "RTS optimization: call to symmetric function f(-x) replaced by f(x)" },
142 { FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
143 { FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
144 { FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
145 { FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
146 { FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
147 { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
148 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
149 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
150 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
151 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
152 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
153 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
154 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
155 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
156 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
157 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
160 static const char *if_conv_names[IF_RESULT_LAST] = {
162 "if conv side effect ",
163 "if conv Phi node found ",
164 "if conv to deep DAG's ",
165 "if conv bad control flow ",
166 "if conv denied by arch ",
170 * dumps a opcode hash into human readable form
172 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
176 counter_t f_new_node;
180 cnt_clr(&f_new_node);
183 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
184 foreach_pset(set, entry) {
185 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
186 get_id_str(entry->op->name),
187 cnt_to_uint(&entry->cnt_alive),
188 cnt_to_uint(&entry->new_node),
189 cnt_to_uint(&entry->into_Id)
192 cnt_add(&f_alive, &entry->cnt_alive);
193 cnt_add(&f_new_node, &entry->new_node);
194 cnt_add(&f_Id, &entry->into_Id);
196 fprintf(dmp->f, "-------------------------------------------\n");
197 fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
198 cnt_to_uint(&f_alive),
199 cnt_to_uint(&f_new_node),
202 } /* simple_dump_opcode_hash */
205 * Return the name of an optimization.
207 static const char *get_opt_name(int index) {
208 assert(index < (int) ARR_SIZE(opt_names) && "index out of range");
209 assert((int) opt_names[index].kind == index && "opt_names broken");
210 return opt_names[index].name;
214 * dumps an optimization hash into human readable form
216 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
218 if (pset_count(set) > 0) {
220 const char *name = get_opt_name(index);
222 fprintf(dmp->f, "\n%s:\n", name);
223 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
225 foreach_pset(set, entry) {
226 fprintf(dmp->f, "%-16s %8u\n",
227 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
230 } /* simple_dump_opt_hash */
233 * dumps the register pressure for each block and for each register class
235 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
237 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
238 reg_pressure_entry_t *rp_entry;
240 /* return if no be statistic information available */
244 fprintf(dmp->f, "\nREG PRESSURE:\n");
245 fprintf(dmp->f, "%12s", "Block Nr");
247 /* print table head (register class names) */
248 foreach_pset(b_entry->reg_pressure, rp_entry)
249 fprintf(dmp->f, "%15s", rp_entry->class_name);
250 fprintf(dmp->f, "\n");
252 /* print the reg pressure for all blocks and register classes */
253 for (/* b_entry is already initialized */ ;
255 b_entry = pset_next(entry->be_block_hash)) {
256 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
258 foreach_pset(b_entry->reg_pressure, rp_entry)
259 fprintf(dmp->f, "%15d", rp_entry->pressure);
260 fprintf(dmp->f, "\n");
262 } /* simple_dump_be_block_reg_pressure */
264 /** prints a distribution entry */
265 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
267 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
268 } /* simple_dump_distrib_entry */
271 * dumps the distribution of the amount of ready nodes for each block
273 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
275 if (pset_count(entry->be_block_hash) > 0) {
276 be_block_entry_t *b_entry;
279 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
280 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
281 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
283 foreach_pset(entry->be_block_hash, b_entry) {
284 /* this ensures that all keys from 1 to 5 are in the table */
285 for (i = 1; i < 6; ++i)
286 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
288 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
289 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
290 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
291 fprintf(dmp->f, "\n");
294 } /* simple_dump_be_block_sched_ready */
297 * Adds the counter for given entry to another distribution table.
299 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
300 distrib_tbl_t *sum_tbl = env;
302 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
303 } /* add_distrib_entry */
306 * dumps permutation statistics for one and block and one class
308 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
310 perm_stat_entry_t *ps_ent;
311 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
312 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
316 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
325 foreach_pset(entry->perm_stat, ps_ent) {
326 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
329 stat_get_count_distrib_tbl(ps_ent->chains),
330 stat_get_count_distrib_tbl(ps_ent->cycles),
335 /* sum up distribution table for chains */
336 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
338 /* sum up distribution table for cycles */
339 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
342 /* print chain distribution for all perms of this class in this block */
343 fprintf(dmp->f, "chain distribution:\n");
345 /* add all missing entries to chain distribution table */
346 for (i = 1; i <= entry->n_regs; i++) {
347 snprintf(buf, sizeof(buf), "length %d", i);
348 fprintf(dmp->f, "%12s", buf);
349 stat_insert_int_distrib_tbl(sum_chains, i);
351 fprintf(dmp->f, "\n");
352 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
353 fprintf(dmp->f, "\n");
355 /* print cycle distribution for all perms of this class in this block */
356 fprintf(dmp->f, "cycle distribution:\n");
358 /* add all missing entries to cycle distribution table */
359 for (i = 1; i <= entry->n_regs; i++) {
360 snprintf(buf, sizeof(buf), "length %d", i);
361 fprintf(dmp->f, "%12s", buf);
362 stat_insert_int_distrib_tbl(sum_cycles, i);
364 fprintf(dmp->f, "\n");
365 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
366 fprintf(dmp->f, "\n");
368 /* delete temporary sum distribution tables */
369 stat_delete_distrib_tbl(sum_chains);
370 stat_delete_distrib_tbl(sum_cycles);
372 } /* simple_dump_be_block_permstat_class */
375 * dumps statistics about perms
377 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
379 if (pset_count(entry->be_block_hash) > 0) {
380 be_block_entry_t *b_entry;
382 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
383 foreach_pset(entry->be_block_hash, b_entry) {
384 perm_class_entry_t *pc_ent;
386 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
388 if (b_entry->perm_class_stat) {
389 foreach_pset(b_entry->perm_class_stat, pc_ent) {
390 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
391 simple_dump_be_block_permstat_class(dmp, pc_ent);
396 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
398 } /* simple_dump_be_block_permstat */
401 * dumps the number of real_function_call optimization
403 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
408 if (! cnt_eq(cnt, 0)) {
409 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
410 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
412 } /* simple_dump_real_func_calls */
415 * dumps the number of tail_recursion optimization
417 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
422 if (num_tail_recursion > 0) {
423 fprintf(dmp->f, "\nTail recursion optimized:\n");
424 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
426 } /* simple_dump_tail_recursion */
429 * dumps the edges count
431 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
436 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
437 } /* simple_dump_edges */
442 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
444 int i, dump_opts = 1;
445 block_entry_t *b_entry;
446 extbb_entry_t *eb_entry;
452 ir_graph *const_irg = get_const_code_irg();
454 if (entry->irg == const_irg)
455 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
458 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
460 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
463 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
464 " was inlined : %u\n"
465 " got inlined : %u\n"
466 " strength red : %u\n"
467 " leaf function : %s\n"
468 " calls only leaf functions : %s\n"
472 " indirect calls : %u\n"
473 " external calls : %u\n",
474 entry->is_deleted ? "DELETED " : "",
475 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
476 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
477 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
478 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
479 entry->is_leaf ? "YES" : "NO",
480 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
481 entry->is_recursive ? "YES" : "NO",
482 entry->is_chain_call ? "YES" : "NO",
483 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
484 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
485 cnt_to_uint(&entry->cnt[gcnt_external_calls])
488 for (i = 0; i < IF_RESULT_LAST; ++i) {
489 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
492 fprintf(dmp->f, "\nGlobals counts:\n");
493 fprintf(dmp->f, "--------------\n");
499 " pure address calc ops : %u\n"
500 " all address calc ops : %u\n",
501 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
502 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
505 /* Load/Store address classification */
507 " global Ld/St address : %u\n"
508 " local Ld/St address : %u\n"
509 " this Ld/St address : %u\n"
510 " param Ld/St address : %u\n"
511 " other Ld/St address : %u\n",
512 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
513 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
514 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
515 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
516 cnt_to_uint(&entry->cnt[gcnt_other_adr])
519 simple_dump_opcode_hash(dmp, entry->opcode_hash);
520 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
522 /* effects of optimizations */
526 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
527 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
529 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
530 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
533 /* dump block info */
534 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
535 foreach_pset(entry->block_hash, b_entry) {
536 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
538 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
539 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
540 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
541 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
542 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
543 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
544 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
548 /* dump block reg pressure */
549 simple_dump_be_block_reg_pressure(dmp, entry);
551 /* dump block ready nodes distribution */
552 simple_dump_be_block_sched_ready(dmp, entry);
554 /* dump block permutation statistics */
555 simple_dump_be_block_permstat(dmp, entry);
557 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
558 /* dump extended block info */
559 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
560 foreach_pset(entry->extbb_hash, eb_entry) {
561 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
563 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
564 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
565 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
566 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
567 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
568 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
573 } /* simple_dump_graph */
576 * dumps the constant table
578 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
588 fprintf(dmp->f, "\nConstant Information:\n");
589 fprintf(dmp->f, "---------------------\n");
591 fprintf(dmp->f, "\nBit usage for integer constants\n");
592 fprintf(dmp->f, "-------------------------------\n");
594 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
595 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
596 cnt_add(&sum, &tbl->int_bits_count[i]);
598 fprintf(dmp->f, "-------------------------------\n");
600 fprintf(dmp->f, "\nFloating point constants classification\n");
601 fprintf(dmp->f, "--------------------------------------\n");
602 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
603 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
604 cnt_add(&sum, &tbl->floats[i]);
606 fprintf(dmp->f, "--------------------------------------\n");
608 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
609 cnt_add(&sum, &tbl->others);
610 fprintf(dmp->f, "-------------------------------\n");
612 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
613 } /* simple_dump_const_tbl */
616 * Dumps a line of the parameter table
618 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
621 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
622 } /* dump_tbl_line */
625 * dumps the parameter distribution table
627 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
628 fprintf(dmp->f, "\nCall parameter Information:\n");
629 fprintf(dmp->f, "---------------------\n");
631 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
632 fprintf(dmp->f, "-------------------------------\n");
634 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
635 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
636 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
637 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
638 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
639 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
640 } /* simple_dump_param_tbl */
643 * dumps the optimization counter table
645 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
648 fprintf(dmp->f, "\nOptimization counts:\n");
649 fprintf(dmp->f, "---------------------\n");
651 for (i = 0; i < len; ++i) {
652 unsigned cnt = cnt_to_uint(&tbl[i]);
655 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
658 } /* simple_dump_opt_cnt */
661 * initialize the simple dumper
663 static void simple_init(dumper_t *dmp, const char *name) {
666 snprintf(fname, sizeof(fname), "%s.txt", name);
667 dmp->f = fopen(fname, "w");
674 * finishes the simple dumper
676 static void simple_finish(dumper_t *dmp) {
680 } /* simple_finish */
683 * the simple human readable dumper
685 const dumper_t simple_dumper = {
687 simple_dump_const_tbl,
688 simple_dump_param_tbl,
696 FOURCC('S', 'M', 'P', 'L'),
699 /* ---------------------------------------------------------------------- */
702 * count the nodes as needed:
704 * 1 normal (data) Phi's
709 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
714 for (i = 0; i < 4; ++i)
717 foreach_pset(graph->opcode_hash, entry) {
718 if (entry->op == op_Phi) {
720 cnt_add(&cnt[1], &entry->cnt_alive);
721 } else if (entry->op == dmp->status->op_PhiM) {
723 cnt_add(&cnt[2], &entry->cnt_alive);
724 } else if (entry->op == op_Proj) {
726 cnt_add(&cnt[3], &entry->cnt_alive);
728 /* all other nodes */
729 cnt_add(&cnt[0], &entry->cnt_alive);
732 } /* csv_count_nodes */
737 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
745 if (entry->irg && !entry->is_deleted) {
746 ir_graph *const_irg = get_const_code_irg();
748 if (entry->irg == const_irg) {
749 name = "<Const code Irg>";
753 name = get_entity_name(entry->ent);
755 name = "<UNKNOWN IRG>";
758 csv_count_nodes(dmp, entry, cnt);
760 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
763 cnt_to_uint(&cnt[0]),
764 cnt_to_uint(&cnt[1]),
765 cnt_to_uint(&cnt[2]),
769 } /* csv_dump_graph */
774 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
779 } /* csv_dump_const_tbl */
782 * dumps the parameter distribution table
784 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
789 } /* csv_dump_param_tbl */
792 * dumps the optimization counter
794 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
799 } /* csv_dump_opt_cnt */
802 * initialize the simple dumper
804 static void csv_init(dumper_t *dmp, const char *name)
808 snprintf(fname, sizeof(fname), "%s.csv", name);
809 dmp->f = fopen(fname, "a");
815 * finishes the simple dumper
817 static void csv_finish(dumper_t *dmp)
825 * the simple human readable dumper
827 const dumper_t csv_dumper = {
838 FOURCC('C', 'S', 'V', '\0')