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_OPT_NORMALIZE, "a commutative node was normalized" },
65 { HOOK_LOWERED, "Lowered" },
66 { HOOK_BACKEND, "Backend transformation" },
67 { FS_OPT_NEUTRAL_0, "algebraic simplification: a op 0 = 0 op a = a" },
68 { FS_OPT_NEUTRAL_1, "algebraic simplification: a op 1 = 1 op a = a" },
69 { FS_OPT_ADD_A_A, "algebraic simplification: a + a = a * 2" },
70 { FS_OPT_ADD_A_MINUS_B, "algebraic simplification: a + -b = a - b" },
71 { FS_OPT_ADD_SUB, "algebraic simplification: (a + x) - x = (a - x) + x = a" },
72 { FS_OPT_ADD_MUL_A_X_A, "algebraic simplification: a * x + a = a * (x + 1)" },
73 { FS_OPT_SUB_0_A, "algebraic simplification: 0 - a = -a" },
74 { FS_OPT_MINUS_SUB, "algebraic simplification: -(a - b) = b - a" },
75 { FS_OPT_SUB_MINUS, "algebraic simplification: a - (-b) = a + b" },
76 { FS_OPT_SUB_MUL_A_X_A, "algebraic simplification: a * x - a = a * (x - 1)" },
77 { FS_OPT_SUB_SUB_X_Y_Z, "algebraic simplification: (x - y) - z = x - (y + z)" },
78 { FS_OPT_SUB_C_NOT_X, "algebraic simplification: c - ~a = a + (c+1)" },
79 { FS_OPT_SUB_TO_ADD, "algebraic simplification: (-a) - b = -(a + b), a - (b - c) = a + (c - b), a - (b * C) = a + (b * -C)" },
80 { FS_OPT_SUB_TO_NOT, "algebraic simplification: -1 - x -> ~x" },
81 { FS_OPT_SUB_TO_CONV, "algebraic simplification: a - NULL = (int)a" },
82 { FS_OPT_MUL_MINUS, "algebraic simplification: (-a) * (b - c) = a * (c - b)" },
83 { FS_OPT_MUL_MINUS_1, "algebraic simplification: a * -1 = -a" },
84 { FS_OPT_MINUS_MUL_C, "algebraic simplification: (-a) * C = a * (-C)" },
85 { FS_OPT_MUL_MINUS_MINUS,"algebraic simplification: (-a) * (-b) = a * b" },
86 { FS_OPT_OR, "algebraic simplification: a | a = a | 0 = 0 | a = a" },
87 { FS_OPT_AND, "algebraic simplification: a & 0b1...1 = 0b1...1 & a = a & a = (a|X) & a = a" },
88 { FS_OPT_TO_EOR, "algebraic simplification: (a|b) & ~(a&b) = a^b" },
89 { FS_OPT_EOR_A_A, "algebraic simplification: a ^ a = 0" },
90 { FS_OPT_EOR_A_B_A, "algebraic simplification: (a ^ b) ^ a = b" },
91 { FS_OPT_EOR_TO_NOT_BOOL,"boolean simplification: bool ^ 1 = !bool" },
92 { FS_OPT_EOR_TO_NOT, "algebraic simplification: x ^ 0b1..1 = ~x, (a ^ b) & b = ~a & b" },
93 { FS_OPT_NOT_CMP, "algebraic simplification: !(a cmp b) = a !cmp b" },
94 { FS_OPT_OR_SHFT_TO_ROTL,"algebraic simplification: (x << c) | (x >> (bits - c)) == Rotl(x, c)" },
95 { FS_OPT_REASSOC_SHIFT, "algebraic simplification: (x SHF c1) SHF c2 = x SHF (c1+c2)" },
96 { FS_OPT_SHIFT_AND, "algebraic simplification: (a SHF c) AND (b SHF c) = (a AND b) SHF c" },
97 { FS_OPT_SHIFT_OR, "algebraic simplification: (a SHF c) OR (b SHF c) = (a OR b) SHF c" },
98 { FS_OPT_SHIFT_EOR, "algebraic simplification: (a SHF c) XOR (b SHF c) = (a XOR b) SHF c" },
99 { FS_OPT_CONV, "algebraic simplification: Conv could be removed" },
100 { FS_OPT_CAST, "algebraic simplification: a Cast could be removed" },
101 { FS_OPT_MIN_MAX_EQ, "algebraic simplification: Min(a,a) = Max(a,a) = a" },
102 { FS_OPT_MUX_BOOL, "boolean simplification: Muxb(sel, true, false) = sel" },
103 { FS_OPT_MUX_NOT_BOOL, "boolean simplification: Muxb(sel, false, true) = Not(sel)" },
104 { FS_OPT_MUX_OR_BOOL, "boolean simplification: Muxb(sel, true, x) = Or(sel, x)" },
105 { FS_OPT_MUX_ORNOT_BOOL, "boolean simplification: Muxb(sel, x, true) = Or(Not(sel), x)" },
106 { FS_OPT_MUX_AND_BOOL, "boolean simplification: Muxb(sel, x, false) = And(sel, x)" },
107 { FS_OPT_MUX_ANDNOT_BOOL,"boolean simplification: Muxb(sel, false, x) = And(Not(sel), x)" },
108 { FS_OPT_MUX_C, "algebraic simplification: Mux(C, f, t) = C ? t : f" },
109 { FS_OPT_MUX_EQ, "algebraic simplification: Mux(v, x, x) = x" },
110 { FS_OPT_MUX_TRANSFORM, "algebraic simplification: Mux(t ==/!= f, t, f) = f/t, Mux(t ==/!= 0, -t, t) = -t/t" },
111 { FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
112 { FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
113 { FS_OPT_MUX_TO_ABS, "algebraic simplification: Mux(a > 0, a, -a) = Abs(a)" },
114 { FS_OPT_MUX_TO_BITOP, "algebraic simplification: Mux((a & 2^x) ==/!= 0, 2^x, 0) = (a & 2^x) (xor 2^x)" },
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;
194 counter_t f_normlized;
197 cnt_clr(&f_new_node);
199 cnt_clr(&f_normlized);
201 fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id", "normalized");
202 foreach_pset(set, entry) {
203 fprintf(dmp->f, "%-16s %8u %8u %8u\n",
204 get_id_str(entry->op->name),
205 cnt_to_uint(&entry->cnt_alive),
206 cnt_to_uint(&entry->new_node),
207 cnt_to_uint(&entry->into_Id),
208 cnt_to_uint(&entry->normalized)
211 cnt_add(&f_alive, &entry->cnt_alive);
212 cnt_add(&f_new_node, &entry->new_node);
213 cnt_add(&f_Id, &entry->into_Id);
214 cnt_add(&f_normlized, &entry->normalized);
216 fprintf(dmp->f, "-------------------------------------------\n");
217 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n", "Sum",
218 cnt_to_uint(&f_alive),
219 cnt_to_uint(&f_new_node),
221 cnt_to_uint(&f_normlized)
223 } /* simple_dump_opcode_hash */
226 * Return the name of an optimization.
228 static const char *get_opt_name(int index) {
229 assert(index < (int) ARR_SIZE(opt_names) && "index out of range");
230 assert((int) opt_names[index].kind == index && "opt_names broken");
231 return opt_names[index].name;
235 * dumps an optimization hash into human readable form
237 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
239 if (pset_count(set) > 0) {
241 const char *name = get_opt_name(index);
243 fprintf(dmp->f, "\n%s:\n", name);
244 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
246 foreach_pset(set, entry) {
247 fprintf(dmp->f, "%-16s %8u\n",
248 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
251 } /* simple_dump_opt_hash */
254 * dumps the register pressure for each block and for each register class
256 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
258 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
259 reg_pressure_entry_t *rp_entry;
261 /* return if no be statistic information available */
265 fprintf(dmp->f, "\nREG PRESSURE:\n");
266 fprintf(dmp->f, "%12s", "Block Nr");
268 /* print table head (register class names) */
269 foreach_pset(b_entry->reg_pressure, rp_entry)
270 fprintf(dmp->f, "%15s", rp_entry->class_name);
271 fprintf(dmp->f, "\n");
273 /* print the reg pressure for all blocks and register classes */
274 for (/* b_entry is already initialized */ ;
276 b_entry = pset_next(entry->be_block_hash)) {
277 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
279 foreach_pset(b_entry->reg_pressure, rp_entry)
280 fprintf(dmp->f, "%15d", rp_entry->pressure);
281 fprintf(dmp->f, "\n");
283 } /* simple_dump_be_block_reg_pressure */
285 /** prints a distribution entry */
286 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
288 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
289 } /* simple_dump_distrib_entry */
292 * dumps the distribution of the amount of ready nodes for each block
294 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
296 if (pset_count(entry->be_block_hash) > 0) {
297 be_block_entry_t *b_entry;
300 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
301 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
302 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
304 foreach_pset(entry->be_block_hash, b_entry) {
305 /* this ensures that all keys from 1 to 5 are in the table */
306 for (i = 1; i < 6; ++i)
307 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
309 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
310 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
311 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
312 fprintf(dmp->f, "\n");
315 } /* simple_dump_be_block_sched_ready */
318 * Adds the counter for given entry to another distribution table.
320 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
321 distrib_tbl_t *sum_tbl = env;
323 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
324 } /* add_distrib_entry */
327 * dumps permutation statistics for one and block and one class
329 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
331 perm_stat_entry_t *ps_ent;
332 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
333 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
337 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
346 foreach_pset(entry->perm_stat, ps_ent) {
347 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
350 stat_get_count_distrib_tbl(ps_ent->chains),
351 stat_get_count_distrib_tbl(ps_ent->cycles),
356 /* sum up distribution table for chains */
357 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
359 /* sum up distribution table for cycles */
360 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
363 /* print chain distribution for all perms of this class in this block */
364 fprintf(dmp->f, "chain distribution:\n");
366 /* add all missing entries to chain distribution table */
367 for (i = 1; i <= entry->n_regs; i++) {
368 snprintf(buf, sizeof(buf), "length %d", i);
369 fprintf(dmp->f, "%12s", buf);
370 stat_insert_int_distrib_tbl(sum_chains, i);
372 fprintf(dmp->f, "\n");
373 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
374 fprintf(dmp->f, "\n");
376 /* print cycle distribution for all perms of this class in this block */
377 fprintf(dmp->f, "cycle distribution:\n");
379 /* add all missing entries to cycle distribution table */
380 for (i = 1; i <= entry->n_regs; i++) {
381 snprintf(buf, sizeof(buf), "length %d", i);
382 fprintf(dmp->f, "%12s", buf);
383 stat_insert_int_distrib_tbl(sum_cycles, i);
385 fprintf(dmp->f, "\n");
386 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
387 fprintf(dmp->f, "\n");
389 /* delete temporary sum distribution tables */
390 stat_delete_distrib_tbl(sum_chains);
391 stat_delete_distrib_tbl(sum_cycles);
393 } /* simple_dump_be_block_permstat_class */
396 * dumps statistics about perms
398 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
400 if (pset_count(entry->be_block_hash) > 0) {
401 be_block_entry_t *b_entry;
403 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
404 foreach_pset(entry->be_block_hash, b_entry) {
405 perm_class_entry_t *pc_ent;
407 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
409 if (b_entry->perm_class_stat) {
410 foreach_pset(b_entry->perm_class_stat, pc_ent) {
411 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
412 simple_dump_be_block_permstat_class(dmp, pc_ent);
417 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
419 } /* simple_dump_be_block_permstat */
422 * dumps the number of real_function_call optimization
424 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
429 if (! cnt_eq(cnt, 0)) {
430 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
431 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
433 } /* simple_dump_real_func_calls */
436 * dumps the number of tail_recursion optimization
438 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
443 if (num_tail_recursion > 0) {
444 fprintf(dmp->f, "\nTail recursion optimized:\n");
445 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
447 } /* simple_dump_tail_recursion */
450 * dumps the edges count
452 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
457 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
458 } /* simple_dump_edges */
463 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
465 int i, dump_opts = 1;
466 block_entry_t *b_entry;
467 extbb_entry_t *eb_entry;
473 ir_graph *const_irg = get_const_code_irg();
475 if (entry->irg == const_irg)
476 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
479 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
481 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
484 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
485 " was inlined : %u\n"
486 " got inlined : %u\n"
487 " strength red : %u\n"
488 " leaf function : %s\n"
489 " calls only leaf functions : %s\n"
494 " indirect calls : %u\n"
495 " external calls : %u\n",
496 entry->is_deleted ? "DELETED " : "",
497 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
498 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
499 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
500 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
501 entry->is_leaf ? "YES" : "NO",
502 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
503 entry->is_recursive ? "YES" : "NO",
504 entry->is_chain_call ? "YES" : "NO",
505 entry->is_strict ? "YES" : "NO",
506 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
507 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
508 cnt_to_uint(&entry->cnt[gcnt_external_calls])
511 for (i = 0; i < IF_RESULT_LAST; ++i) {
512 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
515 fprintf(dmp->f, "\nGlobals counts:\n");
516 fprintf(dmp->f, "--------------\n");
522 " pure address calc ops : %u\n"
523 " all address calc ops : %u\n",
524 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
525 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
528 /* Load/Store address classification */
530 " global Ld/St address : %u\n"
531 " local Ld/St address : %u\n"
532 " this Ld/St address : %u\n"
533 " param Ld/St address : %u\n"
534 " other Ld/St address : %u\n",
535 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
536 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
537 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
538 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
539 cnt_to_uint(&entry->cnt[gcnt_other_adr])
542 simple_dump_opcode_hash(dmp, entry->opcode_hash);
543 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
545 /* effects of optimizations */
549 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
550 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
552 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
553 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
556 /* dump block info */
557 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
558 foreach_pset(entry->block_hash, b_entry) {
559 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
561 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
562 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
563 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
564 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
565 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
566 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
567 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
571 /* dump block reg pressure */
572 simple_dump_be_block_reg_pressure(dmp, entry);
574 /* dump block ready nodes distribution */
575 simple_dump_be_block_sched_ready(dmp, entry);
577 /* dump block permutation statistics */
578 simple_dump_be_block_permstat(dmp, entry);
580 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
581 /* dump extended block info */
582 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
583 foreach_pset(entry->extbb_hash, eb_entry) {
584 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
586 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
587 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
588 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
589 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
590 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
591 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
596 } /* simple_dump_graph */
599 * dumps the constant table
601 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
611 fprintf(dmp->f, "\nConstant Information:\n");
612 fprintf(dmp->f, "---------------------\n");
614 fprintf(dmp->f, "\nBit usage for integer constants\n");
615 fprintf(dmp->f, "-------------------------------\n");
617 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
618 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
619 cnt_add(&sum, &tbl->int_bits_count[i]);
621 fprintf(dmp->f, "-------------------------------\n");
623 fprintf(dmp->f, "\nFloating point constants classification\n");
624 fprintf(dmp->f, "--------------------------------------\n");
625 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
626 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
627 cnt_add(&sum, &tbl->floats[i]);
629 fprintf(dmp->f, "--------------------------------------\n");
631 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
632 cnt_add(&sum, &tbl->others);
633 fprintf(dmp->f, "-------------------------------\n");
635 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
636 } /* simple_dump_const_tbl */
639 * Dumps a line of the parameter table
641 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
644 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
645 } /* dump_tbl_line */
648 * dumps the parameter distribution table
650 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
651 fprintf(dmp->f, "\nCall parameter Information:\n");
652 fprintf(dmp->f, "---------------------\n");
654 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
655 fprintf(dmp->f, "-------------------------------\n");
657 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
658 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
659 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
660 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
661 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
662 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
663 } /* simple_dump_param_tbl */
666 * dumps the optimization counter table
668 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
671 fprintf(dmp->f, "\nOptimization counts:\n");
672 fprintf(dmp->f, "---------------------\n");
674 for (i = 0; i < len; ++i) {
675 unsigned cnt = cnt_to_uint(&tbl[i]);
678 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
681 } /* simple_dump_opt_cnt */
684 * initialize the simple dumper
686 static void simple_init(dumper_t *dmp, const char *name) {
689 snprintf(fname, sizeof(fname), "%s.txt", name);
690 dmp->f = fopen(fname, "w");
697 * finishes the simple dumper
699 static void simple_finish(dumper_t *dmp) {
703 } /* simple_finish */
706 * the simple human readable dumper
708 const dumper_t simple_dumper = {
710 simple_dump_const_tbl,
711 simple_dump_param_tbl,
719 FOURCC('S', 'M', 'P', 'L'),
722 /* ---------------------------------------------------------------------- */
725 * count the nodes as needed:
727 * 1 normal (data) Phi's
732 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
737 for (i = 0; i < 4; ++i)
740 foreach_pset(graph->opcode_hash, entry) {
741 if (entry->op == op_Phi) {
743 cnt_add(&cnt[1], &entry->cnt_alive);
744 } else if (entry->op == dmp->status->op_PhiM) {
746 cnt_add(&cnt[2], &entry->cnt_alive);
747 } else if (entry->op == op_Proj) {
749 cnt_add(&cnt[3], &entry->cnt_alive);
751 /* all other nodes */
752 cnt_add(&cnt[0], &entry->cnt_alive);
755 } /* csv_count_nodes */
760 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
768 if (entry->irg && !entry->is_deleted) {
769 ir_graph *const_irg = get_const_code_irg();
771 if (entry->irg == const_irg) {
772 name = "<Const code Irg>";
776 name = get_entity_name(entry->ent);
778 name = "<UNKNOWN IRG>";
781 csv_count_nodes(dmp, entry, cnt);
783 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
786 cnt_to_uint(&cnt[0]),
787 cnt_to_uint(&cnt[1]),
788 cnt_to_uint(&cnt[2]),
792 } /* csv_dump_graph */
797 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
802 } /* csv_dump_const_tbl */
805 * dumps the parameter distribution table
807 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
812 } /* csv_dump_param_tbl */
815 * dumps the optimization counter
817 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
822 } /* csv_dump_opt_cnt */
825 * initialize the simple dumper
827 static void csv_init(dumper_t *dmp, const char *name)
831 snprintf(fname, sizeof(fname), "%s.csv", name);
832 dmp->f = fopen(fname, "a");
838 * finishes the simple dumper
840 static void csv_finish(dumper_t *dmp)
848 * the simple human readable dumper
850 const dumper_t csv_dumper = {
861 FOURCC('C', 'S', 'V', '\0')