2 * Copyright (C) 1995-2011 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_MIN_MAX_EQ, "algebraic simplification: Min(a,a) = Max(a,a) = a" },
102 { (hook_opt_kind)FS_OPT_MUX_COMBINE, "boolean simplification: two Mux nodes where combined into one" },
103 { (hook_opt_kind)FS_OPT_MUX_CONV, "boolean simplification: MuxI(sel, 1, 0) = (I)sel" },
104 { (hook_opt_kind)FS_OPT_MUX_BOOL, "boolean simplification: Muxb(sel, true, false) = sel" },
105 { (hook_opt_kind)FS_OPT_MUX_NOT_BOOL, "boolean simplification: Muxb(sel, false, true) = Not(sel)" },
106 { (hook_opt_kind)FS_OPT_MUX_OR_BOOL, "boolean simplification: Muxb(sel, true, x) = Or(sel, x)" },
107 { (hook_opt_kind)FS_OPT_MUX_ORNOT_BOOL, "boolean simplification: Muxb(sel, x, true) = Or(Not(sel), x)" },
108 { (hook_opt_kind)FS_OPT_MUX_AND_BOOL, "boolean simplification: Muxb(sel, x, false) = And(sel, x)" },
109 { (hook_opt_kind)FS_OPT_MUX_ANDNOT_BOOL,"boolean simplification: Muxb(sel, false, x) = And(Not(sel), x)" },
110 { (hook_opt_kind)FS_OPT_MUX_C, "algebraic simplification: Mux(C, f, t) = C ? t : f" },
111 { (hook_opt_kind)FS_OPT_MUX_EQ, "algebraic simplification: Mux(v, x, x) = x" },
112 { (hook_opt_kind)FS_OPT_MUX_TRANSFORM, "algebraic simplification: Mux(t ==/!= f, t, f) = f/t, Mux(t ==/!= 0, -t, t) = -t/t" },
113 { (hook_opt_kind)FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
114 { (hook_opt_kind)FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
115 { (hook_opt_kind)FS_OPT_MUX_TO_BITOP, "algebraic simplification: Mux((a & 2^x) ==/!= 0, 2^x, 0) = (a & 2^x) (xor 2^x)" },
116 { (hook_opt_kind)FS_OPT_INVOLUTION, "algebraic simplification: OP(OP(x)) = x" },
117 { (hook_opt_kind)FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
118 { (hook_opt_kind)FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
119 { (hook_opt_kind)FS_OPT_NOT_PLUS_1, "algebraic simplification: ~x + 1 = -x" },
120 { (hook_opt_kind)FS_OPT_ADD_X_NOT_X, "algebraic simplification: ~x + x = -1" },
121 { (hook_opt_kind)FS_OPT_FP_INV_MUL, "algebraic simplification: x / y = x * (1.0/y)" },
122 { (hook_opt_kind)FS_OPT_CONST_PHI, "constant evaluation on Phi node" },
123 { (hook_opt_kind)FS_OPT_PREDICATE, "predicate optimization" },
124 { (hook_opt_kind)FS_OPT_DEMORGAN, "optimization using DeMorgan's law" },
125 { (hook_opt_kind)FS_OPT_CMP_OP_OP, "CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y)" },
126 { (hook_opt_kind)FS_OPT_CMP_OP_C, "CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2)" },
127 { (hook_opt_kind)FS_OPT_CMP_CONV_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y)" },
128 { (hook_opt_kind)FS_OPT_CMP_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y)" },
129 { (hook_opt_kind)FS_OPT_CMP_TO_BOOL, "CMP optimization: Cmp(x, y) = BoolOP(x, y)" },
130 { (hook_opt_kind)FS_OPT_CMP_CNST_MAGN, "CMP optimization: reduced magnitude of a const" },
131 { (hook_opt_kind)FS_OPT_CMP_SHF_TO_AND, "CMP optimization: transformed shift into And" },
132 { (hook_opt_kind)FS_OPT_CMP_MOD_TO_AND, "CMP optimization: transformed Mod into And" },
133 { (hook_opt_kind)FS_OPT_NOP, "the operation is a NOP" },
134 { (hook_opt_kind)FS_OPT_GVN_FOLLOWER, "GVN-PRE: replaced a follower" },
135 { (hook_opt_kind)FS_OPT_GVN_FULLY, "GVN-PRE: replaced by fully redundant value" },
136 { (hook_opt_kind)FS_OPT_GVN_PARTLY, "GVN-PRE: replaced by partly redundant value" },
137 { (hook_opt_kind)FS_OPT_COMBO_CONST, "Combo: evaluated into Constant" },
138 { (hook_opt_kind)FS_OPT_COMBO_CF, "Combo: removed conditional control flow" },
139 { (hook_opt_kind)FS_OPT_COMBO_FOLLOWER, "Combo: removed a follower" },
140 { (hook_opt_kind)FS_OPT_COMBO_CONGRUENT,"Combo: replaced by congruent" },
141 { (hook_opt_kind)FS_OPT_JUMPTHREADING, "Jump threading: removed conditional control flow" },
142 { (hook_opt_kind)FS_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
143 { (hook_opt_kind)FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
144 { (hook_opt_kind)FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
145 { (hook_opt_kind)FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
146 { (hook_opt_kind)FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
147 { (hook_opt_kind)FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
148 { (hook_opt_kind)FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
149 { (hook_opt_kind)FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
150 { (hook_opt_kind)FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
151 { (hook_opt_kind)FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
152 { (hook_opt_kind)FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
153 { (hook_opt_kind)FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
154 { (hook_opt_kind)FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
155 { (hook_opt_kind)FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
156 { (hook_opt_kind)FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
157 { (hook_opt_kind)FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
158 { (hook_opt_kind)FS_OPT_RTS_SYMMETRIC, "RTS optimization: call to symmetric function f(-x) replaced by f(x)" },
159 { (hook_opt_kind)FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
160 { (hook_opt_kind)FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
161 { (hook_opt_kind)FS_OPT_RTS_STRCPY, "RTS optimization: call to strcpy() replaced" },
162 { (hook_opt_kind)FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
163 { (hook_opt_kind)FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
164 { (hook_opt_kind)FS_OPT_RTS_MEMPCPY, "RTS optimization: call to mempcpy() replaced" },
165 { (hook_opt_kind)FS_OPT_RTS_MEMMOVE, "RTS optimization: call to memmove() replaced" },
166 { (hook_opt_kind)FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
167 { (hook_opt_kind)FS_OPT_RTS_MEMCMP, "RTS optimization: call to memcmp() replaced" },
168 { (hook_opt_kind)FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
169 { (hook_opt_kind)FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
170 { (hook_opt_kind)FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
171 { (hook_opt_kind)FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
172 { (hook_opt_kind)FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
173 { (hook_opt_kind)FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
174 { (hook_opt_kind)FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
175 { (hook_opt_kind)FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
176 { (hook_opt_kind)FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
177 { (hook_opt_kind)FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
178 { (hook_opt_kind)FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
181 static const char *if_conv_names[IF_RESULT_LAST] = {
183 "if conv side effect ",
184 "if conv Phi node found ",
185 "if conv to deep DAG's ",
186 "if conv bad control flow ",
187 "if conv denied by arch ",
191 * dumps a opcode hash into human readable form
193 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
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, node_entry_t, 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)
230 * Return the name of an optimization.
232 static const char *get_opt_name(int index)
234 assert(index < (int) ARRAY_SIZE(opt_names) && "index out of range");
235 assert((int) opt_names[index].kind == index && "opt_names broken");
236 return opt_names[index].name;
240 * dumps an optimization hash into human readable form
242 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
244 if (pset_count(set) > 0) {
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, opt_entry_t, entry) {
251 fprintf(dmp->f, "%-16s %8u\n",
252 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
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 /* return if no be statistic information available */
263 be_block_entry_t *const b_first = pset_first(be_block_entry_t, entry->be_block_hash);
267 fprintf(dmp->f, "\nREG PRESSURE:\n");
268 fprintf(dmp->f, "%12s", "Block Nr");
270 /* print table head (register class names) */
271 foreach_pset(b_first->reg_pressure, reg_pressure_entry_t, rp_entry)
272 fprintf(dmp->f, "%15s", rp_entry->class_name);
273 fprintf(dmp->f, "\n");
275 /* print the reg pressure for all blocks and register classes */
276 foreach_pset(entry->block_hash, be_block_entry_t, b_entry) {
277 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
279 foreach_pset(b_entry->reg_pressure, reg_pressure_entry_t, rp_entry)
280 fprintf(dmp->f, "%15d", rp_entry->pressure);
281 fprintf(dmp->f, "\n");
285 /** prints a distribution entry */
286 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env)
288 dumper_t *dmp = (dumper_t*)env;
289 fprintf(dmp->f, "%12u", cnt_to_uint(&entry->cnt));
293 * dumps the distribution of the amount of ready nodes for each block
295 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
297 if (pset_count(entry->be_block_hash) > 0) {
300 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
301 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
302 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
304 foreach_pset(entry->be_block_hash, be_block_entry_t, b_entry) {
305 /* this ensures that all keys from 1 to 5 are in the table */
306 for (i = 1; i < 6; ++i)
307 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
309 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
310 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
311 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
312 fprintf(dmp->f, "\n");
318 * Adds the counter for given entry to another distribution table.
320 static void add_distrib_entry(const distrib_entry_t *entry, void *env)
322 distrib_tbl_t *sum_tbl = (distrib_tbl_t*)env;
324 stat_add_int_distrib_tbl(sum_tbl, (int)PTR_TO_INT(entry->object), &entry->cnt);
328 * dumps permutation statistics for one and block and one class
330 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
332 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
333 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
337 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
346 foreach_pset(entry->perm_stat, perm_stat_entry_t, ps_ent) {
347 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
350 stat_get_count_distrib_tbl(ps_ent->chains),
351 stat_get_count_distrib_tbl(ps_ent->cycles),
356 /* sum up distribution table for chains */
357 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
359 /* sum up distribution table for cycles */
360 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
363 /* print chain distribution for all perms of this class in this block */
364 fprintf(dmp->f, "chain distribution:\n");
366 /* add all missing entries to chain distribution table */
367 for (i = 1; i <= entry->n_regs; i++) {
368 snprintf(buf, sizeof(buf), "length %d", i);
369 fprintf(dmp->f, "%12s", buf);
370 stat_insert_int_distrib_tbl(sum_chains, i);
372 fprintf(dmp->f, "\n");
373 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
374 fprintf(dmp->f, "\n");
376 /* print cycle distribution for all perms of this class in this block */
377 fprintf(dmp->f, "cycle distribution:\n");
379 /* add all missing entries to cycle distribution table */
380 for (i = 1; i <= entry->n_regs; i++) {
381 snprintf(buf, sizeof(buf), "length %d", i);
382 fprintf(dmp->f, "%12s", buf);
383 stat_insert_int_distrib_tbl(sum_cycles, i);
385 fprintf(dmp->f, "\n");
386 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
387 fprintf(dmp->f, "\n");
389 /* delete temporary sum distribution tables */
390 stat_delete_distrib_tbl(sum_chains);
391 stat_delete_distrib_tbl(sum_cycles);
396 * dumps statistics about perms
398 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
400 if (pset_count(entry->be_block_hash) > 0) {
401 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
402 foreach_pset(entry->be_block_hash, be_block_entry_t, b_entry) {
403 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
405 if (b_entry->perm_class_stat) {
406 foreach_pset(b_entry->perm_class_stat, perm_class_entry_t, pc_ent) {
407 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
408 simple_dump_be_block_permstat_class(dmp, pc_ent);
413 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
418 * dumps the number of real_function_call optimization
420 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
425 if (! cnt_eq(cnt, 0)) {
426 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
427 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
432 * dumps the number of tail_recursion optimization
434 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
439 if (num_tail_recursion > 0) {
440 fprintf(dmp->f, "\nTail recursion optimized:\n");
441 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
446 * dumps the edges count
448 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
453 fprintf(dmp->f, "%-16s %8u\n", "Edges", cnt_to_uint(cnt));
459 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
467 ir_graph *const_irg = get_const_code_irg();
470 if (entry->irg == const_irg)
471 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
474 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
476 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
479 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
480 " was inlined : %u\n"
481 " got inlined : %u\n"
482 " strength red : %u\n"
483 " leaf function : %s\n"
484 " calls only leaf functions : %s\n"
489 " indirect calls : %u\n"
490 " external calls : %u\n",
491 entry->is_deleted ? "DELETED " : "",
492 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
493 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
494 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
495 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
496 entry->is_leaf ? "YES" : "NO",
497 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
498 entry->is_recursive ? "YES" : "NO",
499 entry->is_chain_call ? "YES" : "NO",
500 entry->is_strict ? "YES" : "NO",
501 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
502 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
503 cnt_to_uint(&entry->cnt[gcnt_external_calls])
506 for (i = 0; i < IF_RESULT_LAST; ++i) {
507 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
510 fprintf(dmp->f, "\nGlobals counts:\n");
511 fprintf(dmp->f, "--------------\n");
517 " pure address calc ops : %u\n"
518 " all address calc ops : %u\n",
519 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
520 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
523 /* Load/Store address classification */
525 " global Ld/St address : %u\n"
526 " local Ld/St address : %u\n"
527 " this Ld/St address : %u\n"
528 " param Ld/St address : %u\n"
529 " other Ld/St address : %u\n",
530 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
531 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
532 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
533 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
534 cnt_to_uint(&entry->cnt[gcnt_other_adr])
537 simple_dump_opcode_hash(dmp, entry->opcode_hash);
538 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
540 /* effects of optimizations */
544 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
545 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
547 for (i = 0; i != ARRAY_SIZE(entry->opt_hash); ++i) {
548 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
551 /* dump block info */
552 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
553 foreach_pset(entry->block_hash, block_entry_t, b_entry) {
554 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
556 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
557 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
558 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
559 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
560 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
561 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
562 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
566 /* dump block reg pressure */
567 simple_dump_be_block_reg_pressure(dmp, entry);
569 /* dump block ready nodes distribution */
570 simple_dump_be_block_sched_ready(dmp, entry);
572 /* dump block permutation statistics */
573 simple_dump_be_block_permstat(dmp, entry);
578 * dumps the constant table
580 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
590 fprintf(dmp->f, "\nConstant Information:\n");
591 fprintf(dmp->f, "---------------------\n");
593 fprintf(dmp->f, "\nBit usage for integer constants\n");
594 fprintf(dmp->f, "-------------------------------\n");
596 for (i = 0; i < ARRAY_SIZE(tbl->int_bits_count); ++i) {
597 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
598 cnt_add(&sum, &tbl->int_bits_count[i]);
600 fprintf(dmp->f, "-------------------------------\n");
602 fprintf(dmp->f, "\nFloating point constants classification\n");
603 fprintf(dmp->f, "--------------------------------------\n");
604 for (i = 0; i < ARRAY_SIZE(tbl->floats); ++i) {
605 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name((float_classify_t)i), cnt_to_uint(&tbl->floats[i]));
606 cnt_add(&sum, &tbl->floats[i]);
608 fprintf(dmp->f, "--------------------------------------\n");
610 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
611 cnt_add(&sum, &tbl->others);
612 fprintf(dmp->f, "-------------------------------\n");
614 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
618 * Dumps a line of the parameter table
620 static void dump_tbl_line(const distrib_entry_t *entry, void *env)
622 dumper_t *dmp = (dumper_t*)env;
624 fprintf(dmp->f, "%ld : %u\n", (long int)PTR_TO_INT(entry->object),
625 cnt_to_uint(&entry->cnt));
629 * dumps the parameter distribution table
631 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global)
633 fprintf(dmp->f, "\nCall parameter Information:\n");
634 fprintf(dmp->f, "---------------------\n");
636 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
637 fprintf(dmp->f, "-------------------------------\n");
639 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
640 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
641 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
642 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
643 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
644 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
648 * dumps the optimization counter table
650 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len)
654 fprintf(dmp->f, "\nOptimization counts:\n");
655 fprintf(dmp->f, "---------------------\n");
657 for (i = 0; i < len; ++i) {
658 unsigned cnt = cnt_to_uint(&tbl[i]);
661 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
667 * initialize the simple dumper
669 static void simple_init(dumper_t *dmp, const char *name)
673 snprintf(fname, sizeof(fname), "%s.txt", name);
674 dmp->f = fopen(fname, "w");
681 * finishes the simple dumper
683 static void simple_finish(dumper_t *dmp)
691 * the simple human readable dumper
693 const dumper_t simple_dumper = {
695 simple_dump_const_tbl,
696 simple_dump_param_tbl,
704 FOURCC('S', 'M', 'P', 'L'),
707 /* ---------------------------------------------------------------------- */
710 * count the nodes as needed:
712 * 1 normal (data) Phi's
717 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
721 for (i = 0; i < 4; ++i)
724 foreach_pset(graph->opcode_hash, node_entry_t, entry) {
725 if (entry->op == op_Phi) {
727 cnt_add(&cnt[1], &entry->cnt_alive);
728 } else if (entry->op == dmp->status->op_PhiM) {
730 cnt_add(&cnt[2], &entry->cnt_alive);
731 } else if (entry->op == op_Proj) {
733 cnt_add(&cnt[3], &entry->cnt_alive);
735 /* all other nodes */
736 cnt_add(&cnt[0], &entry->cnt_alive);
744 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
752 if (entry->irg && !entry->is_deleted) {
753 ir_graph *const_irg = get_const_code_irg();
755 if (entry->irg == const_irg) {
759 name = get_entity_name(entry->ent);
761 name = "<UNKNOWN IRG>";
764 csv_count_nodes(dmp, entry, cnt);
766 fprintf(dmp->f, "%-40s, %p, %u, %u, %u, %u\n",
769 cnt_to_uint(&cnt[0]),
770 cnt_to_uint(&cnt[1]),
771 cnt_to_uint(&cnt[2]),
780 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
788 * dumps the parameter distribution table
790 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global)
799 * dumps the optimization counter
801 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len)
810 * initialize the simple dumper
812 static void csv_init(dumper_t *dmp, const char *name)
816 snprintf(fname, sizeof(fname), "%s.csv", name);
817 dmp->f = fopen(fname, "a");
823 * finishes the simple dumper
825 static void csv_finish(dumper_t *dmp)
833 * the simple human readable dumper
835 const dumper_t csv_dumper = {
846 FOURCC('C', 'S', 'V', '\0')