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_STRCPY, "RTS optimization: call to strcpy() replaced" },
161 { FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
162 { FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
163 { FS_OPT_RTS_MEMPCPY, "RTS optimization: call to mempcpy() replaced" },
164 { FS_OPT_RTS_MEMMOVE, "RTS optimization: call to memmove() replaced" },
165 { FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
166 { FS_OPT_RTS_MEMCMP, "RTS optimization: call to memcmp() replaced" },
167 { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
168 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
169 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
170 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
171 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
172 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
173 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
174 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
175 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
176 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
177 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
180 static const char *if_conv_names[IF_RESULT_LAST] = {
182 "if conv side effect ",
183 "if conv Phi node found ",
184 "if conv to deep DAG's ",
185 "if conv bad control flow ",
186 "if conv denied by arch ",
190 * dumps a opcode hash into human readable form
192 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
196 counter_t f_new_node;
198 counter_t f_normlized;
201 cnt_clr(&f_new_node);
203 cnt_clr(&f_normlized);
205 fprintf(dmp->f, "%-16s %-8s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id", "normalized");
206 foreach_pset(set, entry) {
207 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n",
208 get_id_str(entry->op->name),
209 cnt_to_uint(&entry->cnt_alive),
210 cnt_to_uint(&entry->new_node),
211 cnt_to_uint(&entry->into_Id),
212 cnt_to_uint(&entry->normalized)
215 cnt_add(&f_alive, &entry->cnt_alive);
216 cnt_add(&f_new_node, &entry->new_node);
217 cnt_add(&f_Id, &entry->into_Id);
218 cnt_add(&f_normlized, &entry->normalized);
220 fprintf(dmp->f, "-------------------------------------------\n");
221 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n", "Sum",
222 cnt_to_uint(&f_alive),
223 cnt_to_uint(&f_new_node),
225 cnt_to_uint(&f_normlized)
227 } /* simple_dump_opcode_hash */
230 * Return the name of an optimization.
232 static const char *get_opt_name(int index) {
233 assert(index < (int) ARR_SIZE(opt_names) && "index out of range");
234 assert((int) opt_names[index].kind == index && "opt_names broken");
235 return opt_names[index].name;
239 * dumps an optimization hash into human readable form
241 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
243 if (pset_count(set) > 0) {
245 const char *name = get_opt_name(index);
247 fprintf(dmp->f, "\n%s:\n", name);
248 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
250 foreach_pset(set, entry) {
251 fprintf(dmp->f, "%-16s %8u\n",
252 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
255 } /* simple_dump_opt_hash */
258 * dumps the register pressure for each block and for each register class
260 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
262 be_block_entry_t *b_entry = pset_first(entry->be_block_hash);
263 reg_pressure_entry_t *rp_entry;
265 /* return if no be statistic information available */
269 fprintf(dmp->f, "\nREG PRESSURE:\n");
270 fprintf(dmp->f, "%12s", "Block Nr");
272 /* print table head (register class names) */
273 foreach_pset(b_entry->reg_pressure, rp_entry)
274 fprintf(dmp->f, "%15s", rp_entry->class_name);
275 fprintf(dmp->f, "\n");
277 /* print the reg pressure for all blocks and register classes */
278 for (/* b_entry is already initialized */ ;
280 b_entry = pset_next(entry->be_block_hash)) {
281 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
283 foreach_pset(b_entry->reg_pressure, rp_entry)
284 fprintf(dmp->f, "%15d", rp_entry->pressure);
285 fprintf(dmp->f, "\n");
287 } /* simple_dump_be_block_reg_pressure */
289 /** prints a distribution entry */
290 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env) {
292 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
293 } /* simple_dump_distrib_entry */
296 * dumps the distribution of the amount of ready nodes for each block
298 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
300 if (pset_count(entry->be_block_hash) > 0) {
301 be_block_entry_t *b_entry;
304 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
305 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
306 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
308 foreach_pset(entry->be_block_hash, b_entry) {
309 /* this ensures that all keys from 1 to 5 are in the table */
310 for (i = 1; i < 6; ++i)
311 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
313 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
314 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
315 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
316 fprintf(dmp->f, "\n");
319 } /* simple_dump_be_block_sched_ready */
322 * Adds the counter for given entry to another distribution table.
324 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
325 distrib_tbl_t *sum_tbl = env;
327 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
328 } /* add_distrib_entry */
331 * dumps permutation statistics for one and block and one class
333 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
335 perm_stat_entry_t *ps_ent;
336 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
337 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
341 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
350 foreach_pset(entry->perm_stat, ps_ent) {
351 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
354 stat_get_count_distrib_tbl(ps_ent->chains),
355 stat_get_count_distrib_tbl(ps_ent->cycles),
360 /* sum up distribution table for chains */
361 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
363 /* sum up distribution table for cycles */
364 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
367 /* print chain distribution for all perms of this class in this block */
368 fprintf(dmp->f, "chain distribution:\n");
370 /* add all missing entries to chain distribution table */
371 for (i = 1; i <= entry->n_regs; i++) {
372 snprintf(buf, sizeof(buf), "length %d", i);
373 fprintf(dmp->f, "%12s", buf);
374 stat_insert_int_distrib_tbl(sum_chains, i);
376 fprintf(dmp->f, "\n");
377 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
378 fprintf(dmp->f, "\n");
380 /* print cycle distribution for all perms of this class in this block */
381 fprintf(dmp->f, "cycle distribution:\n");
383 /* add all missing entries to cycle distribution table */
384 for (i = 1; i <= entry->n_regs; i++) {
385 snprintf(buf, sizeof(buf), "length %d", i);
386 fprintf(dmp->f, "%12s", buf);
387 stat_insert_int_distrib_tbl(sum_cycles, i);
389 fprintf(dmp->f, "\n");
390 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
391 fprintf(dmp->f, "\n");
393 /* delete temporary sum distribution tables */
394 stat_delete_distrib_tbl(sum_chains);
395 stat_delete_distrib_tbl(sum_cycles);
397 } /* simple_dump_be_block_permstat_class */
400 * dumps statistics about perms
402 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
404 if (pset_count(entry->be_block_hash) > 0) {
405 be_block_entry_t *b_entry;
407 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
408 foreach_pset(entry->be_block_hash, b_entry) {
409 perm_class_entry_t *pc_ent;
411 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
413 if (b_entry->perm_class_stat) {
414 foreach_pset(b_entry->perm_class_stat, pc_ent) {
415 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
416 simple_dump_be_block_permstat_class(dmp, pc_ent);
421 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
423 } /* simple_dump_be_block_permstat */
426 * dumps the number of real_function_call optimization
428 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
433 if (! cnt_eq(cnt, 0)) {
434 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
435 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
437 } /* simple_dump_real_func_calls */
440 * dumps the number of tail_recursion optimization
442 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
447 if (num_tail_recursion > 0) {
448 fprintf(dmp->f, "\nTail recursion optimized:\n");
449 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
451 } /* simple_dump_tail_recursion */
454 * dumps the edges count
456 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
461 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
462 } /* simple_dump_edges */
467 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
469 int i, dump_opts = 1;
470 block_entry_t *b_entry;
471 extbb_entry_t *eb_entry;
477 ir_graph *const_irg = get_const_code_irg();
479 if (entry->irg == const_irg)
480 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
483 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
485 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
488 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
489 " was inlined : %u\n"
490 " got inlined : %u\n"
491 " strength red : %u\n"
492 " leaf function : %s\n"
493 " calls only leaf functions : %s\n"
498 " indirect calls : %u\n"
499 " external calls : %u\n",
500 entry->is_deleted ? "DELETED " : "",
501 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
502 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
503 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
504 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
505 entry->is_leaf ? "YES" : "NO",
506 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
507 entry->is_recursive ? "YES" : "NO",
508 entry->is_chain_call ? "YES" : "NO",
509 entry->is_strict ? "YES" : "NO",
510 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
511 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
512 cnt_to_uint(&entry->cnt[gcnt_external_calls])
515 for (i = 0; i < IF_RESULT_LAST; ++i) {
516 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
519 fprintf(dmp->f, "\nGlobals counts:\n");
520 fprintf(dmp->f, "--------------\n");
526 " pure address calc ops : %u\n"
527 " all address calc ops : %u\n",
528 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
529 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
532 /* Load/Store address classification */
534 " global Ld/St address : %u\n"
535 " local Ld/St address : %u\n"
536 " this Ld/St address : %u\n"
537 " param Ld/St address : %u\n"
538 " other Ld/St address : %u\n",
539 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
540 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
541 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
542 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
543 cnt_to_uint(&entry->cnt[gcnt_other_adr])
546 simple_dump_opcode_hash(dmp, entry->opcode_hash);
547 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
549 /* effects of optimizations */
553 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
554 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
556 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
557 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
560 /* dump block info */
561 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
562 foreach_pset(entry->block_hash, b_entry) {
563 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
565 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
566 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
567 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
568 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
569 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
570 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
571 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
575 /* dump block reg pressure */
576 simple_dump_be_block_reg_pressure(dmp, entry);
578 /* dump block ready nodes distribution */
579 simple_dump_be_block_sched_ready(dmp, entry);
581 /* dump block permutation statistics */
582 simple_dump_be_block_permstat(dmp, entry);
584 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
585 /* dump extended block info */
586 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
587 foreach_pset(entry->extbb_hash, eb_entry) {
588 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
590 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
591 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
592 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
593 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
594 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
595 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
600 } /* simple_dump_graph */
603 * dumps the constant table
605 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
615 fprintf(dmp->f, "\nConstant Information:\n");
616 fprintf(dmp->f, "---------------------\n");
618 fprintf(dmp->f, "\nBit usage for integer constants\n");
619 fprintf(dmp->f, "-------------------------------\n");
621 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
622 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
623 cnt_add(&sum, &tbl->int_bits_count[i]);
625 fprintf(dmp->f, "-------------------------------\n");
627 fprintf(dmp->f, "\nFloating point constants classification\n");
628 fprintf(dmp->f, "--------------------------------------\n");
629 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
630 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
631 cnt_add(&sum, &tbl->floats[i]);
633 fprintf(dmp->f, "--------------------------------------\n");
635 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
636 cnt_add(&sum, &tbl->others);
637 fprintf(dmp->f, "-------------------------------\n");
639 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
640 } /* simple_dump_const_tbl */
643 * Dumps a line of the parameter table
645 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
648 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
649 } /* dump_tbl_line */
652 * dumps the parameter distribution table
654 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
655 fprintf(dmp->f, "\nCall parameter Information:\n");
656 fprintf(dmp->f, "---------------------\n");
658 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
659 fprintf(dmp->f, "-------------------------------\n");
661 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
662 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
663 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
664 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
665 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
666 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
667 } /* simple_dump_param_tbl */
670 * dumps the optimization counter table
672 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
675 fprintf(dmp->f, "\nOptimization counts:\n");
676 fprintf(dmp->f, "---------------------\n");
678 for (i = 0; i < len; ++i) {
679 unsigned cnt = cnt_to_uint(&tbl[i]);
682 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
685 } /* simple_dump_opt_cnt */
688 * initialize the simple dumper
690 static void simple_init(dumper_t *dmp, const char *name) {
693 snprintf(fname, sizeof(fname), "%s.txt", name);
694 dmp->f = fopen(fname, "w");
701 * finishes the simple dumper
703 static void simple_finish(dumper_t *dmp) {
707 } /* simple_finish */
710 * the simple human readable dumper
712 const dumper_t simple_dumper = {
714 simple_dump_const_tbl,
715 simple_dump_param_tbl,
723 FOURCC('S', 'M', 'P', 'L'),
726 /* ---------------------------------------------------------------------- */
729 * count the nodes as needed:
731 * 1 normal (data) Phi's
736 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
741 for (i = 0; i < 4; ++i)
744 foreach_pset(graph->opcode_hash, entry) {
745 if (entry->op == op_Phi) {
747 cnt_add(&cnt[1], &entry->cnt_alive);
748 } else if (entry->op == dmp->status->op_PhiM) {
750 cnt_add(&cnt[2], &entry->cnt_alive);
751 } else if (entry->op == op_Proj) {
753 cnt_add(&cnt[3], &entry->cnt_alive);
755 /* all other nodes */
756 cnt_add(&cnt[0], &entry->cnt_alive);
759 } /* csv_count_nodes */
764 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
772 if (entry->irg && !entry->is_deleted) {
773 ir_graph *const_irg = get_const_code_irg();
775 if (entry->irg == const_irg) {
776 name = "<Const code Irg>";
780 name = get_entity_name(entry->ent);
782 name = "<UNKNOWN IRG>";
785 csv_count_nodes(dmp, entry, cnt);
787 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
790 cnt_to_uint(&cnt[0]),
791 cnt_to_uint(&cnt[1]),
792 cnt_to_uint(&cnt[2]),
796 } /* csv_dump_graph */
801 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
806 } /* csv_dump_const_tbl */
809 * dumps the parameter distribution table
811 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
816 } /* csv_dump_param_tbl */
819 * dumps the optimization counter
821 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
826 } /* csv_dump_opt_cnt */
829 * initialize the simple dumper
831 static void csv_init(dumper_t *dmp, const char *name)
835 snprintf(fname, sizeof(fname), "%s.csv", name);
836 dmp->f = fopen(fname, "a");
842 * finishes the simple dumper
844 static void csv_finish(dumper_t *dmp)
852 * the simple human readable dumper
854 const dumper_t csv_dumper = {
865 FOURCC('C', 'S', 'V', '\0')