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
34 * names of the optimizations
40 { HOOK_OPT_DEAD_BLOCK, "dead block elimination" },
41 { HOOK_OPT_STG, "straightening optimization" },
42 { HOOK_OPT_IFSIM, "if simplification" },
43 { HOOK_OPT_CONST_EVAL, "constant evaluation" },
44 { HOOK_OPT_ALGSIM, "algebraic simplification" },
45 { HOOK_OPT_PHI, "Phi optmization" },
46 { HOOK_OPT_SYNC, "Sync optmization" },
47 { HOOK_OPT_WAW, "Write-After-Write optimization" },
48 { HOOK_OPT_WAR, "Write-After-Read optimization" },
49 { HOOK_OPT_RAW, "Read-After-Write optimization" },
50 { HOOK_OPT_RAR, "Read-After-Read optimization" },
51 { HOOK_OPT_RC, "Read-a-Const optimization" },
52 { HOOK_OPT_TUPLE, "Tuple optimization" },
53 { HOOK_OPT_ID, "ID optimization" },
54 { HOOK_OPT_CSE, "Common subexpression elimination" },
55 { HOOK_OPT_STRENGTH_RED, "Strength reduction" },
56 { HOOK_OPT_ARCH_DEP, "Architecture dependant optimization" },
57 { HOOK_OPT_REASSOC, "Reassociation optimization" },
58 { HOOK_OPT_POLY_CALL, "Polymorphic call optimization" },
59 { HOOK_OPT_IF_CONV, "an if conversion was tried" },
60 { HOOK_OPT_FUNC_CALL, "Real function call optimization" },
61 { HOOK_OPT_CONFIRM, "Confirm-based optimization: replacement" },
62 { HOOK_OPT_CONFIRM_C, "Confirm-based optimization: replaced by const" },
63 { HOOK_OPT_CONFIRM_E, "Confirm-based optimization: evaluated" },
64 { HOOK_OPT_EXC_REM, "a exception edge was removed due to a Confirmation prove" },
65 { HOOK_OPT_NORMALIZE, "a commutative node was normalized" },
66 { HOOK_LOWERED, "Lowered" },
67 { HOOK_BACKEND, "Backend transformation" },
68 { FS_OPT_NEUTRAL_0, "algebraic simplification: a op 0 = 0 op a = a" },
69 { FS_OPT_NEUTRAL_1, "algebraic simplification: a op 1 = 1 op a = a" },
70 { FS_OPT_ADD_A_A, "algebraic simplification: a + a = a * 2" },
71 { FS_OPT_ADD_A_MINUS_B, "algebraic simplification: a + -b = a - b" },
72 { FS_OPT_ADD_SUB, "algebraic simplification: (a + x) - x = (a - x) + x = a" },
73 { FS_OPT_ADD_MUL_A_X_A, "algebraic simplification: a * x + a = a * (x + 1)" },
74 { FS_OPT_SUB_0_A, "algebraic simplification: 0 - a = -a" },
75 { FS_OPT_MINUS_SUB, "algebraic simplification: -(a - b) = b - a" },
76 { FS_OPT_SUB_MINUS, "algebraic simplification: a - (-b) = a + b" },
77 { FS_OPT_SUB_MUL_A_X_A, "algebraic simplification: a * x - a = a * (x - 1)" },
78 { FS_OPT_SUB_SUB_X_Y_Z, "algebraic simplification: (x - y) - z = x - (y + z)" },
79 { FS_OPT_SUB_C_NOT_X, "algebraic simplification: c - ~a = a + (c+1)" },
80 { FS_OPT_SUB_TO_ADD, "algebraic simplification: (-a) - b = -(a + b), a - (b - c) = a + (c - b), a - (b * C) = a + (b * -C)" },
81 { FS_OPT_SUB_TO_NOT, "algebraic simplification: -1 - x -> ~x" },
82 { FS_OPT_SUB_TO_CONV, "algebraic simplification: a - NULL = (int)a" },
83 { FS_OPT_MUL_MINUS, "algebraic simplification: (-a) * (b - c) = a * (c - b)" },
84 { FS_OPT_MUL_MINUS_1, "algebraic simplification: a * -1 = -a" },
85 { FS_OPT_MINUS_MUL_C, "algebraic simplification: (-a) * C = a * (-C)" },
86 { FS_OPT_MUL_MINUS_MINUS,"algebraic simplification: (-a) * (-b) = a * b" },
87 { FS_OPT_OR, "algebraic simplification: a | a = a | 0 = 0 | a = a" },
88 { FS_OPT_AND, "algebraic simplification: a & 0b1...1 = 0b1...1 & a = a & a = (a|X) & a = a" },
89 { FS_OPT_TO_EOR, "algebraic simplification: (a|b) & ~(a&b) = a^b" },
90 { FS_OPT_EOR_A_A, "algebraic simplification: a ^ a = 0" },
91 { FS_OPT_EOR_A_B_A, "algebraic simplification: (a ^ b) ^ a = b" },
92 { FS_OPT_EOR_TO_NOT_BOOL,"boolean simplification: bool ^ 1 = !bool" },
93 { FS_OPT_EOR_TO_NOT, "algebraic simplification: x ^ 0b1..1 = ~x, (a ^ b) & b = ~a & b" },
94 { FS_OPT_NOT_CMP, "algebraic simplification: !(a cmp b) = a !cmp b" },
95 { FS_OPT_OR_SHFT_TO_ROTL,"algebraic simplification: (x << c) | (x >> (bits - c)) == Rotl(x, c)" },
96 { FS_OPT_REASSOC_SHIFT, "algebraic simplification: (x SHF c1) SHF c2 = x SHF (c1+c2)" },
97 { FS_OPT_SHIFT_AND, "algebraic simplification: (a SHF c) AND (b SHF c) = (a AND b) SHF c" },
98 { FS_OPT_SHIFT_OR, "algebraic simplification: (a SHF c) OR (b SHF c) = (a OR b) SHF c" },
99 { FS_OPT_SHIFT_EOR, "algebraic simplification: (a SHF c) XOR (b SHF c) = (a XOR b) SHF c" },
100 { FS_OPT_CONV, "algebraic simplification: Conv could be removed" },
101 { FS_OPT_CAST, "algebraic simplification: a Cast could be removed" },
102 { FS_OPT_MIN_MAX_EQ, "algebraic simplification: Min(a,a) = Max(a,a) = a" },
103 { FS_OPT_MUX_COMBINE, "boolean simplification: two Mux nodes where combined into one" },
104 { FS_OPT_MUX_CONV, "boolean simplification: MuxI(sel, 1, 0) = (I)sel" },
105 { FS_OPT_MUX_BOOL, "boolean simplification: Muxb(sel, true, false) = sel" },
106 { FS_OPT_MUX_NOT_BOOL, "boolean simplification: Muxb(sel, false, true) = Not(sel)" },
107 { FS_OPT_MUX_OR_BOOL, "boolean simplification: Muxb(sel, true, x) = Or(sel, x)" },
108 { FS_OPT_MUX_ORNOT_BOOL, "boolean simplification: Muxb(sel, x, true) = Or(Not(sel), x)" },
109 { FS_OPT_MUX_AND_BOOL, "boolean simplification: Muxb(sel, x, false) = And(sel, x)" },
110 { FS_OPT_MUX_ANDNOT_BOOL,"boolean simplification: Muxb(sel, false, x) = And(Not(sel), x)" },
111 { FS_OPT_MUX_C, "algebraic simplification: Mux(C, f, t) = C ? t : f" },
112 { FS_OPT_MUX_EQ, "algebraic simplification: Mux(v, x, x) = x" },
113 { FS_OPT_MUX_TRANSFORM, "algebraic simplification: Mux(t ==/!= f, t, f) = f/t, Mux(t ==/!= 0, -t, t) = -t/t" },
114 { FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
115 { FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
116 { FS_OPT_MUX_TO_ABS, "algebraic simplification: Mux(a > 0, a, -a) = Abs(a)" },
117 { FS_OPT_MUX_TO_BITOP, "algebraic simplification: Mux((a & 2^x) ==/!= 0, 2^x, 0) = (a & 2^x) (xor 2^x)" },
118 { FS_OPT_IDEM_UNARY, "algebraic simplification: Idempotent unary operation" },
119 { FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
120 { FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
121 { FS_OPT_NOT_PLUS_1, "algebraic simplification: ~x + 1 = -x" },
122 { FS_OPT_ADD_X_NOT_X, "algebraic simplification: ~x + x = -1" },
123 { FS_OPT_FP_INV_MUL, "algebraic simplification: x / y = x * (1.0/y)" },
124 { FS_OPT_ABS_MINUS_X, "algebraic simplification: Abs(-x) = Abs(x)" },
125 { FS_OPT_CONST_PHI, "constant evaluation on Phi node" },
126 { FS_OPT_PREDICATE, "predicate optimization" },
127 { FS_OPT_DEMORGAN, "optimization using DeMorgan's law" },
128 { FS_OPT_CMP_OP_OP, "CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y)" },
129 { FS_OPT_CMP_OP_C, "CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2)" },
130 { FS_OPT_CMP_CONV_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y)" },
131 { FS_OPT_CMP_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y)" },
132 { FS_OPT_CMP_TO_BOOL, "CMP optimization: Cmp(x, y) = BoolOP(x, y)" },
133 { FS_OPT_CMP_CNST_MAGN, "CMP optimization: reduced magnitude of a const" },
134 { FS_OPT_CMP_SHF_TO_AND, "CMP optimization: transformed shift into And" },
135 { FS_OPT_CMP_MOD_TO_AND, "CMP optimization: transformed Mod into And" },
136 { FS_OPT_NOP, "the operation is a NOP" },
137 { FS_OPT_GVN_FOLLOWER, "GVN-PRE: replaced a follower" },
138 { FS_OPT_GVN_FULLY, "GVN-PRE: replaced by fully redundant value" },
139 { FS_OPT_GVN_PARTLY, "GVN-PRE: replaced by partly redundant value" },
140 { FS_OPT_COMBO_CONST, "Combo: evaluated into Constant" },
141 { FS_OPT_COMBO_CF, "Combo: removed conditional control flow" },
142 { FS_OPT_COMBO_FOLLOWER, "Combo: removed a follower" },
143 { FS_OPT_COMBO_CONGRUENT,"Combo: replaced by congruent" },
144 { FS_OPT_JUMPTHREADING, "Jump threading: removed conditional control flow" },
145 { FS_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
146 { FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
147 { FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
148 { FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
149 { FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
150 { FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
151 { FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
152 { FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
153 { FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
154 { FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
155 { FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
156 { FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
157 { FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
158 { FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
159 { FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
160 { FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
161 { FS_OPT_RTS_SYMMETRIC, "RTS optimization: call to symmetric function f(-x) replaced by f(x)" },
162 { FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
163 { FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
164 { FS_OPT_RTS_STRCPY, "RTS optimization: call to strcpy() replaced" },
165 { FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
166 { FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
167 { FS_OPT_RTS_MEMPCPY, "RTS optimization: call to mempcpy() replaced" },
168 { FS_OPT_RTS_MEMMOVE, "RTS optimization: call to memmove() replaced" },
169 { FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
170 { FS_OPT_RTS_MEMCMP, "RTS optimization: call to memcmp() replaced" },
171 { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
172 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
173 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
174 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
175 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
176 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
177 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
178 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
179 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
180 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
181 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
184 static const char *if_conv_names[IF_RESULT_LAST] = {
186 "if conv side effect ",
187 "if conv Phi node found ",
188 "if conv to deep DAG's ",
189 "if conv bad control flow ",
190 "if conv denied by arch ",
194 * dumps a opcode hash into human readable form
196 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
200 counter_t f_new_node;
202 counter_t f_normlized;
205 cnt_clr(&f_new_node);
207 cnt_clr(&f_normlized);
209 fprintf(dmp->f, "%-16s %-8s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id", "normalized");
210 foreach_pset(set, entry) {
211 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n",
212 get_id_str(entry->op->name),
213 cnt_to_uint(&entry->cnt_alive),
214 cnt_to_uint(&entry->new_node),
215 cnt_to_uint(&entry->into_Id),
216 cnt_to_uint(&entry->normalized)
219 cnt_add(&f_alive, &entry->cnt_alive);
220 cnt_add(&f_new_node, &entry->new_node);
221 cnt_add(&f_Id, &entry->into_Id);
222 cnt_add(&f_normlized, &entry->normalized);
224 fprintf(dmp->f, "-------------------------------------------\n");
225 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n", "Sum",
226 cnt_to_uint(&f_alive),
227 cnt_to_uint(&f_new_node),
229 cnt_to_uint(&f_normlized)
231 } /* simple_dump_opcode_hash */
234 * Return the name of an optimization.
236 static const char *get_opt_name(int index)
238 assert(index < (int) ARRAY_SIZE(opt_names) && "index out of range");
239 assert((int) opt_names[index].kind == index && "opt_names broken");
240 return opt_names[index].name;
244 * dumps an optimization hash into human readable form
246 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
248 if (pset_count(set) > 0) {
250 const char *name = get_opt_name(index);
252 fprintf(dmp->f, "\n%s:\n", name);
253 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
255 foreach_pset(set, entry) {
256 fprintf(dmp->f, "%-16s %8u\n",
257 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
260 } /* simple_dump_opt_hash */
263 * dumps the register pressure for each block and for each register class
265 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
267 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
268 reg_pressure_entry_t *rp_entry;
270 /* return if no be statistic information available */
274 fprintf(dmp->f, "\nREG PRESSURE:\n");
275 fprintf(dmp->f, "%12s", "Block Nr");
277 /* print table head (register class names) */
278 foreach_pset(b_entry->reg_pressure, rp_entry)
279 fprintf(dmp->f, "%15s", rp_entry->class_name);
280 fprintf(dmp->f, "\n");
282 /* print the reg pressure for all blocks and register classes */
283 for (/* b_entry is already initialized */ ;
285 b_entry = pset_next(entry->be_block_hash)) {
286 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
288 foreach_pset(b_entry->reg_pressure, rp_entry)
289 fprintf(dmp->f, "%15d", rp_entry->pressure);
290 fprintf(dmp->f, "\n");
292 } /* simple_dump_be_block_reg_pressure */
294 /** prints a distribution entry */
295 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env)
298 fprintf(dmp->f, "%12u", cnt_to_uint(&entry->cnt));
299 } /* simple_dump_distrib_entry */
302 * dumps the distribution of the amount of ready nodes for each block
304 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
306 if (pset_count(entry->be_block_hash) > 0) {
307 be_block_entry_t *b_entry;
310 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
311 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
312 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
314 foreach_pset(entry->be_block_hash, b_entry) {
315 /* this ensures that all keys from 1 to 5 are in the table */
316 for (i = 1; i < 6; ++i)
317 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
319 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
320 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
321 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
322 fprintf(dmp->f, "\n");
325 } /* simple_dump_be_block_sched_ready */
328 * Adds the counter for given entry to another distribution table.
330 static void add_distrib_entry(const distrib_entry_t *entry, void *env)
332 distrib_tbl_t *sum_tbl = env;
334 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
335 } /* add_distrib_entry */
338 * dumps permutation statistics for one and block and one class
340 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
342 perm_stat_entry_t *ps_ent;
343 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
344 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
348 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
357 foreach_pset(entry->perm_stat, ps_ent) {
358 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
361 stat_get_count_distrib_tbl(ps_ent->chains),
362 stat_get_count_distrib_tbl(ps_ent->cycles),
367 /* sum up distribution table for chains */
368 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
370 /* sum up distribution table for cycles */
371 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
374 /* print chain distribution for all perms of this class in this block */
375 fprintf(dmp->f, "chain distribution:\n");
377 /* add all missing entries to chain distribution table */
378 for (i = 1; i <= entry->n_regs; i++) {
379 snprintf(buf, sizeof(buf), "length %d", i);
380 fprintf(dmp->f, "%12s", buf);
381 stat_insert_int_distrib_tbl(sum_chains, i);
383 fprintf(dmp->f, "\n");
384 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
385 fprintf(dmp->f, "\n");
387 /* print cycle distribution for all perms of this class in this block */
388 fprintf(dmp->f, "cycle distribution:\n");
390 /* add all missing entries to cycle distribution table */
391 for (i = 1; i <= entry->n_regs; i++) {
392 snprintf(buf, sizeof(buf), "length %d", i);
393 fprintf(dmp->f, "%12s", buf);
394 stat_insert_int_distrib_tbl(sum_cycles, i);
396 fprintf(dmp->f, "\n");
397 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
398 fprintf(dmp->f, "\n");
400 /* delete temporary sum distribution tables */
401 stat_delete_distrib_tbl(sum_chains);
402 stat_delete_distrib_tbl(sum_cycles);
404 } /* simple_dump_be_block_permstat_class */
407 * dumps statistics about perms
409 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
411 if (pset_count(entry->be_block_hash) > 0) {
412 be_block_entry_t *b_entry;
414 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
415 foreach_pset(entry->be_block_hash, b_entry) {
416 perm_class_entry_t *pc_ent;
418 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
420 if (b_entry->perm_class_stat) {
421 foreach_pset(b_entry->perm_class_stat, pc_ent) {
422 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
423 simple_dump_be_block_permstat_class(dmp, pc_ent);
428 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
430 } /* simple_dump_be_block_permstat */
433 * dumps the number of real_function_call optimization
435 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
440 if (! cnt_eq(cnt, 0)) {
441 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
442 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
444 } /* simple_dump_real_func_calls */
447 * dumps the number of tail_recursion optimization
449 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
454 if (num_tail_recursion > 0) {
455 fprintf(dmp->f, "\nTail recursion optimized:\n");
456 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
458 } /* simple_dump_tail_recursion */
461 * dumps the edges count
463 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
468 fprintf(dmp->f, "%-16s %8u\n", "Edges", cnt_to_uint(cnt));
469 } /* simple_dump_edges */
474 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
476 int i, dump_opts = 1;
477 block_entry_t *b_entry;
478 extbb_entry_t *eb_entry;
484 ir_graph *const_irg = get_const_code_irg();
486 if (entry->irg == const_irg)
487 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
490 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
492 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
495 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
496 " was inlined : %u\n"
497 " got inlined : %u\n"
498 " strength red : %u\n"
499 " leaf function : %s\n"
500 " calls only leaf functions : %s\n"
505 " indirect calls : %u\n"
506 " external calls : %u\n",
507 entry->is_deleted ? "DELETED " : "",
508 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
509 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
510 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
511 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
512 entry->is_leaf ? "YES" : "NO",
513 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
514 entry->is_recursive ? "YES" : "NO",
515 entry->is_chain_call ? "YES" : "NO",
516 entry->is_strict ? "YES" : "NO",
517 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
518 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
519 cnt_to_uint(&entry->cnt[gcnt_external_calls])
522 for (i = 0; i < IF_RESULT_LAST; ++i) {
523 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
526 fprintf(dmp->f, "\nGlobals counts:\n");
527 fprintf(dmp->f, "--------------\n");
533 " pure address calc ops : %u\n"
534 " all address calc ops : %u\n",
535 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
536 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
539 /* Load/Store address classification */
541 " global Ld/St address : %u\n"
542 " local Ld/St address : %u\n"
543 " this Ld/St address : %u\n"
544 " param Ld/St address : %u\n"
545 " other Ld/St address : %u\n",
546 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
547 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
548 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
549 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
550 cnt_to_uint(&entry->cnt[gcnt_other_adr])
553 simple_dump_opcode_hash(dmp, entry->opcode_hash);
554 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
556 /* effects of optimizations */
560 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
561 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
563 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
564 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
567 /* dump block info */
568 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
569 foreach_pset(entry->block_hash, b_entry) {
570 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
572 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
573 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
574 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
575 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
576 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
577 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
578 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
582 /* dump block reg pressure */
583 simple_dump_be_block_reg_pressure(dmp, entry);
585 /* dump block ready nodes distribution */
586 simple_dump_be_block_sched_ready(dmp, entry);
588 /* dump block permutation statistics */
589 simple_dump_be_block_permstat(dmp, entry);
591 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
592 /* dump extended block info */
593 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
594 foreach_pset(entry->extbb_hash, eb_entry) {
595 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
597 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
598 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
599 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
600 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
601 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
602 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
607 } /* simple_dump_graph */
610 * dumps the constant table
612 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
622 fprintf(dmp->f, "\nConstant Information:\n");
623 fprintf(dmp->f, "---------------------\n");
625 fprintf(dmp->f, "\nBit usage for integer constants\n");
626 fprintf(dmp->f, "-------------------------------\n");
628 for (i = 0; i < ARRAY_SIZE(tbl->int_bits_count); ++i) {
629 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
630 cnt_add(&sum, &tbl->int_bits_count[i]);
632 fprintf(dmp->f, "-------------------------------\n");
634 fprintf(dmp->f, "\nFloating point constants classification\n");
635 fprintf(dmp->f, "--------------------------------------\n");
636 for (i = 0; i < ARRAY_SIZE(tbl->floats); ++i) {
637 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
638 cnt_add(&sum, &tbl->floats[i]);
640 fprintf(dmp->f, "--------------------------------------\n");
642 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
643 cnt_add(&sum, &tbl->others);
644 fprintf(dmp->f, "-------------------------------\n");
646 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
647 } /* simple_dump_const_tbl */
650 * Dumps a line of the parameter table
652 static void dump_tbl_line(const distrib_entry_t *entry, void *env)
656 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
657 } /* dump_tbl_line */
660 * dumps the parameter distribution table
662 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global)
664 fprintf(dmp->f, "\nCall parameter Information:\n");
665 fprintf(dmp->f, "---------------------\n");
667 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
668 fprintf(dmp->f, "-------------------------------\n");
670 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
671 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
672 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
673 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
674 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
675 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
676 } /* simple_dump_param_tbl */
679 * dumps the optimization counter table
681 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len)
685 fprintf(dmp->f, "\nOptimization counts:\n");
686 fprintf(dmp->f, "---------------------\n");
688 for (i = 0; i < len; ++i) {
689 unsigned cnt = cnt_to_uint(&tbl[i]);
692 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
695 } /* simple_dump_opt_cnt */
698 * initialize the simple dumper
700 static void simple_init(dumper_t *dmp, const char *name)
704 snprintf(fname, sizeof(fname), "%s.txt", name);
705 dmp->f = fopen(fname, "w");
712 * finishes the simple dumper
714 static void simple_finish(dumper_t *dmp)
719 } /* simple_finish */
722 * the simple human readable dumper
724 const dumper_t simple_dumper = {
726 simple_dump_const_tbl,
727 simple_dump_param_tbl,
735 FOURCC('S', 'M', 'P', 'L'),
738 /* ---------------------------------------------------------------------- */
741 * count the nodes as needed:
743 * 1 normal (data) Phi's
748 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
753 for (i = 0; i < 4; ++i)
756 foreach_pset(graph->opcode_hash, entry) {
757 if (entry->op == op_Phi) {
759 cnt_add(&cnt[1], &entry->cnt_alive);
760 } else if (entry->op == dmp->status->op_PhiM) {
762 cnt_add(&cnt[2], &entry->cnt_alive);
763 } else if (entry->op == op_Proj) {
765 cnt_add(&cnt[3], &entry->cnt_alive);
767 /* all other nodes */
768 cnt_add(&cnt[0], &entry->cnt_alive);
771 } /* csv_count_nodes */
776 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
784 if (entry->irg && !entry->is_deleted) {
785 ir_graph *const_irg = get_const_code_irg();
787 if (entry->irg == const_irg) {
788 name = "<Const code Irg>";
792 name = get_entity_name(entry->ent);
794 name = "<UNKNOWN IRG>";
797 csv_count_nodes(dmp, entry, cnt);
799 fprintf(dmp->f, "%-40s, %p, %u, %u, %u, %u\n",
802 cnt_to_uint(&cnt[0]),
803 cnt_to_uint(&cnt[1]),
804 cnt_to_uint(&cnt[2]),
808 } /* csv_dump_graph */
813 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
818 } /* csv_dump_const_tbl */
821 * dumps the parameter distribution table
823 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global)
829 } /* csv_dump_param_tbl */
832 * dumps the optimization counter
834 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len)
840 } /* csv_dump_opt_cnt */
843 * initialize the simple dumper
845 static void csv_init(dumper_t *dmp, const char *name)
849 snprintf(fname, sizeof(fname), "%s.csv", name);
850 dmp->f = fopen(fname, "a");
856 * finishes the simple dumper
858 static void csv_finish(dumper_t *dmp)
866 * the simple human readable dumper
868 const dumper_t csv_dumper = {
879 FOURCC('C', 'S', 'V', '\0')