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
33 * names of the optimizations
39 { HOOK_OPT_DEAD_BLOCK, "dead block elimination" },
40 { HOOK_OPT_STG, "straightening optimization" },
41 { HOOK_OPT_IFSIM, "if simplification" },
42 { HOOK_OPT_CONST_EVAL, "constant evaluation" },
43 { HOOK_OPT_ALGSIM, "algebraic simplification" },
44 { HOOK_OPT_PHI, "Phi optmization" },
45 { HOOK_OPT_SYNC, "Sync optmization" },
46 { HOOK_OPT_WAW, "Write-After-Write optimization" },
47 { HOOK_OPT_WAR, "Write-After-Read optimization" },
48 { HOOK_OPT_RAW, "Read-After-Write optimization" },
49 { HOOK_OPT_RAR, "Read-After-Read optimization" },
50 { HOOK_OPT_RC, "Read-a-Const optimization" },
51 { HOOK_OPT_TUPLE, "Tuple optimization" },
52 { HOOK_OPT_ID, "ID optimization" },
53 { HOOK_OPT_CSE, "Common subexpression elimination" },
54 { HOOK_OPT_STRENGTH_RED, "Strength reduction" },
55 { HOOK_OPT_ARCH_DEP, "Architecture dependant optimization" },
56 { HOOK_OPT_REASSOC, "Reassociation optimization" },
57 { HOOK_OPT_POLY_CALL, "Polymorphic call optimization" },
58 { HOOK_OPT_IF_CONV, "an if conversion was tried" },
59 { HOOK_OPT_FUNC_CALL, "Real function call optimization" },
60 { HOOK_OPT_CONFIRM, "Confirm-based optimization: replacement" },
61 { HOOK_OPT_CONFIRM_C, "Confirm-based optimization: replaced by const" },
62 { HOOK_OPT_CONFIRM_E, "Confirm-based optimization: evaluated" },
63 { HOOK_OPT_EXC_REM, "a exception edge was removed due to a Confirmation prove" },
64 { HOOK_LOWERED, "Lowered" },
65 { HOOK_BACKEND, "Backend transformation" },
66 { FS_OPT_NEUTRAL_0, "algebraic simplification: a op 0 = 0 op a = a" },
67 { FS_OPT_NEUTRAL_1, "algebraic simplification: a op 1 = 1 op a = a" },
68 { FS_OPT_ADD_A_A, "algebraic simplification: a + a = a * 2" },
69 { FS_OPT_ADD_A_MINUS_B, "algebraic simplification: a + -b = a - b" },
70 { FS_OPT_ADD_SUB, "algebraic simplification: (a + x) - x = (a - x) + x = a" },
71 { FS_OPT_ADD_MUL_A_X_A, "algebraic simplification: a * x + a = a * (x + 1)" },
72 { FS_OPT_SUB_0_A, "algebraic simplification: 0 - a = -a" },
73 { FS_OPT_MINUS_SUB, "algebraic simplification: -(a - b) = b - a" },
74 { FS_OPT_SUB_MINUS, "algebraic simplification: a - (-b) = a + b" },
75 { FS_OPT_SUB_MUL_A_X_A, "algebraic simplification: a * x - a = a * (x - 1)" },
76 { FS_OPT_SUB_SUB_X_Y_Z, "algebraic simplification: (x - y) - z = x - (y + z)" },
77 { FS_OPT_SUB_C_NOT_X, "algebraic simplification: c - ~a = a + (c+1)" },
78 { FS_OPT_SUB_TO_ADD, "algebraic simplification: (-a) - b = -(a + b), a - (b - c) = a + (c - b), a - (b * C) = a + (b * -C)" },
79 { FS_OPT_SUB_TO_NOT, "algebraic simplification: -1 - x -> ~x" },
80 { FS_OPT_SUB_TO_CONV, "algebraic simplification: a - NULL = (int)a" },
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_A_B_A, "algebraic simplification: (a ^ b) ^ a = b" },
90 { FS_OPT_EOR_TO_NOT_BOOL,"boolean simplification: bool ^ 1 = !bool" },
91 { FS_OPT_EOR_TO_NOT, "algebraic simplification: x ^ 0b1..1 = ~x, (a ^ b) & b = ~a & b" },
92 { FS_OPT_NOT_CMP, "algebraic simplification: !(a cmp b) = a !cmp b" },
93 { FS_OPT_OR_SHFT_TO_ROTL,"algebraic simplification: (x << c) | (x >> (bits - c)) == Rotl(x, c)" },
94 { FS_OPT_REASSOC_SHIFT, "algebraic simplification: (x SHF c1) SHF c2 = x SHF (c1+c2)" },
95 { FS_OPT_SHIFT_AND, "algebraic simplification: (a SHF c) AND (b SHF c) = (a AND b) SHF c" },
96 { FS_OPT_SHIFT_OR, "algebraic simplification: (a SHF c) OR (b SHF c) = (a OR b) SHF c" },
97 { FS_OPT_SHIFT_EOR, "algebraic simplification: (a SHF c) XOR (b SHF c) = (a XOR b) SHF c" },
98 { FS_OPT_CONV, "algebraic simplification: Conv could be removed" },
99 { FS_OPT_CAST, "algebraic simplification: a Cast could be removed" },
100 { FS_OPT_MIN_MAX_EQ, "algebraic simplification: Min(a,a) = Max(a,a) = a" },
101 { FS_OPT_MUX_BOOL, "boolean simplification: Muxb(sel, true, false) = sel" },
102 { FS_OPT_MUX_NOT_BOOL, "boolean simplification: Muxb(sel, false, true) = Not(sel)" },
103 { FS_OPT_MUX_OR_BOOL, "boolean simplification: Muxb(sel, true, x) = Or(sel, x)" },
104 { FS_OPT_MUX_ORNOT_BOOL, "boolean simplification: Muxb(sel, x, true) = Or(Not(sel), x)" },
105 { FS_OPT_MUX_AND_BOOL, "boolean simplification: Muxb(sel, x, false) = And(sel, x)" },
106 { FS_OPT_MUX_ANDNOT_BOOL,"boolean simplification: Muxb(sel, false, x) = And(Not(sel), x)" },
107 { FS_OPT_MUX_C, "algebraic simplification: Mux(C, f, t) = C ? t : f" },
108 { FS_OPT_MUX_EQ, "algebraic simplification: Mux(v, x, x) = x" },
109 { FS_OPT_MUX_TRANSFORM, "algebraic simplification: Mux(t ==/!= f, t, f) = f/t, Mux(t ==/!= 0, -t, t) = -t/t" },
110 { FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
111 { FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
112 { FS_OPT_MUX_TO_ABS, "algebraic simplification: Mux(a > 0, a, -a) = Abs(a)" },
113 { FS_OPT_MUX_TO_BITOP, "algebraic simplification: Mux((a & 2^x) ==/!= 0, 2^x, 0) = (a & 2^x) (xor 2^x)" },
114 { FS_OPT_IDEM_UNARY, "algebraic simplification: Idempotent unary operation" },
115 { FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
116 { FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
117 { FS_OPT_NOT_PLUS_1, "algebraic simplification: ~x + 1 = -x" },
118 { FS_OPT_ADD_X_NOT_X, "algebraic simplification: ~x + x = -1" },
119 { FS_OPT_FP_INV_MUL, "algebraic simplification: x / y = x * (1.0/y)" },
120 { FS_OPT_ABS_MINUS_X, "algebraic simplification: Abs(-x) = Abs(x)" },
121 { FS_OPT_CONST_PHI, "constant evaluation on Phi node" },
122 { FS_OPT_PREDICATE, "predicate optimization" },
123 { FS_OPT_DEMORGAN, "optimization using DeMorgan's law" },
124 { FS_OPT_CMP_OP_OP, "CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y)" },
125 { FS_OPT_CMP_OP_C, "CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2)" },
126 { FS_OPT_CMP_CONV_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y)" },
127 { FS_OPT_CMP_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y)" },
128 { FS_OPT_CMP_TO_BOOL, "CMP optimization: Cmp(x, y) = BoolOP(x, y)" },
129 { FS_OPT_CMP_CNST_MAGN, "CMP optimization: reduced magnitude of a const" },
130 { FS_OPT_CMP_SHF_TO_AND, "CMP optimization: transformed shift into And" },
131 { FS_OPT_CMP_MOD_TO_AND, "CMP optimization: transformed Mod into And" },
132 { FS_OPT_NOP, "the operation is a NOP" },
133 { FS_OPT_GVN_FOLLOWER, "GVN-PRE: replaced a follower" },
134 { FS_OPT_GVN_FULLY, "GVN-PRE: replaced by fully redundant value" },
135 { FS_OPT_GVN_PARTLY, "GVN-PRE: replaced by partly redundant value" },
136 { FS_OPT_COMBO_CONST, "Combo: evaluated into Constant" },
137 { FS_OPT_COMBO_CF, "Combo: removed conditional control flow" },
138 { FS_OPT_COMBO_FOLLOWER, "Combo: removed a follower" },
139 { FS_OPT_COMBO_CONGRUENT,"Combo: replaced by congruent" },
140 { FS_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
141 { FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
142 { FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
143 { FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
144 { FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
145 { FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
146 { FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
147 { FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
148 { FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
149 { FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
150 { FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
151 { FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
152 { FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
153 { FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
154 { FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
155 { FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
156 { FS_OPT_RTS_SYMMETRIC, "RTS optimization: call to symmetric function f(-x) replaced by f(x)" },
157 { FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
158 { FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
159 { FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
160 { FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
161 { FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
162 { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
163 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
164 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
165 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
166 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
167 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
168 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
169 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
170 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
171 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
172 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
175 static const char *if_conv_names[IF_RESULT_LAST] = {
177 "if conv side effect ",
178 "if conv Phi node found ",
179 "if conv to deep DAG's ",
180 "if conv bad control flow ",
181 "if conv denied by arch ",
185 * dumps a opcode hash into human readable form
187 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
191 counter_t f_new_node;
195 cnt_clr(&f_new_node);
198 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
199 foreach_pset(set, entry) {
200 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
201 get_id_str(entry->op->name),
202 cnt_to_uint(&entry->cnt_alive),
203 cnt_to_uint(&entry->new_node),
204 cnt_to_uint(&entry->into_Id)
207 cnt_add(&f_alive, &entry->cnt_alive);
208 cnt_add(&f_new_node, &entry->new_node);
209 cnt_add(&f_Id, &entry->into_Id);
211 fprintf(dmp->f, "-------------------------------------------\n");
212 fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
213 cnt_to_uint(&f_alive),
214 cnt_to_uint(&f_new_node),
217 } /* simple_dump_opcode_hash */
220 * Return the name of an optimization.
222 static const char *get_opt_name(int index) {
223 assert(index < (int) ARR_SIZE(opt_names) && "index out of range");
224 assert((int) opt_names[index].kind == index && "opt_names broken");
225 return opt_names[index].name;
229 * dumps an optimization hash into human readable form
231 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
233 if (pset_count(set) > 0) {
235 const char *name = get_opt_name(index);
237 fprintf(dmp->f, "\n%s:\n", name);
238 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
240 foreach_pset(set, entry) {
241 fprintf(dmp->f, "%-16s %8u\n",
242 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
245 } /* simple_dump_opt_hash */
248 * dumps the register pressure for each block and for each register class
250 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
252 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
253 reg_pressure_entry_t *rp_entry;
255 /* return if no be statistic information available */
259 fprintf(dmp->f, "\nREG PRESSURE:\n");
260 fprintf(dmp->f, "%12s", "Block Nr");
262 /* print table head (register class names) */
263 foreach_pset(b_entry->reg_pressure, rp_entry)
264 fprintf(dmp->f, "%15s", rp_entry->class_name);
265 fprintf(dmp->f, "\n");
267 /* print the reg pressure for all blocks and register classes */
268 for (/* b_entry is already initialized */ ;
270 b_entry = pset_next(entry->be_block_hash)) {
271 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
273 foreach_pset(b_entry->reg_pressure, rp_entry)
274 fprintf(dmp->f, "%15d", rp_entry->pressure);
275 fprintf(dmp->f, "\n");
277 } /* simple_dump_be_block_reg_pressure */
279 /** prints a distribution entry */
280 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
282 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
283 } /* simple_dump_distrib_entry */
286 * dumps the distribution of the amount of ready nodes for each block
288 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
290 if (pset_count(entry->be_block_hash) > 0) {
291 be_block_entry_t *b_entry;
294 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
295 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
296 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
298 foreach_pset(entry->be_block_hash, b_entry) {
299 /* this ensures that all keys from 1 to 5 are in the table */
300 for (i = 1; i < 6; ++i)
301 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
303 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
304 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
305 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
306 fprintf(dmp->f, "\n");
309 } /* simple_dump_be_block_sched_ready */
312 * Adds the counter for given entry to another distribution table.
314 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
315 distrib_tbl_t *sum_tbl = env;
317 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
318 } /* add_distrib_entry */
321 * dumps permutation statistics for one and block and one class
323 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
325 perm_stat_entry_t *ps_ent;
326 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
327 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
331 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
340 foreach_pset(entry->perm_stat, ps_ent) {
341 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
344 stat_get_count_distrib_tbl(ps_ent->chains),
345 stat_get_count_distrib_tbl(ps_ent->cycles),
350 /* sum up distribution table for chains */
351 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
353 /* sum up distribution table for cycles */
354 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
357 /* print chain distribution for all perms of this class in this block */
358 fprintf(dmp->f, "chain distribution:\n");
360 /* add all missing entries to chain distribution table */
361 for (i = 1; i <= entry->n_regs; i++) {
362 snprintf(buf, sizeof(buf), "length %d", i);
363 fprintf(dmp->f, "%12s", buf);
364 stat_insert_int_distrib_tbl(sum_chains, i);
366 fprintf(dmp->f, "\n");
367 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
368 fprintf(dmp->f, "\n");
370 /* print cycle distribution for all perms of this class in this block */
371 fprintf(dmp->f, "cycle distribution:\n");
373 /* add all missing entries to cycle distribution table */
374 for (i = 1; i <= entry->n_regs; i++) {
375 snprintf(buf, sizeof(buf), "length %d", i);
376 fprintf(dmp->f, "%12s", buf);
377 stat_insert_int_distrib_tbl(sum_cycles, i);
379 fprintf(dmp->f, "\n");
380 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
381 fprintf(dmp->f, "\n");
383 /* delete temporary sum distribution tables */
384 stat_delete_distrib_tbl(sum_chains);
385 stat_delete_distrib_tbl(sum_cycles);
387 } /* simple_dump_be_block_permstat_class */
390 * dumps statistics about perms
392 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
394 if (pset_count(entry->be_block_hash) > 0) {
395 be_block_entry_t *b_entry;
397 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
398 foreach_pset(entry->be_block_hash, b_entry) {
399 perm_class_entry_t *pc_ent;
401 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
403 if (b_entry->perm_class_stat) {
404 foreach_pset(b_entry->perm_class_stat, pc_ent) {
405 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
406 simple_dump_be_block_permstat_class(dmp, pc_ent);
411 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
413 } /* simple_dump_be_block_permstat */
416 * dumps the number of real_function_call optimization
418 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
423 if (! cnt_eq(cnt, 0)) {
424 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
425 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
427 } /* simple_dump_real_func_calls */
430 * dumps the number of tail_recursion optimization
432 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
437 if (num_tail_recursion > 0) {
438 fprintf(dmp->f, "\nTail recursion optimized:\n");
439 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
441 } /* simple_dump_tail_recursion */
444 * dumps the edges count
446 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
451 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
452 } /* simple_dump_edges */
457 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
459 int i, dump_opts = 1;
460 block_entry_t *b_entry;
461 extbb_entry_t *eb_entry;
467 ir_graph *const_irg = get_const_code_irg();
469 if (entry->irg == const_irg)
470 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
473 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
475 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
478 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
479 " was inlined : %u\n"
480 " got inlined : %u\n"
481 " strength red : %u\n"
482 " leaf function : %s\n"
483 " 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 entry->is_strict ? "YES" : "NO",
500 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
501 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
502 cnt_to_uint(&entry->cnt[gcnt_external_calls])
505 for (i = 0; i < IF_RESULT_LAST; ++i) {
506 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
509 fprintf(dmp->f, "\nGlobals counts:\n");
510 fprintf(dmp->f, "--------------\n");
516 " pure address calc ops : %u\n"
517 " all address calc ops : %u\n",
518 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
519 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
522 /* Load/Store address classification */
524 " global Ld/St address : %u\n"
525 " local Ld/St address : %u\n"
526 " this Ld/St address : %u\n"
527 " param Ld/St address : %u\n"
528 " other Ld/St address : %u\n",
529 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
530 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
531 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
532 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
533 cnt_to_uint(&entry->cnt[gcnt_other_adr])
536 simple_dump_opcode_hash(dmp, entry->opcode_hash);
537 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
539 /* effects of optimizations */
543 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
544 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
546 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
547 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
550 /* dump block info */
551 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
552 foreach_pset(entry->block_hash, b_entry) {
553 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
555 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
556 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
557 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
558 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
559 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
560 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
561 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
565 /* dump block reg pressure */
566 simple_dump_be_block_reg_pressure(dmp, entry);
568 /* dump block ready nodes distribution */
569 simple_dump_be_block_sched_ready(dmp, entry);
571 /* dump block permutation statistics */
572 simple_dump_be_block_permstat(dmp, entry);
574 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
575 /* dump extended block info */
576 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
577 foreach_pset(entry->extbb_hash, eb_entry) {
578 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
580 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
581 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
582 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
583 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
584 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
585 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
590 } /* simple_dump_graph */
593 * dumps the constant table
595 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
605 fprintf(dmp->f, "\nConstant Information:\n");
606 fprintf(dmp->f, "---------------------\n");
608 fprintf(dmp->f, "\nBit usage for integer constants\n");
609 fprintf(dmp->f, "-------------------------------\n");
611 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
612 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
613 cnt_add(&sum, &tbl->int_bits_count[i]);
615 fprintf(dmp->f, "-------------------------------\n");
617 fprintf(dmp->f, "\nFloating point constants classification\n");
618 fprintf(dmp->f, "--------------------------------------\n");
619 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
620 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
621 cnt_add(&sum, &tbl->floats[i]);
623 fprintf(dmp->f, "--------------------------------------\n");
625 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
626 cnt_add(&sum, &tbl->others);
627 fprintf(dmp->f, "-------------------------------\n");
629 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
630 } /* simple_dump_const_tbl */
633 * Dumps a line of the parameter table
635 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
638 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
639 } /* dump_tbl_line */
642 * dumps the parameter distribution table
644 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
645 fprintf(dmp->f, "\nCall parameter Information:\n");
646 fprintf(dmp->f, "---------------------\n");
648 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
649 fprintf(dmp->f, "-------------------------------\n");
651 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
652 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
653 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
654 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
655 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
656 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
657 } /* simple_dump_param_tbl */
660 * dumps the optimization counter table
662 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
665 fprintf(dmp->f, "\nOptimization counts:\n");
666 fprintf(dmp->f, "---------------------\n");
668 for (i = 0; i < len; ++i) {
669 unsigned cnt = cnt_to_uint(&tbl[i]);
672 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
675 } /* simple_dump_opt_cnt */
678 * initialize the simple dumper
680 static void simple_init(dumper_t *dmp, const char *name) {
683 snprintf(fname, sizeof(fname), "%s.txt", name);
684 dmp->f = fopen(fname, "w");
691 * finishes the simple dumper
693 static void simple_finish(dumper_t *dmp) {
697 } /* simple_finish */
700 * the simple human readable dumper
702 const dumper_t simple_dumper = {
704 simple_dump_const_tbl,
705 simple_dump_param_tbl,
713 FOURCC('S', 'M', 'P', 'L'),
716 /* ---------------------------------------------------------------------- */
719 * count the nodes as needed:
721 * 1 normal (data) Phi's
726 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
731 for (i = 0; i < 4; ++i)
734 foreach_pset(graph->opcode_hash, entry) {
735 if (entry->op == op_Phi) {
737 cnt_add(&cnt[1], &entry->cnt_alive);
738 } else if (entry->op == dmp->status->op_PhiM) {
740 cnt_add(&cnt[2], &entry->cnt_alive);
741 } else if (entry->op == op_Proj) {
743 cnt_add(&cnt[3], &entry->cnt_alive);
745 /* all other nodes */
746 cnt_add(&cnt[0], &entry->cnt_alive);
749 } /* csv_count_nodes */
754 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
762 if (entry->irg && !entry->is_deleted) {
763 ir_graph *const_irg = get_const_code_irg();
765 if (entry->irg == const_irg) {
766 name = "<Const code Irg>";
770 name = get_entity_name(entry->ent);
772 name = "<UNKNOWN IRG>";
775 csv_count_nodes(dmp, entry, cnt);
777 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
780 cnt_to_uint(&cnt[0]),
781 cnt_to_uint(&cnt[1]),
782 cnt_to_uint(&cnt[2]),
786 } /* csv_dump_graph */
791 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
796 } /* csv_dump_const_tbl */
799 * dumps the parameter distribution table
801 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
806 } /* csv_dump_param_tbl */
809 * dumps the optimization counter
811 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
816 } /* csv_dump_opt_cnt */
819 * initialize the simple dumper
821 static void csv_init(dumper_t *dmp, const char *name)
825 snprintf(fname, sizeof(fname), "%s.csv", name);
826 dmp->f = fopen(fname, "a");
832 * finishes the simple dumper
834 static void csv_finish(dumper_t *dmp)
842 * the simple human readable dumper
844 const dumper_t csv_dumper = {
855 FOURCC('C', 'S', 'V', '\0')