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_MUX_TO_BITOP, "algebraic simplification: Mux((a & 2^x) ==/!= 0, 2^x, 0) = (a & 2^x) (xor 2^x)" },
116 { FS_OPT_IDEM_UNARY, "algebraic simplification: Idempotent unary operation" },
117 { FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
118 { FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
119 { FS_OPT_NOT_PLUS_1, "algebraic simplification: ~x + 1 = -x" },
120 { FS_OPT_ADD_X_NOT_X, "algebraic simplification: ~x + x = -1" },
121 { FS_OPT_FP_INV_MUL, "algebraic simplification: x / y = x * (1.0/y)" },
122 { FS_OPT_ABS_MINUS_X, "algebraic simplification: Abs(-x) = Abs(x)" },
123 { FS_OPT_CONST_PHI, "constant evaluation on Phi node" },
124 { FS_OPT_PREDICATE, "predicate optimization" },
125 { FS_OPT_DEMORGAN, "optimization using DeMorgan's law" },
126 { FS_OPT_CMP_OP_OP, "CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y)" },
127 { FS_OPT_CMP_OP_C, "CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2)" },
128 { FS_OPT_CMP_CONV_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y)" },
129 { FS_OPT_CMP_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y)" },
130 { FS_OPT_CMP_TO_BOOL, "CMP optimization: Cmp(x, y) = BoolOP(x, y)" },
131 { FS_OPT_CMP_CNST_MAGN, "CMP optimization: reduced magnitude of a const" },
132 { FS_OPT_CMP_SHF_TO_AND, "CMP optimization: transformed shift into And" },
133 { FS_OPT_CMP_MOD_TO_AND, "CMP optimization: transformed Mod into And" },
134 { FS_OPT_NOP, "the operation is a NOP" },
135 { FS_OPT_GVN_FOLLOWER, "GVN-PRE: replaced a follower" },
136 { FS_OPT_GVN_FULLY, "GVN-PRE: replaced by fully redundant value" },
137 { FS_OPT_GVN_PARTLY, "GVN-PRE: replaced by partly redundant value" },
138 { FS_OPT_COMBO_CONST, "Combo: evaluated into Constant" },
139 { FS_OPT_COMBO_CF, "Combo: removed conditional control flow" },
140 { FS_OPT_COMBO_FOLLOWER, "Combo: removed a follower" },
141 { FS_OPT_COMBO_CONGRUENT,"Combo: replaced by congruent" },
142 { FS_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
143 { FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
144 { FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
145 { FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
146 { FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
147 { FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
148 { FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
149 { FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
150 { FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
151 { FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
152 { FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
153 { FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
154 { FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
155 { FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
156 { FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
157 { FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
158 { FS_OPT_RTS_SYMMETRIC, "RTS optimization: call to symmetric function f(-x) replaced by f(x)" },
159 { FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
160 { FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
161 { FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
162 { FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
163 { FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
164 { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
165 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
166 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
167 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
168 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
169 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
170 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
171 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
172 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
173 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
174 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
177 static const char *if_conv_names[IF_RESULT_LAST] = {
179 "if conv side effect ",
180 "if conv Phi node found ",
181 "if conv to deep DAG's ",
182 "if conv bad control flow ",
183 "if conv denied by arch ",
187 * dumps a opcode hash into human readable form
189 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
193 counter_t f_new_node;
197 cnt_clr(&f_new_node);
200 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
201 foreach_pset(set, entry) {
202 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
203 get_id_str(entry->op->name),
204 cnt_to_uint(&entry->cnt_alive),
205 cnt_to_uint(&entry->new_node),
206 cnt_to_uint(&entry->into_Id)
209 cnt_add(&f_alive, &entry->cnt_alive);
210 cnt_add(&f_new_node, &entry->new_node);
211 cnt_add(&f_Id, &entry->into_Id);
213 fprintf(dmp->f, "-------------------------------------------\n");
214 fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
215 cnt_to_uint(&f_alive),
216 cnt_to_uint(&f_new_node),
219 } /* simple_dump_opcode_hash */
222 * Return the name of an optimization.
224 static const char *get_opt_name(int index) {
225 assert(index < (int) ARR_SIZE(opt_names) && "index out of range");
226 assert((int) opt_names[index].kind == index && "opt_names broken");
227 return opt_names[index].name;
231 * dumps an optimization hash into human readable form
233 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
235 if (pset_count(set) > 0) {
237 const char *name = get_opt_name(index);
239 fprintf(dmp->f, "\n%s:\n", name);
240 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
242 foreach_pset(set, entry) {
243 fprintf(dmp->f, "%-16s %8u\n",
244 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
247 } /* simple_dump_opt_hash */
250 * dumps the register pressure for each block and for each register class
252 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
254 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
255 reg_pressure_entry_t *rp_entry;
257 /* return if no be statistic information available */
261 fprintf(dmp->f, "\nREG PRESSURE:\n");
262 fprintf(dmp->f, "%12s", "Block Nr");
264 /* print table head (register class names) */
265 foreach_pset(b_entry->reg_pressure, rp_entry)
266 fprintf(dmp->f, "%15s", rp_entry->class_name);
267 fprintf(dmp->f, "\n");
269 /* print the reg pressure for all blocks and register classes */
270 for (/* b_entry is already initialized */ ;
272 b_entry = pset_next(entry->be_block_hash)) {
273 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
275 foreach_pset(b_entry->reg_pressure, rp_entry)
276 fprintf(dmp->f, "%15d", rp_entry->pressure);
277 fprintf(dmp->f, "\n");
279 } /* simple_dump_be_block_reg_pressure */
281 /** prints a distribution entry */
282 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
284 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
285 } /* simple_dump_distrib_entry */
288 * dumps the distribution of the amount of ready nodes for each block
290 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
292 if (pset_count(entry->be_block_hash) > 0) {
293 be_block_entry_t *b_entry;
296 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
297 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
298 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
300 foreach_pset(entry->be_block_hash, b_entry) {
301 /* this ensures that all keys from 1 to 5 are in the table */
302 for (i = 1; i < 6; ++i)
303 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
305 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
306 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
307 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
308 fprintf(dmp->f, "\n");
311 } /* simple_dump_be_block_sched_ready */
314 * Adds the counter for given entry to another distribution table.
316 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
317 distrib_tbl_t *sum_tbl = env;
319 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
320 } /* add_distrib_entry */
323 * dumps permutation statistics for one and block and one class
325 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
327 perm_stat_entry_t *ps_ent;
328 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
329 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
333 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
342 foreach_pset(entry->perm_stat, ps_ent) {
343 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
346 stat_get_count_distrib_tbl(ps_ent->chains),
347 stat_get_count_distrib_tbl(ps_ent->cycles),
352 /* sum up distribution table for chains */
353 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
355 /* sum up distribution table for cycles */
356 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
359 /* print chain distribution for all perms of this class in this block */
360 fprintf(dmp->f, "chain distribution:\n");
362 /* add all missing entries to chain distribution table */
363 for (i = 1; i <= entry->n_regs; i++) {
364 snprintf(buf, sizeof(buf), "length %d", i);
365 fprintf(dmp->f, "%12s", buf);
366 stat_insert_int_distrib_tbl(sum_chains, i);
368 fprintf(dmp->f, "\n");
369 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
370 fprintf(dmp->f, "\n");
372 /* print cycle distribution for all perms of this class in this block */
373 fprintf(dmp->f, "cycle distribution:\n");
375 /* add all missing entries to cycle distribution table */
376 for (i = 1; i <= entry->n_regs; i++) {
377 snprintf(buf, sizeof(buf), "length %d", i);
378 fprintf(dmp->f, "%12s", buf);
379 stat_insert_int_distrib_tbl(sum_cycles, i);
381 fprintf(dmp->f, "\n");
382 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
383 fprintf(dmp->f, "\n");
385 /* delete temporary sum distribution tables */
386 stat_delete_distrib_tbl(sum_chains);
387 stat_delete_distrib_tbl(sum_cycles);
389 } /* simple_dump_be_block_permstat_class */
392 * dumps statistics about perms
394 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
396 if (pset_count(entry->be_block_hash) > 0) {
397 be_block_entry_t *b_entry;
399 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
400 foreach_pset(entry->be_block_hash, b_entry) {
401 perm_class_entry_t *pc_ent;
403 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
405 if (b_entry->perm_class_stat) {
406 foreach_pset(b_entry->perm_class_stat, pc_ent) {
407 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
408 simple_dump_be_block_permstat_class(dmp, pc_ent);
413 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
415 } /* simple_dump_be_block_permstat */
418 * dumps the number of real_function_call optimization
420 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
425 if (! cnt_eq(cnt, 0)) {
426 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
427 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
429 } /* simple_dump_real_func_calls */
432 * dumps the number of tail_recursion optimization
434 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
439 if (num_tail_recursion > 0) {
440 fprintf(dmp->f, "\nTail recursion optimized:\n");
441 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
443 } /* simple_dump_tail_recursion */
446 * dumps the edges count
448 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
453 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
454 } /* simple_dump_edges */
459 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
461 int i, dump_opts = 1;
462 block_entry_t *b_entry;
463 extbb_entry_t *eb_entry;
469 ir_graph *const_irg = get_const_code_irg();
471 if (entry->irg == const_irg)
472 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
475 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
477 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
480 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
481 " was inlined : %u\n"
482 " got inlined : %u\n"
483 " strength red : %u\n"
484 " leaf function : %s\n"
485 " calls only leaf functions : %s\n"
490 " indirect calls : %u\n"
491 " external calls : %u\n",
492 entry->is_deleted ? "DELETED " : "",
493 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
494 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
495 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
496 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
497 entry->is_leaf ? "YES" : "NO",
498 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
499 entry->is_recursive ? "YES" : "NO",
500 entry->is_chain_call ? "YES" : "NO",
501 entry->is_strict ? "YES" : "NO",
502 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
503 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
504 cnt_to_uint(&entry->cnt[gcnt_external_calls])
507 for (i = 0; i < IF_RESULT_LAST; ++i) {
508 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
511 fprintf(dmp->f, "\nGlobals counts:\n");
512 fprintf(dmp->f, "--------------\n");
518 " pure address calc ops : %u\n"
519 " all address calc ops : %u\n",
520 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
521 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
524 /* Load/Store address classification */
526 " global Ld/St address : %u\n"
527 " local Ld/St address : %u\n"
528 " this Ld/St address : %u\n"
529 " param Ld/St address : %u\n"
530 " other Ld/St address : %u\n",
531 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
532 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
533 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
534 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
535 cnt_to_uint(&entry->cnt[gcnt_other_adr])
538 simple_dump_opcode_hash(dmp, entry->opcode_hash);
539 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
541 /* effects of optimizations */
545 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
546 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
548 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
549 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
552 /* dump block info */
553 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
554 foreach_pset(entry->block_hash, b_entry) {
555 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
557 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
558 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
559 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
560 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
561 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
562 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
563 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
567 /* dump block reg pressure */
568 simple_dump_be_block_reg_pressure(dmp, entry);
570 /* dump block ready nodes distribution */
571 simple_dump_be_block_sched_ready(dmp, entry);
573 /* dump block permutation statistics */
574 simple_dump_be_block_permstat(dmp, entry);
576 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
577 /* dump extended block info */
578 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
579 foreach_pset(entry->extbb_hash, eb_entry) {
580 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
582 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
583 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
584 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
585 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
586 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
587 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
592 } /* simple_dump_graph */
595 * dumps the constant table
597 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
607 fprintf(dmp->f, "\nConstant Information:\n");
608 fprintf(dmp->f, "---------------------\n");
610 fprintf(dmp->f, "\nBit usage for integer constants\n");
611 fprintf(dmp->f, "-------------------------------\n");
613 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
614 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
615 cnt_add(&sum, &tbl->int_bits_count[i]);
617 fprintf(dmp->f, "-------------------------------\n");
619 fprintf(dmp->f, "\nFloating point constants classification\n");
620 fprintf(dmp->f, "--------------------------------------\n");
621 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
622 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
623 cnt_add(&sum, &tbl->floats[i]);
625 fprintf(dmp->f, "--------------------------------------\n");
627 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
628 cnt_add(&sum, &tbl->others);
629 fprintf(dmp->f, "-------------------------------\n");
631 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
632 } /* simple_dump_const_tbl */
635 * Dumps a line of the parameter table
637 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
640 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
641 } /* dump_tbl_line */
644 * dumps the parameter distribution table
646 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
647 fprintf(dmp->f, "\nCall parameter Information:\n");
648 fprintf(dmp->f, "---------------------\n");
650 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
651 fprintf(dmp->f, "-------------------------------\n");
653 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
654 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
655 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
656 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
657 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
658 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
659 } /* simple_dump_param_tbl */
662 * dumps the optimization counter table
664 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
667 fprintf(dmp->f, "\nOptimization counts:\n");
668 fprintf(dmp->f, "---------------------\n");
670 for (i = 0; i < len; ++i) {
671 unsigned cnt = cnt_to_uint(&tbl[i]);
674 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
677 } /* simple_dump_opt_cnt */
680 * initialize the simple dumper
682 static void simple_init(dumper_t *dmp, const char *name) {
685 snprintf(fname, sizeof(fname), "%s.txt", name);
686 dmp->f = fopen(fname, "w");
693 * finishes the simple dumper
695 static void simple_finish(dumper_t *dmp) {
699 } /* simple_finish */
702 * the simple human readable dumper
704 const dumper_t simple_dumper = {
706 simple_dump_const_tbl,
707 simple_dump_param_tbl,
715 FOURCC('S', 'M', 'P', 'L'),
718 /* ---------------------------------------------------------------------- */
721 * count the nodes as needed:
723 * 1 normal (data) Phi's
728 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
733 for (i = 0; i < 4; ++i)
736 foreach_pset(graph->opcode_hash, entry) {
737 if (entry->op == op_Phi) {
739 cnt_add(&cnt[1], &entry->cnt_alive);
740 } else if (entry->op == dmp->status->op_PhiM) {
742 cnt_add(&cnt[2], &entry->cnt_alive);
743 } else if (entry->op == op_Proj) {
745 cnt_add(&cnt[3], &entry->cnt_alive);
747 /* all other nodes */
748 cnt_add(&cnt[0], &entry->cnt_alive);
751 } /* csv_count_nodes */
756 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
764 if (entry->irg && !entry->is_deleted) {
765 ir_graph *const_irg = get_const_code_irg();
767 if (entry->irg == const_irg) {
768 name = "<Const code Irg>";
772 name = get_entity_name(entry->ent);
774 name = "<UNKNOWN IRG>";
777 csv_count_nodes(dmp, entry, cnt);
779 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
782 cnt_to_uint(&cnt[0]),
783 cnt_to_uint(&cnt[1]),
784 cnt_to_uint(&cnt[2]),
788 } /* csv_dump_graph */
793 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
798 } /* csv_dump_const_tbl */
801 * dumps the parameter distribution table
803 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
808 } /* csv_dump_param_tbl */
811 * dumps the optimization counter
813 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
818 } /* csv_dump_opt_cnt */
821 * initialize the simple dumper
823 static void csv_init(dumper_t *dmp, const char *name)
827 snprintf(fname, sizeof(fname), "%s.csv", name);
828 dmp->f = fopen(fname, "a");
834 * finishes the simple dumper
836 static void csv_finish(dumper_t *dmp)
844 * the simple human readable dumper
846 const dumper_t csv_dumper = {
857 FOURCC('C', 'S', 'V', '\0')