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_COND_EVAL, "Conditional evaluation: removed conditional control flow" },
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_STRCPY, "RTS optimization: call to strcpy() replaced" },
162 { FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
163 { FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
164 { FS_OPT_RTS_MEMPCPY, "RTS optimization: call to mempcpy() replaced" },
165 { FS_OPT_RTS_MEMMOVE, "RTS optimization: call to memmove() replaced" },
166 { FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
167 { FS_OPT_RTS_MEMCMP, "RTS optimization: call to memcmp() replaced" },
168 { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
169 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
170 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
171 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
172 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
173 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
174 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
175 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
176 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
177 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
178 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
181 static const char *if_conv_names[IF_RESULT_LAST] = {
183 "if conv side effect ",
184 "if conv Phi node found ",
185 "if conv to deep DAG's ",
186 "if conv bad control flow ",
187 "if conv denied by arch ",
191 * dumps a opcode hash into human readable form
193 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
197 counter_t f_new_node;
199 counter_t f_normlized;
202 cnt_clr(&f_new_node);
204 cnt_clr(&f_normlized);
206 fprintf(dmp->f, "%-16s %-8s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id", "normalized");
207 foreach_pset(set, entry) {
208 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n",
209 get_id_str(entry->op->name),
210 cnt_to_uint(&entry->cnt_alive),
211 cnt_to_uint(&entry->new_node),
212 cnt_to_uint(&entry->into_Id),
213 cnt_to_uint(&entry->normalized)
216 cnt_add(&f_alive, &entry->cnt_alive);
217 cnt_add(&f_new_node, &entry->new_node);
218 cnt_add(&f_Id, &entry->into_Id);
219 cnt_add(&f_normlized, &entry->normalized);
221 fprintf(dmp->f, "-------------------------------------------\n");
222 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n", "Sum",
223 cnt_to_uint(&f_alive),
224 cnt_to_uint(&f_new_node),
226 cnt_to_uint(&f_normlized)
228 } /* simple_dump_opcode_hash */
231 * Return the name of an optimization.
233 static const char *get_opt_name(int index) {
234 assert(index < (int) ARR_SIZE(opt_names) && "index out of range");
235 assert((int) opt_names[index].kind == index && "opt_names broken");
236 return opt_names[index].name;
240 * dumps an optimization hash into human readable form
242 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
244 if (pset_count(set) > 0) {
246 const char *name = get_opt_name(index);
248 fprintf(dmp->f, "\n%s:\n", name);
249 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
251 foreach_pset(set, entry) {
252 fprintf(dmp->f, "%-16s %8u\n",
253 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
256 } /* simple_dump_opt_hash */
259 * dumps the register pressure for each block and for each register class
261 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
263 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
264 reg_pressure_entry_t *rp_entry;
266 /* return if no be statistic information available */
270 fprintf(dmp->f, "\nREG PRESSURE:\n");
271 fprintf(dmp->f, "%12s", "Block Nr");
273 /* print table head (register class names) */
274 foreach_pset(b_entry->reg_pressure, rp_entry)
275 fprintf(dmp->f, "%15s", rp_entry->class_name);
276 fprintf(dmp->f, "\n");
278 /* print the reg pressure for all blocks and register classes */
279 for (/* b_entry is already initialized */ ;
281 b_entry = pset_next(entry->be_block_hash)) {
282 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
284 foreach_pset(b_entry->reg_pressure, rp_entry)
285 fprintf(dmp->f, "%15d", rp_entry->pressure);
286 fprintf(dmp->f, "\n");
288 } /* simple_dump_be_block_reg_pressure */
290 /** prints a distribution entry */
291 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
293 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
294 } /* simple_dump_distrib_entry */
297 * dumps the distribution of the amount of ready nodes for each block
299 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
301 if (pset_count(entry->be_block_hash) > 0) {
302 be_block_entry_t *b_entry;
305 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
306 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
307 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
309 foreach_pset(entry->be_block_hash, b_entry) {
310 /* this ensures that all keys from 1 to 5 are in the table */
311 for (i = 1; i < 6; ++i)
312 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
314 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
315 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
316 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
317 fprintf(dmp->f, "\n");
320 } /* simple_dump_be_block_sched_ready */
323 * Adds the counter for given entry to another distribution table.
325 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
326 distrib_tbl_t *sum_tbl = env;
328 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
329 } /* add_distrib_entry */
332 * dumps permutation statistics for one and block and one class
334 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
336 perm_stat_entry_t *ps_ent;
337 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
338 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
342 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
351 foreach_pset(entry->perm_stat, ps_ent) {
352 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
355 stat_get_count_distrib_tbl(ps_ent->chains),
356 stat_get_count_distrib_tbl(ps_ent->cycles),
361 /* sum up distribution table for chains */
362 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
364 /* sum up distribution table for cycles */
365 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
368 /* print chain distribution for all perms of this class in this block */
369 fprintf(dmp->f, "chain distribution:\n");
371 /* add all missing entries to chain distribution table */
372 for (i = 1; i <= entry->n_regs; i++) {
373 snprintf(buf, sizeof(buf), "length %d", i);
374 fprintf(dmp->f, "%12s", buf);
375 stat_insert_int_distrib_tbl(sum_chains, i);
377 fprintf(dmp->f, "\n");
378 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
379 fprintf(dmp->f, "\n");
381 /* print cycle distribution for all perms of this class in this block */
382 fprintf(dmp->f, "cycle distribution:\n");
384 /* add all missing entries to cycle distribution table */
385 for (i = 1; i <= entry->n_regs; i++) {
386 snprintf(buf, sizeof(buf), "length %d", i);
387 fprintf(dmp->f, "%12s", buf);
388 stat_insert_int_distrib_tbl(sum_cycles, i);
390 fprintf(dmp->f, "\n");
391 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
392 fprintf(dmp->f, "\n");
394 /* delete temporary sum distribution tables */
395 stat_delete_distrib_tbl(sum_chains);
396 stat_delete_distrib_tbl(sum_cycles);
398 } /* simple_dump_be_block_permstat_class */
401 * dumps statistics about perms
403 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
405 if (pset_count(entry->be_block_hash) > 0) {
406 be_block_entry_t *b_entry;
408 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
409 foreach_pset(entry->be_block_hash, b_entry) {
410 perm_class_entry_t *pc_ent;
412 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
414 if (b_entry->perm_class_stat) {
415 foreach_pset(b_entry->perm_class_stat, pc_ent) {
416 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
417 simple_dump_be_block_permstat_class(dmp, pc_ent);
422 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
424 } /* simple_dump_be_block_permstat */
427 * dumps the number of real_function_call optimization
429 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
434 if (! cnt_eq(cnt, 0)) {
435 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
436 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
438 } /* simple_dump_real_func_calls */
441 * dumps the number of tail_recursion optimization
443 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
448 if (num_tail_recursion > 0) {
449 fprintf(dmp->f, "\nTail recursion optimized:\n");
450 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
452 } /* simple_dump_tail_recursion */
455 * dumps the edges count
457 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
462 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
463 } /* simple_dump_edges */
468 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
470 int i, dump_opts = 1;
471 block_entry_t *b_entry;
472 extbb_entry_t *eb_entry;
478 ir_graph *const_irg = get_const_code_irg();
480 if (entry->irg == const_irg)
481 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
484 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
486 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
489 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
490 " was inlined : %u\n"
491 " got inlined : %u\n"
492 " strength red : %u\n"
493 " leaf function : %s\n"
494 " calls only leaf functions : %s\n"
499 " indirect calls : %u\n"
500 " external calls : %u\n",
501 entry->is_deleted ? "DELETED " : "",
502 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
503 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
504 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
505 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
506 entry->is_leaf ? "YES" : "NO",
507 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
508 entry->is_recursive ? "YES" : "NO",
509 entry->is_chain_call ? "YES" : "NO",
510 entry->is_strict ? "YES" : "NO",
511 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
512 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
513 cnt_to_uint(&entry->cnt[gcnt_external_calls])
516 for (i = 0; i < IF_RESULT_LAST; ++i) {
517 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
520 fprintf(dmp->f, "\nGlobals counts:\n");
521 fprintf(dmp->f, "--------------\n");
527 " pure address calc ops : %u\n"
528 " all address calc ops : %u\n",
529 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
530 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
533 /* Load/Store address classification */
535 " global Ld/St address : %u\n"
536 " local Ld/St address : %u\n"
537 " this Ld/St address : %u\n"
538 " param Ld/St address : %u\n"
539 " other Ld/St address : %u\n",
540 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
541 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
542 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
543 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
544 cnt_to_uint(&entry->cnt[gcnt_other_adr])
547 simple_dump_opcode_hash(dmp, entry->opcode_hash);
548 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
550 /* effects of optimizations */
554 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
555 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
557 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
558 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
561 /* dump block info */
562 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
563 foreach_pset(entry->block_hash, b_entry) {
564 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
566 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
567 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
568 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
569 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
570 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
571 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
572 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
576 /* dump block reg pressure */
577 simple_dump_be_block_reg_pressure(dmp, entry);
579 /* dump block ready nodes distribution */
580 simple_dump_be_block_sched_ready(dmp, entry);
582 /* dump block permutation statistics */
583 simple_dump_be_block_permstat(dmp, entry);
585 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
586 /* dump extended block info */
587 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
588 foreach_pset(entry->extbb_hash, eb_entry) {
589 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
591 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
592 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
593 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
594 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
595 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
596 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
601 } /* simple_dump_graph */
604 * dumps the constant table
606 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
616 fprintf(dmp->f, "\nConstant Information:\n");
617 fprintf(dmp->f, "---------------------\n");
619 fprintf(dmp->f, "\nBit usage for integer constants\n");
620 fprintf(dmp->f, "-------------------------------\n");
622 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
623 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
624 cnt_add(&sum, &tbl->int_bits_count[i]);
626 fprintf(dmp->f, "-------------------------------\n");
628 fprintf(dmp->f, "\nFloating point constants classification\n");
629 fprintf(dmp->f, "--------------------------------------\n");
630 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
631 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
632 cnt_add(&sum, &tbl->floats[i]);
634 fprintf(dmp->f, "--------------------------------------\n");
636 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
637 cnt_add(&sum, &tbl->others);
638 fprintf(dmp->f, "-------------------------------\n");
640 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
641 } /* simple_dump_const_tbl */
644 * Dumps a line of the parameter table
646 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
649 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
650 } /* dump_tbl_line */
653 * dumps the parameter distribution table
655 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
656 fprintf(dmp->f, "\nCall parameter Information:\n");
657 fprintf(dmp->f, "---------------------\n");
659 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
660 fprintf(dmp->f, "-------------------------------\n");
662 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
663 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
664 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
665 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
666 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
667 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
668 } /* simple_dump_param_tbl */
671 * dumps the optimization counter table
673 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
676 fprintf(dmp->f, "\nOptimization counts:\n");
677 fprintf(dmp->f, "---------------------\n");
679 for (i = 0; i < len; ++i) {
680 unsigned cnt = cnt_to_uint(&tbl[i]);
683 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
686 } /* simple_dump_opt_cnt */
689 * initialize the simple dumper
691 static void simple_init(dumper_t *dmp, const char *name) {
694 snprintf(fname, sizeof(fname), "%s.txt", name);
695 dmp->f = fopen(fname, "w");
702 * finishes the simple dumper
704 static void simple_finish(dumper_t *dmp) {
708 } /* simple_finish */
711 * the simple human readable dumper
713 const dumper_t simple_dumper = {
715 simple_dump_const_tbl,
716 simple_dump_param_tbl,
724 FOURCC('S', 'M', 'P', 'L'),
727 /* ---------------------------------------------------------------------- */
730 * count the nodes as needed:
732 * 1 normal (data) Phi's
737 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
742 for (i = 0; i < 4; ++i)
745 foreach_pset(graph->opcode_hash, entry) {
746 if (entry->op == op_Phi) {
748 cnt_add(&cnt[1], &entry->cnt_alive);
749 } else if (entry->op == dmp->status->op_PhiM) {
751 cnt_add(&cnt[2], &entry->cnt_alive);
752 } else if (entry->op == op_Proj) {
754 cnt_add(&cnt[3], &entry->cnt_alive);
756 /* all other nodes */
757 cnt_add(&cnt[0], &entry->cnt_alive);
760 } /* csv_count_nodes */
765 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
773 if (entry->irg && !entry->is_deleted) {
774 ir_graph *const_irg = get_const_code_irg();
776 if (entry->irg == const_irg) {
777 name = "<Const code Irg>";
781 name = get_entity_name(entry->ent);
783 name = "<UNKNOWN IRG>";
786 csv_count_nodes(dmp, entry, cnt);
788 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
791 cnt_to_uint(&cnt[0]),
792 cnt_to_uint(&cnt[1]),
793 cnt_to_uint(&cnt[2]),
797 } /* csv_dump_graph */
802 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
807 } /* csv_dump_const_tbl */
810 * dumps the parameter distribution table
812 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
817 } /* csv_dump_param_tbl */
820 * dumps the optimization counter
822 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
827 } /* csv_dump_opt_cnt */
830 * initialize the simple dumper
832 static void csv_init(dumper_t *dmp, const char *name)
836 snprintf(fname, sizeof(fname), "%s.csv", name);
837 dmp->f = fopen(fname, "a");
843 * finishes the simple dumper
845 static void csv_finish(dumper_t *dmp)
853 * the simple human readable dumper
855 const dumper_t csv_dumper = {
866 FOURCC('C', 'S', 'V', '\0')