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 { (hook_opt_kind)FS_OPT_NEUTRAL_0, "algebraic simplification: a op 0 = 0 op a = a" },
69 { (hook_opt_kind)FS_OPT_NEUTRAL_1, "algebraic simplification: a op 1 = 1 op a = a" },
70 { (hook_opt_kind)FS_OPT_ADD_A_A, "algebraic simplification: a + a = a * 2" },
71 { (hook_opt_kind)FS_OPT_ADD_A_MINUS_B, "algebraic simplification: a + -b = a - b" },
72 { (hook_opt_kind)FS_OPT_ADD_SUB, "algebraic simplification: (a + x) - x = (a - x) + x = a" },
73 { (hook_opt_kind)FS_OPT_ADD_MUL_A_X_A, "algebraic simplification: a * x + a = a * (x + 1)" },
74 { (hook_opt_kind)FS_OPT_SUB_0_A, "algebraic simplification: 0 - a = -a" },
75 { (hook_opt_kind)FS_OPT_MINUS_SUB, "algebraic simplification: -(a - b) = b - a" },
76 { (hook_opt_kind)FS_OPT_SUB_MINUS, "algebraic simplification: a - (-b) = a + b" },
77 { (hook_opt_kind)FS_OPT_SUB_MUL_A_X_A, "algebraic simplification: a * x - a = a * (x - 1)" },
78 { (hook_opt_kind)FS_OPT_SUB_SUB_X_Y_Z, "algebraic simplification: (x - y) - z = x - (y + z)" },
79 { (hook_opt_kind)FS_OPT_SUB_C_NOT_X, "algebraic simplification: c - ~a = a + (c+1)" },
80 { (hook_opt_kind)FS_OPT_SUB_TO_ADD, "algebraic simplification: (-a) - b = -(a + b), a - (b - c) = a + (c - b), a - (b * C) = a + (b * -C)" },
81 { (hook_opt_kind)FS_OPT_SUB_TO_NOT, "algebraic simplification: -1 - x -> ~x" },
82 { (hook_opt_kind)FS_OPT_SUB_TO_CONV, "algebraic simplification: a - NULL = (int)a" },
83 { (hook_opt_kind)FS_OPT_MUL_MINUS, "algebraic simplification: (-a) * (b - c) = a * (c - b)" },
84 { (hook_opt_kind)FS_OPT_MUL_MINUS_1, "algebraic simplification: a * -1 = -a" },
85 { (hook_opt_kind)FS_OPT_MINUS_MUL_C, "algebraic simplification: (-a) * C = a * (-C)" },
86 { (hook_opt_kind)FS_OPT_MUL_MINUS_MINUS,"algebraic simplification: (-a) * (-b) = a * b" },
87 { (hook_opt_kind)FS_OPT_OR, "algebraic simplification: a | a = a | 0 = 0 | a = a" },
88 { (hook_opt_kind)FS_OPT_AND, "algebraic simplification: a & 0b1...1 = 0b1...1 & a = a & a = (a|X) & a = a" },
89 { (hook_opt_kind)FS_OPT_TO_EOR, "algebraic simplification: (a|b) & ~(a&b) = a^b" },
90 { (hook_opt_kind)FS_OPT_EOR_A_A, "algebraic simplification: a ^ a = 0" },
91 { (hook_opt_kind)FS_OPT_EOR_A_B_A, "algebraic simplification: (a ^ b) ^ a = b" },
92 { (hook_opt_kind)FS_OPT_EOR_TO_NOT_BOOL,"boolean simplification: bool ^ 1 = !bool" },
93 { (hook_opt_kind)FS_OPT_EOR_TO_NOT, "algebraic simplification: x ^ 0b1..1 = ~x, (a ^ b) & b = ~a & b" },
94 { (hook_opt_kind)FS_OPT_NOT_CMP, "algebraic simplification: !(a cmp b) = a !cmp b" },
95 { (hook_opt_kind)FS_OPT_OR_SHFT_TO_ROTL,"algebraic simplification: (x << c) | (x >> (bits - c)) == Rotl(x, c)" },
96 { (hook_opt_kind)FS_OPT_REASSOC_SHIFT, "algebraic simplification: (x SHF c1) SHF c2 = x SHF (c1+c2)" },
97 { (hook_opt_kind)FS_OPT_SHIFT_AND, "algebraic simplification: (a SHF c) AND (b SHF c) = (a AND b) SHF c" },
98 { (hook_opt_kind)FS_OPT_SHIFT_OR, "algebraic simplification: (a SHF c) OR (b SHF c) = (a OR b) SHF c" },
99 { (hook_opt_kind)FS_OPT_SHIFT_EOR, "algebraic simplification: (a SHF c) XOR (b SHF c) = (a XOR b) SHF c" },
100 { (hook_opt_kind)FS_OPT_CONV, "algebraic simplification: Conv could be removed" },
101 { (hook_opt_kind)FS_OPT_CAST, "algebraic simplification: a Cast could be removed" },
102 { (hook_opt_kind)FS_OPT_MIN_MAX_EQ, "algebraic simplification: Min(a,a) = Max(a,a) = a" },
103 { (hook_opt_kind)FS_OPT_MUX_COMBINE, "boolean simplification: two Mux nodes where combined into one" },
104 { (hook_opt_kind)FS_OPT_MUX_CONV, "boolean simplification: MuxI(sel, 1, 0) = (I)sel" },
105 { (hook_opt_kind)FS_OPT_MUX_BOOL, "boolean simplification: Muxb(sel, true, false) = sel" },
106 { (hook_opt_kind)FS_OPT_MUX_NOT_BOOL, "boolean simplification: Muxb(sel, false, true) = Not(sel)" },
107 { (hook_opt_kind)FS_OPT_MUX_OR_BOOL, "boolean simplification: Muxb(sel, true, x) = Or(sel, x)" },
108 { (hook_opt_kind)FS_OPT_MUX_ORNOT_BOOL, "boolean simplification: Muxb(sel, x, true) = Or(Not(sel), x)" },
109 { (hook_opt_kind)FS_OPT_MUX_AND_BOOL, "boolean simplification: Muxb(sel, x, false) = And(sel, x)" },
110 { (hook_opt_kind)FS_OPT_MUX_ANDNOT_BOOL,"boolean simplification: Muxb(sel, false, x) = And(Not(sel), x)" },
111 { (hook_opt_kind)FS_OPT_MUX_C, "algebraic simplification: Mux(C, f, t) = C ? t : f" },
112 { (hook_opt_kind)FS_OPT_MUX_EQ, "algebraic simplification: Mux(v, x, x) = x" },
113 { (hook_opt_kind)FS_OPT_MUX_TRANSFORM, "algebraic simplification: Mux(t ==/!= f, t, f) = f/t, Mux(t ==/!= 0, -t, t) = -t/t" },
114 { (hook_opt_kind)FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
115 { (hook_opt_kind)FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
116 { (hook_opt_kind)FS_OPT_MUX_TO_BITOP, "algebraic simplification: Mux((a & 2^x) ==/!= 0, 2^x, 0) = (a & 2^x) (xor 2^x)" },
117 { (hook_opt_kind)FS_OPT_IDEM_UNARY, "algebraic simplification: Idempotent unary operation" },
118 { (hook_opt_kind)FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
119 { (hook_opt_kind)FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
120 { (hook_opt_kind)FS_OPT_NOT_PLUS_1, "algebraic simplification: ~x + 1 = -x" },
121 { (hook_opt_kind)FS_OPT_ADD_X_NOT_X, "algebraic simplification: ~x + x = -1" },
122 { (hook_opt_kind)FS_OPT_FP_INV_MUL, "algebraic simplification: x / y = x * (1.0/y)" },
123 { (hook_opt_kind)FS_OPT_CONST_PHI, "constant evaluation on Phi node" },
124 { (hook_opt_kind)FS_OPT_PREDICATE, "predicate optimization" },
125 { (hook_opt_kind)FS_OPT_DEMORGAN, "optimization using DeMorgan's law" },
126 { (hook_opt_kind)FS_OPT_CMP_OP_OP, "CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y)" },
127 { (hook_opt_kind)FS_OPT_CMP_OP_C, "CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2)" },
128 { (hook_opt_kind)FS_OPT_CMP_CONV_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y)" },
129 { (hook_opt_kind)FS_OPT_CMP_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y)" },
130 { (hook_opt_kind)FS_OPT_CMP_TO_BOOL, "CMP optimization: Cmp(x, y) = BoolOP(x, y)" },
131 { (hook_opt_kind)FS_OPT_CMP_CNST_MAGN, "CMP optimization: reduced magnitude of a const" },
132 { (hook_opt_kind)FS_OPT_CMP_SHF_TO_AND, "CMP optimization: transformed shift into And" },
133 { (hook_opt_kind)FS_OPT_CMP_MOD_TO_AND, "CMP optimization: transformed Mod into And" },
134 { (hook_opt_kind)FS_OPT_NOP, "the operation is a NOP" },
135 { (hook_opt_kind)FS_OPT_GVN_FOLLOWER, "GVN-PRE: replaced a follower" },
136 { (hook_opt_kind)FS_OPT_GVN_FULLY, "GVN-PRE: replaced by fully redundant value" },
137 { (hook_opt_kind)FS_OPT_GVN_PARTLY, "GVN-PRE: replaced by partly redundant value" },
138 { (hook_opt_kind)FS_OPT_COMBO_CONST, "Combo: evaluated into Constant" },
139 { (hook_opt_kind)FS_OPT_COMBO_CF, "Combo: removed conditional control flow" },
140 { (hook_opt_kind)FS_OPT_COMBO_FOLLOWER, "Combo: removed a follower" },
141 { (hook_opt_kind)FS_OPT_COMBO_CONGRUENT,"Combo: replaced by congruent" },
142 { (hook_opt_kind)FS_OPT_JUMPTHREADING, "Jump threading: removed conditional control flow" },
143 { (hook_opt_kind)FS_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
144 { (hook_opt_kind)FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
145 { (hook_opt_kind)FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
146 { (hook_opt_kind)FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
147 { (hook_opt_kind)FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
148 { (hook_opt_kind)FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
149 { (hook_opt_kind)FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
150 { (hook_opt_kind)FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
151 { (hook_opt_kind)FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
152 { (hook_opt_kind)FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
153 { (hook_opt_kind)FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
154 { (hook_opt_kind)FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
155 { (hook_opt_kind)FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
156 { (hook_opt_kind)FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
157 { (hook_opt_kind)FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
158 { (hook_opt_kind)FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
159 { (hook_opt_kind)FS_OPT_RTS_SYMMETRIC, "RTS optimization: call to symmetric function f(-x) replaced by f(x)" },
160 { (hook_opt_kind)FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
161 { (hook_opt_kind)FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
162 { (hook_opt_kind)FS_OPT_RTS_STRCPY, "RTS optimization: call to strcpy() replaced" },
163 { (hook_opt_kind)FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
164 { (hook_opt_kind)FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
165 { (hook_opt_kind)FS_OPT_RTS_MEMPCPY, "RTS optimization: call to mempcpy() replaced" },
166 { (hook_opt_kind)FS_OPT_RTS_MEMMOVE, "RTS optimization: call to memmove() replaced" },
167 { (hook_opt_kind)FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
168 { (hook_opt_kind)FS_OPT_RTS_MEMCMP, "RTS optimization: call to memcmp() replaced" },
169 { (hook_opt_kind)FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
170 { (hook_opt_kind)FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
171 { (hook_opt_kind)FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
172 { (hook_opt_kind)FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
173 { (hook_opt_kind)FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
174 { (hook_opt_kind)FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
175 { (hook_opt_kind)FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
176 { (hook_opt_kind)FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
177 { (hook_opt_kind)FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
178 { (hook_opt_kind)FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
179 { (hook_opt_kind)FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
182 static const char *if_conv_names[IF_RESULT_LAST] = {
184 "if conv side effect ",
185 "if conv Phi node found ",
186 "if conv to deep DAG's ",
187 "if conv bad control flow ",
188 "if conv denied by arch ",
192 * dumps a opcode hash into human readable form
194 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
198 counter_t f_new_node;
200 counter_t f_normlized;
203 cnt_clr(&f_new_node);
205 cnt_clr(&f_normlized);
207 fprintf(dmp->f, "%-16s %-8s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id", "normalized");
208 foreach_pset(set, node_entry_t*, entry) {
209 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n",
210 get_id_str(entry->op->name),
211 cnt_to_uint(&entry->cnt_alive),
212 cnt_to_uint(&entry->new_node),
213 cnt_to_uint(&entry->into_Id),
214 cnt_to_uint(&entry->normalized)
217 cnt_add(&f_alive, &entry->cnt_alive);
218 cnt_add(&f_new_node, &entry->new_node);
219 cnt_add(&f_Id, &entry->into_Id);
220 cnt_add(&f_normlized, &entry->normalized);
222 fprintf(dmp->f, "-------------------------------------------\n");
223 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n", "Sum",
224 cnt_to_uint(&f_alive),
225 cnt_to_uint(&f_new_node),
227 cnt_to_uint(&f_normlized)
229 } /* simple_dump_opcode_hash */
232 * Return the name of an optimization.
234 static const char *get_opt_name(int index)
236 assert(index < (int) ARRAY_SIZE(opt_names) && "index out of range");
237 assert((int) opt_names[index].kind == index && "opt_names broken");
238 return opt_names[index].name;
242 * dumps an optimization hash into human readable form
244 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
246 if (pset_count(set) > 0) {
248 const char *name = get_opt_name(index);
250 fprintf(dmp->f, "\n%s:\n", name);
251 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
253 foreach_pset(set, opt_entry_t*, entry) {
254 fprintf(dmp->f, "%-16s %8u\n",
255 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
258 } /* simple_dump_opt_hash */
261 * dumps the register pressure for each block and for each register class
263 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
265 be_block_entry_t *b_entry = (be_block_entry_t*)pset_first(entry->be_block_hash);
266 reg_pressure_entry_t *rp_entry;
268 /* return if no be statistic information available */
272 fprintf(dmp->f, "\nREG PRESSURE:\n");
273 fprintf(dmp->f, "%12s", "Block Nr");
275 /* print table head (register class names) */
276 foreach_pset(b_entry->reg_pressure, reg_pressure_entry_t*, rp_entry)
277 fprintf(dmp->f, "%15s", rp_entry->class_name);
278 fprintf(dmp->f, "\n");
280 /* print the reg pressure for all blocks and register classes */
281 for (/* b_entry is already initialized */ ;
283 b_entry = (be_block_entry_t*)pset_next(entry->be_block_hash)) {
284 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
286 foreach_pset(b_entry->reg_pressure, reg_pressure_entry_t*, rp_entry)
287 fprintf(dmp->f, "%15d", rp_entry->pressure);
288 fprintf(dmp->f, "\n");
290 } /* simple_dump_be_block_reg_pressure */
292 /** prints a distribution entry */
293 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env)
295 dumper_t *dmp = (dumper_t*)env;
296 fprintf(dmp->f, "%12u", cnt_to_uint(&entry->cnt));
297 } /* simple_dump_distrib_entry */
300 * dumps the distribution of the amount of ready nodes for each block
302 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
304 if (pset_count(entry->be_block_hash) > 0) {
305 be_block_entry_t *b_entry;
308 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
309 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
310 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
312 foreach_pset(entry->be_block_hash, be_block_entry_t*, b_entry) {
313 /* this ensures that all keys from 1 to 5 are in the table */
314 for (i = 1; i < 6; ++i)
315 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
317 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
318 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
319 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
320 fprintf(dmp->f, "\n");
323 } /* simple_dump_be_block_sched_ready */
326 * Adds the counter for given entry to another distribution table.
328 static void add_distrib_entry(const distrib_entry_t *entry, void *env)
330 distrib_tbl_t *sum_tbl = (distrib_tbl_t*)env;
332 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
333 } /* add_distrib_entry */
336 * dumps permutation statistics for one and block and one class
338 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
340 perm_stat_entry_t *ps_ent;
341 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
342 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
346 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
355 foreach_pset(entry->perm_stat, perm_stat_entry_t*, ps_ent) {
356 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
359 stat_get_count_distrib_tbl(ps_ent->chains),
360 stat_get_count_distrib_tbl(ps_ent->cycles),
365 /* sum up distribution table for chains */
366 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
368 /* sum up distribution table for cycles */
369 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
372 /* print chain distribution for all perms of this class in this block */
373 fprintf(dmp->f, "chain distribution:\n");
375 /* add all missing entries to chain distribution table */
376 for (i = 1; i <= entry->n_regs; i++) {
377 snprintf(buf, sizeof(buf), "length %d", i);
378 fprintf(dmp->f, "%12s", buf);
379 stat_insert_int_distrib_tbl(sum_chains, i);
381 fprintf(dmp->f, "\n");
382 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
383 fprintf(dmp->f, "\n");
385 /* print cycle distribution for all perms of this class in this block */
386 fprintf(dmp->f, "cycle distribution:\n");
388 /* add all missing entries to cycle distribution table */
389 for (i = 1; i <= entry->n_regs; i++) {
390 snprintf(buf, sizeof(buf), "length %d", i);
391 fprintf(dmp->f, "%12s", buf);
392 stat_insert_int_distrib_tbl(sum_cycles, i);
394 fprintf(dmp->f, "\n");
395 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
396 fprintf(dmp->f, "\n");
398 /* delete temporary sum distribution tables */
399 stat_delete_distrib_tbl(sum_chains);
400 stat_delete_distrib_tbl(sum_cycles);
402 } /* simple_dump_be_block_permstat_class */
405 * dumps statistics about perms
407 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
409 if (pset_count(entry->be_block_hash) > 0) {
410 be_block_entry_t *b_entry;
412 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
413 foreach_pset(entry->be_block_hash, be_block_entry_t*, b_entry) {
414 perm_class_entry_t *pc_ent;
416 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
418 if (b_entry->perm_class_stat) {
419 foreach_pset(b_entry->perm_class_stat, perm_class_entry_t*, pc_ent) {
420 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
421 simple_dump_be_block_permstat_class(dmp, pc_ent);
426 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
428 } /* simple_dump_be_block_permstat */
431 * dumps the number of real_function_call optimization
433 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
438 if (! cnt_eq(cnt, 0)) {
439 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
440 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
442 } /* simple_dump_real_func_calls */
445 * dumps the number of tail_recursion optimization
447 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
452 if (num_tail_recursion > 0) {
453 fprintf(dmp->f, "\nTail recursion optimized:\n");
454 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
456 } /* simple_dump_tail_recursion */
459 * dumps the edges count
461 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
466 fprintf(dmp->f, "%-16s %8u\n", "Edges", cnt_to_uint(cnt));
467 } /* simple_dump_edges */
472 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
474 int i, dump_opts = 1;
475 block_entry_t *b_entry;
476 extbb_entry_t *eb_entry;
482 ir_graph *const_irg = get_const_code_irg();
484 if (entry->irg == const_irg)
485 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
488 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
490 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
493 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
494 " was inlined : %u\n"
495 " got inlined : %u\n"
496 " strength red : %u\n"
497 " leaf function : %s\n"
498 " calls only leaf functions : %s\n"
503 " indirect calls : %u\n"
504 " external calls : %u\n",
505 entry->is_deleted ? "DELETED " : "",
506 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
507 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
508 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
509 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
510 entry->is_leaf ? "YES" : "NO",
511 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
512 entry->is_recursive ? "YES" : "NO",
513 entry->is_chain_call ? "YES" : "NO",
514 entry->is_strict ? "YES" : "NO",
515 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
516 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
517 cnt_to_uint(&entry->cnt[gcnt_external_calls])
520 for (i = 0; i < IF_RESULT_LAST; ++i) {
521 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
524 fprintf(dmp->f, "\nGlobals counts:\n");
525 fprintf(dmp->f, "--------------\n");
531 " pure address calc ops : %u\n"
532 " all address calc ops : %u\n",
533 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
534 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
537 /* Load/Store address classification */
539 " global Ld/St address : %u\n"
540 " local Ld/St address : %u\n"
541 " this Ld/St address : %u\n"
542 " param Ld/St address : %u\n"
543 " other Ld/St address : %u\n",
544 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
545 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
546 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
547 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
548 cnt_to_uint(&entry->cnt[gcnt_other_adr])
551 simple_dump_opcode_hash(dmp, entry->opcode_hash);
552 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
554 /* effects of optimizations */
558 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
559 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
561 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
562 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
565 /* dump block info */
566 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
567 foreach_pset(entry->block_hash, block_entry_t*, b_entry) {
568 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
570 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
571 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
572 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
573 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
574 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
575 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
576 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
580 /* dump block reg pressure */
581 simple_dump_be_block_reg_pressure(dmp, entry);
583 /* dump block ready nodes distribution */
584 simple_dump_be_block_sched_ready(dmp, entry);
586 /* dump block permutation statistics */
587 simple_dump_be_block_permstat(dmp, entry);
589 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
590 /* dump extended block info */
591 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
592 foreach_pset(entry->extbb_hash, extbb_entry_t*, eb_entry) {
593 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
595 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
596 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
597 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
598 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
599 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
600 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
605 } /* simple_dump_graph */
608 * dumps the constant table
610 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
620 fprintf(dmp->f, "\nConstant Information:\n");
621 fprintf(dmp->f, "---------------------\n");
623 fprintf(dmp->f, "\nBit usage for integer constants\n");
624 fprintf(dmp->f, "-------------------------------\n");
626 for (i = 0; i < ARRAY_SIZE(tbl->int_bits_count); ++i) {
627 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
628 cnt_add(&sum, &tbl->int_bits_count[i]);
630 fprintf(dmp->f, "-------------------------------\n");
632 fprintf(dmp->f, "\nFloating point constants classification\n");
633 fprintf(dmp->f, "--------------------------------------\n");
634 for (i = 0; i < ARRAY_SIZE(tbl->floats); ++i) {
635 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name((float_classify_t)i), cnt_to_uint(&tbl->floats[i]));
636 cnt_add(&sum, &tbl->floats[i]);
638 fprintf(dmp->f, "--------------------------------------\n");
640 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
641 cnt_add(&sum, &tbl->others);
642 fprintf(dmp->f, "-------------------------------\n");
644 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
645 } /* simple_dump_const_tbl */
648 * Dumps a line of the parameter table
650 static void dump_tbl_line(const distrib_entry_t *entry, void *env)
652 dumper_t *dmp = (dumper_t*)env;
654 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
655 } /* dump_tbl_line */
658 * dumps the parameter distribution table
660 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global)
662 fprintf(dmp->f, "\nCall parameter Information:\n");
663 fprintf(dmp->f, "---------------------\n");
665 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
666 fprintf(dmp->f, "-------------------------------\n");
668 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
669 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
670 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
671 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
672 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
673 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
674 } /* simple_dump_param_tbl */
677 * dumps the optimization counter table
679 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len)
683 fprintf(dmp->f, "\nOptimization counts:\n");
684 fprintf(dmp->f, "---------------------\n");
686 for (i = 0; i < len; ++i) {
687 unsigned cnt = cnt_to_uint(&tbl[i]);
690 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
693 } /* simple_dump_opt_cnt */
696 * initialize the simple dumper
698 static void simple_init(dumper_t *dmp, const char *name)
702 snprintf(fname, sizeof(fname), "%s.txt", name);
703 dmp->f = fopen(fname, "w");
710 * finishes the simple dumper
712 static void simple_finish(dumper_t *dmp)
717 } /* simple_finish */
720 * the simple human readable dumper
722 const dumper_t simple_dumper = {
724 simple_dump_const_tbl,
725 simple_dump_param_tbl,
733 FOURCC('S', 'M', 'P', 'L'),
736 /* ---------------------------------------------------------------------- */
739 * count the nodes as needed:
741 * 1 normal (data) Phi's
746 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
751 for (i = 0; i < 4; ++i)
754 foreach_pset(graph->opcode_hash, node_entry_t*, entry) {
755 if (entry->op == op_Phi) {
757 cnt_add(&cnt[1], &entry->cnt_alive);
758 } else if (entry->op == dmp->status->op_PhiM) {
760 cnt_add(&cnt[2], &entry->cnt_alive);
761 } else if (entry->op == op_Proj) {
763 cnt_add(&cnt[3], &entry->cnt_alive);
765 /* all other nodes */
766 cnt_add(&cnt[0], &entry->cnt_alive);
769 } /* csv_count_nodes */
774 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
782 if (entry->irg && !entry->is_deleted) {
783 ir_graph *const_irg = get_const_code_irg();
785 if (entry->irg == const_irg) {
786 name = "<Const code Irg>";
790 name = get_entity_name(entry->ent);
792 name = "<UNKNOWN IRG>";
795 csv_count_nodes(dmp, entry, cnt);
797 fprintf(dmp->f, "%-40s, %p, %u, %u, %u, %u\n",
800 cnt_to_uint(&cnt[0]),
801 cnt_to_uint(&cnt[1]),
802 cnt_to_uint(&cnt[2]),
806 } /* csv_dump_graph */
811 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
816 } /* csv_dump_const_tbl */
819 * dumps the parameter distribution table
821 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global)
827 } /* csv_dump_param_tbl */
830 * dumps the optimization counter
832 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len)
838 } /* csv_dump_opt_cnt */
841 * initialize the simple dumper
843 static void csv_init(dumper_t *dmp, const char *name)
847 snprintf(fname, sizeof(fname), "%s.csv", name);
848 dmp->f = fopen(fname, "a");
854 * finishes the simple dumper
856 static void csv_finish(dumper_t *dmp)
864 * the simple human readable dumper
866 const dumper_t csv_dumper = {
877 FOURCC('C', 'S', 'V', '\0')