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_COMBINE, "boolean simplification: two Mux nodes where combined into one" },
103 { FS_OPT_MUX_CONV, "boolean simplification: MuxI(sel, 1, 0) = (I)sel" },
104 { FS_OPT_MUX_BOOL, "boolean simplification: Muxb(sel, true, false) = sel" },
105 { FS_OPT_MUX_NOT_BOOL, "boolean simplification: Muxb(sel, false, true) = Not(sel)" },
106 { FS_OPT_MUX_OR_BOOL, "boolean simplification: Muxb(sel, true, x) = Or(sel, x)" },
107 { FS_OPT_MUX_ORNOT_BOOL, "boolean simplification: Muxb(sel, x, true) = Or(Not(sel), x)" },
108 { FS_OPT_MUX_AND_BOOL, "boolean simplification: Muxb(sel, x, false) = And(sel, x)" },
109 { FS_OPT_MUX_ANDNOT_BOOL,"boolean simplification: Muxb(sel, false, x) = And(Not(sel), x)" },
110 { FS_OPT_MUX_C, "algebraic simplification: Mux(C, f, t) = C ? t : f" },
111 { FS_OPT_MUX_EQ, "algebraic simplification: Mux(v, x, x) = x" },
112 { FS_OPT_MUX_TRANSFORM, "algebraic simplification: Mux(t ==/!= f, t, f) = f/t, Mux(t ==/!= 0, -t, t) = -t/t" },
113 { FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
114 { FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
115 { FS_OPT_MUX_TO_ABS, "algebraic simplification: Mux(a > 0, a, -a) = Abs(a)" },
116 { FS_OPT_MUX_TO_BITOP, "algebraic simplification: Mux((a & 2^x) ==/!= 0, 2^x, 0) = (a & 2^x) (xor 2^x)" },
117 { FS_OPT_IDEM_UNARY, "algebraic simplification: Idempotent unary operation" },
118 { FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
119 { FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
120 { FS_OPT_NOT_PLUS_1, "algebraic simplification: ~x + 1 = -x" },
121 { FS_OPT_ADD_X_NOT_X, "algebraic simplification: ~x + x = -1" },
122 { FS_OPT_FP_INV_MUL, "algebraic simplification: x / y = x * (1.0/y)" },
123 { FS_OPT_ABS_MINUS_X, "algebraic simplification: Abs(-x) = Abs(x)" },
124 { FS_OPT_CONST_PHI, "constant evaluation on Phi node" },
125 { FS_OPT_PREDICATE, "predicate optimization" },
126 { FS_OPT_DEMORGAN, "optimization using DeMorgan's law" },
127 { FS_OPT_CMP_OP_OP, "CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y)" },
128 { FS_OPT_CMP_OP_C, "CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2)" },
129 { FS_OPT_CMP_CONV_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y)" },
130 { FS_OPT_CMP_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y)" },
131 { FS_OPT_CMP_TO_BOOL, "CMP optimization: Cmp(x, y) = BoolOP(x, y)" },
132 { FS_OPT_CMP_CNST_MAGN, "CMP optimization: reduced magnitude of a const" },
133 { FS_OPT_CMP_SHF_TO_AND, "CMP optimization: transformed shift into And" },
134 { FS_OPT_CMP_MOD_TO_AND, "CMP optimization: transformed Mod into And" },
135 { FS_OPT_NOP, "the operation is a NOP" },
136 { FS_OPT_GVN_FOLLOWER, "GVN-PRE: replaced a follower" },
137 { FS_OPT_GVN_FULLY, "GVN-PRE: replaced by fully redundant value" },
138 { FS_OPT_GVN_PARTLY, "GVN-PRE: replaced by partly redundant value" },
139 { FS_OPT_COMBO_CONST, "Combo: evaluated into Constant" },
140 { FS_OPT_COMBO_CF, "Combo: removed conditional control flow" },
141 { FS_OPT_COMBO_FOLLOWER, "Combo: removed a follower" },
142 { FS_OPT_COMBO_CONGRUENT,"Combo: replaced by congruent" },
143 { FS_OPT_JUMPTHREADING, "Jump threading: removed conditional control flow" },
144 { FS_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
145 { FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
146 { FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
147 { FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
148 { FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
149 { FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
150 { FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
151 { FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
152 { FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
153 { FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
154 { FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
155 { FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
156 { FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
157 { FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
158 { FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
159 { FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
160 { FS_OPT_RTS_SYMMETRIC, "RTS optimization: call to symmetric function f(-x) replaced by f(x)" },
161 { FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
162 { FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
163 { FS_OPT_RTS_STRCPY, "RTS optimization: call to strcpy() replaced" },
164 { FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
165 { FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
166 { FS_OPT_RTS_MEMPCPY, "RTS optimization: call to mempcpy() replaced" },
167 { FS_OPT_RTS_MEMMOVE, "RTS optimization: call to memmove() replaced" },
168 { FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
169 { FS_OPT_RTS_MEMCMP, "RTS optimization: call to memcmp() replaced" },
170 { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
171 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
172 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
173 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
174 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
175 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
176 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
177 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
178 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
179 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
180 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
183 static const char *if_conv_names[IF_RESULT_LAST] = {
185 "if conv side effect ",
186 "if conv Phi node found ",
187 "if conv to deep DAG's ",
188 "if conv bad control flow ",
189 "if conv denied by arch ",
193 * dumps a opcode hash into human readable form
195 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
199 counter_t f_new_node;
201 counter_t f_normlized;
204 cnt_clr(&f_new_node);
206 cnt_clr(&f_normlized);
208 fprintf(dmp->f, "%-16s %-8s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id", "normalized");
209 foreach_pset(set, entry) {
210 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n",
211 get_id_str(entry->op->name),
212 cnt_to_uint(&entry->cnt_alive),
213 cnt_to_uint(&entry->new_node),
214 cnt_to_uint(&entry->into_Id),
215 cnt_to_uint(&entry->normalized)
218 cnt_add(&f_alive, &entry->cnt_alive);
219 cnt_add(&f_new_node, &entry->new_node);
220 cnt_add(&f_Id, &entry->into_Id);
221 cnt_add(&f_normlized, &entry->normalized);
223 fprintf(dmp->f, "-------------------------------------------\n");
224 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n", "Sum",
225 cnt_to_uint(&f_alive),
226 cnt_to_uint(&f_new_node),
228 cnt_to_uint(&f_normlized)
230 } /* simple_dump_opcode_hash */
233 * Return the name of an optimization.
235 static const char *get_opt_name(int index)
237 assert(index < (int) ARR_SIZE(opt_names) && "index out of range");
238 assert((int) opt_names[index].kind == index && "opt_names broken");
239 return opt_names[index].name;
243 * dumps an optimization hash into human readable form
245 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
247 if (pset_count(set) > 0) {
249 const char *name = get_opt_name(index);
251 fprintf(dmp->f, "\n%s:\n", name);
252 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
254 foreach_pset(set, entry) {
255 fprintf(dmp->f, "%-16s %8u\n",
256 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
259 } /* simple_dump_opt_hash */
262 * dumps the register pressure for each block and for each register class
264 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
266 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
267 reg_pressure_entry_t *rp_entry;
269 /* return if no be statistic information available */
273 fprintf(dmp->f, "\nREG PRESSURE:\n");
274 fprintf(dmp->f, "%12s", "Block Nr");
276 /* print table head (register class names) */
277 foreach_pset(b_entry->reg_pressure, rp_entry)
278 fprintf(dmp->f, "%15s", rp_entry->class_name);
279 fprintf(dmp->f, "\n");
281 /* print the reg pressure for all blocks and register classes */
282 for (/* b_entry is already initialized */ ;
284 b_entry = pset_next(entry->be_block_hash)) {
285 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
287 foreach_pset(b_entry->reg_pressure, rp_entry)
288 fprintf(dmp->f, "%15d", rp_entry->pressure);
289 fprintf(dmp->f, "\n");
291 } /* simple_dump_be_block_reg_pressure */
293 /** prints a distribution entry */
294 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env)
297 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
298 } /* simple_dump_distrib_entry */
301 * dumps the distribution of the amount of ready nodes for each block
303 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
305 if (pset_count(entry->be_block_hash) > 0) {
306 be_block_entry_t *b_entry;
309 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
310 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
311 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
313 foreach_pset(entry->be_block_hash, b_entry) {
314 /* this ensures that all keys from 1 to 5 are in the table */
315 for (i = 1; i < 6; ++i)
316 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
318 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
319 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
320 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
321 fprintf(dmp->f, "\n");
324 } /* simple_dump_be_block_sched_ready */
327 * Adds the counter for given entry to another distribution table.
329 static void add_distrib_entry(const distrib_entry_t *entry, void *env)
331 distrib_tbl_t *sum_tbl = env;
333 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
334 } /* add_distrib_entry */
337 * dumps permutation statistics for one and block and one class
339 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
341 perm_stat_entry_t *ps_ent;
342 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
343 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
347 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
356 foreach_pset(entry->perm_stat, ps_ent) {
357 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
360 stat_get_count_distrib_tbl(ps_ent->chains),
361 stat_get_count_distrib_tbl(ps_ent->cycles),
366 /* sum up distribution table for chains */
367 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
369 /* sum up distribution table for cycles */
370 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
373 /* print chain distribution for all perms of this class in this block */
374 fprintf(dmp->f, "chain distribution:\n");
376 /* add all missing entries to chain distribution table */
377 for (i = 1; i <= entry->n_regs; i++) {
378 snprintf(buf, sizeof(buf), "length %d", i);
379 fprintf(dmp->f, "%12s", buf);
380 stat_insert_int_distrib_tbl(sum_chains, i);
382 fprintf(dmp->f, "\n");
383 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
384 fprintf(dmp->f, "\n");
386 /* print cycle distribution for all perms of this class in this block */
387 fprintf(dmp->f, "cycle distribution:\n");
389 /* add all missing entries to cycle distribution table */
390 for (i = 1; i <= entry->n_regs; i++) {
391 snprintf(buf, sizeof(buf), "length %d", i);
392 fprintf(dmp->f, "%12s", buf);
393 stat_insert_int_distrib_tbl(sum_cycles, i);
395 fprintf(dmp->f, "\n");
396 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
397 fprintf(dmp->f, "\n");
399 /* delete temporary sum distribution tables */
400 stat_delete_distrib_tbl(sum_chains);
401 stat_delete_distrib_tbl(sum_cycles);
403 } /* simple_dump_be_block_permstat_class */
406 * dumps statistics about perms
408 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
410 if (pset_count(entry->be_block_hash) > 0) {
411 be_block_entry_t *b_entry;
413 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
414 foreach_pset(entry->be_block_hash, b_entry) {
415 perm_class_entry_t *pc_ent;
417 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
419 if (b_entry->perm_class_stat) {
420 foreach_pset(b_entry->perm_class_stat, pc_ent) {
421 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
422 simple_dump_be_block_permstat_class(dmp, pc_ent);
427 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
429 } /* simple_dump_be_block_permstat */
432 * dumps the number of real_function_call optimization
434 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
439 if (! cnt_eq(cnt, 0)) {
440 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
441 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
443 } /* simple_dump_real_func_calls */
446 * dumps the number of tail_recursion optimization
448 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
453 if (num_tail_recursion > 0) {
454 fprintf(dmp->f, "\nTail recursion optimized:\n");
455 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
457 } /* simple_dump_tail_recursion */
460 * dumps the edges count
462 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
467 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
468 } /* simple_dump_edges */
473 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
475 int i, dump_opts = 1;
476 block_entry_t *b_entry;
477 extbb_entry_t *eb_entry;
483 ir_graph *const_irg = get_const_code_irg();
485 if (entry->irg == const_irg)
486 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
489 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
491 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
494 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
495 " was inlined : %u\n"
496 " got inlined : %u\n"
497 " strength red : %u\n"
498 " leaf function : %s\n"
499 " calls only leaf functions : %s\n"
504 " indirect calls : %u\n"
505 " external calls : %u\n",
506 entry->is_deleted ? "DELETED " : "",
507 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
508 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
509 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
510 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
511 entry->is_leaf ? "YES" : "NO",
512 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
513 entry->is_recursive ? "YES" : "NO",
514 entry->is_chain_call ? "YES" : "NO",
515 entry->is_strict ? "YES" : "NO",
516 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
517 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
518 cnt_to_uint(&entry->cnt[gcnt_external_calls])
521 for (i = 0; i < IF_RESULT_LAST; ++i) {
522 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
525 fprintf(dmp->f, "\nGlobals counts:\n");
526 fprintf(dmp->f, "--------------\n");
532 " pure address calc ops : %u\n"
533 " all address calc ops : %u\n",
534 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
535 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
538 /* Load/Store address classification */
540 " global Ld/St address : %u\n"
541 " local Ld/St address : %u\n"
542 " this Ld/St address : %u\n"
543 " param Ld/St address : %u\n"
544 " other Ld/St address : %u\n",
545 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
546 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
547 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
548 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
549 cnt_to_uint(&entry->cnt[gcnt_other_adr])
552 simple_dump_opcode_hash(dmp, entry->opcode_hash);
553 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
555 /* effects of optimizations */
559 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
560 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
562 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
563 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
566 /* dump block info */
567 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
568 foreach_pset(entry->block_hash, b_entry) {
569 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
571 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
572 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
573 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
574 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
575 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
576 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
577 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
581 /* dump block reg pressure */
582 simple_dump_be_block_reg_pressure(dmp, entry);
584 /* dump block ready nodes distribution */
585 simple_dump_be_block_sched_ready(dmp, entry);
587 /* dump block permutation statistics */
588 simple_dump_be_block_permstat(dmp, entry);
590 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
591 /* dump extended block info */
592 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
593 foreach_pset(entry->extbb_hash, eb_entry) {
594 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
596 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
597 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
598 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
599 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
600 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
601 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
606 } /* simple_dump_graph */
609 * dumps the constant table
611 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
621 fprintf(dmp->f, "\nConstant Information:\n");
622 fprintf(dmp->f, "---------------------\n");
624 fprintf(dmp->f, "\nBit usage for integer constants\n");
625 fprintf(dmp->f, "-------------------------------\n");
627 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
628 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
629 cnt_add(&sum, &tbl->int_bits_count[i]);
631 fprintf(dmp->f, "-------------------------------\n");
633 fprintf(dmp->f, "\nFloating point constants classification\n");
634 fprintf(dmp->f, "--------------------------------------\n");
635 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
636 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
637 cnt_add(&sum, &tbl->floats[i]);
639 fprintf(dmp->f, "--------------------------------------\n");
641 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
642 cnt_add(&sum, &tbl->others);
643 fprintf(dmp->f, "-------------------------------\n");
645 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
646 } /* simple_dump_const_tbl */
649 * Dumps a line of the parameter table
651 static void dump_tbl_line(const distrib_entry_t *entry, void *env)
655 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
656 } /* dump_tbl_line */
659 * dumps the parameter distribution table
661 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global)
663 fprintf(dmp->f, "\nCall parameter Information:\n");
664 fprintf(dmp->f, "---------------------\n");
666 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
667 fprintf(dmp->f, "-------------------------------\n");
669 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
670 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
671 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
672 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
673 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
674 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
675 } /* simple_dump_param_tbl */
678 * dumps the optimization counter table
680 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len)
684 fprintf(dmp->f, "\nOptimization counts:\n");
685 fprintf(dmp->f, "---------------------\n");
687 for (i = 0; i < len; ++i) {
688 unsigned cnt = cnt_to_uint(&tbl[i]);
691 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
694 } /* simple_dump_opt_cnt */
697 * initialize the simple dumper
699 static void simple_init(dumper_t *dmp, const char *name)
703 snprintf(fname, sizeof(fname), "%s.txt", name);
704 dmp->f = fopen(fname, "w");
711 * finishes the simple dumper
713 static void simple_finish(dumper_t *dmp)
718 } /* simple_finish */
721 * the simple human readable dumper
723 const dumper_t simple_dumper = {
725 simple_dump_const_tbl,
726 simple_dump_param_tbl,
734 FOURCC('S', 'M', 'P', 'L'),
737 /* ---------------------------------------------------------------------- */
740 * count the nodes as needed:
742 * 1 normal (data) Phi's
747 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
752 for (i = 0; i < 4; ++i)
755 foreach_pset(graph->opcode_hash, entry) {
756 if (entry->op == op_Phi) {
758 cnt_add(&cnt[1], &entry->cnt_alive);
759 } else if (entry->op == dmp->status->op_PhiM) {
761 cnt_add(&cnt[2], &entry->cnt_alive);
762 } else if (entry->op == op_Proj) {
764 cnt_add(&cnt[3], &entry->cnt_alive);
766 /* all other nodes */
767 cnt_add(&cnt[0], &entry->cnt_alive);
770 } /* csv_count_nodes */
775 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
783 if (entry->irg && !entry->is_deleted) {
784 ir_graph *const_irg = get_const_code_irg();
786 if (entry->irg == const_irg) {
787 name = "<Const code Irg>";
791 name = get_entity_name(entry->ent);
793 name = "<UNKNOWN IRG>";
796 csv_count_nodes(dmp, entry, cnt);
798 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
801 cnt_to_uint(&cnt[0]),
802 cnt_to_uint(&cnt[1]),
803 cnt_to_uint(&cnt[2]),
807 } /* csv_dump_graph */
812 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
817 } /* csv_dump_const_tbl */
820 * dumps the parameter distribution table
822 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global)
828 } /* csv_dump_param_tbl */
831 * dumps the optimization counter
833 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len)
839 } /* csv_dump_opt_cnt */
842 * initialize the simple dumper
844 static void csv_init(dumper_t *dmp, const char *name)
848 snprintf(fname, sizeof(fname), "%s.csv", name);
849 dmp->f = fopen(fname, "a");
855 * finishes the simple dumper
857 static void csv_finish(dumper_t *dmp)
865 * the simple human readable dumper
867 const dumper_t csv_dumper = {
878 FOURCC('C', 'S', 'V', '\0')