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_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)
197 counter_t f_new_node;
199 counter_t f_normlized;
202 cnt_clr(&f_new_node);
204 cnt_clr(&f_normlized);
206 fprintf(dmp->f, "%-16s %-8s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id", "normalized");
207 foreach_pset(set, node_entry_t, entry) {
208 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n",
209 get_id_str(entry->op->name),
210 cnt_to_uint(&entry->cnt_alive),
211 cnt_to_uint(&entry->new_node),
212 cnt_to_uint(&entry->into_Id),
213 cnt_to_uint(&entry->normalized)
216 cnt_add(&f_alive, &entry->cnt_alive);
217 cnt_add(&f_new_node, &entry->new_node);
218 cnt_add(&f_Id, &entry->into_Id);
219 cnt_add(&f_normlized, &entry->normalized);
221 fprintf(dmp->f, "-------------------------------------------\n");
222 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n", "Sum",
223 cnt_to_uint(&f_alive),
224 cnt_to_uint(&f_new_node),
226 cnt_to_uint(&f_normlized)
228 } /* simple_dump_opcode_hash */
231 * Return the name of an optimization.
233 static const char *get_opt_name(int index)
235 assert(index < (int) ARRAY_SIZE(opt_names) && "index out of range");
236 assert((int) opt_names[index].kind == index && "opt_names broken");
237 return opt_names[index].name;
241 * dumps an optimization hash into human readable form
243 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
245 if (pset_count(set) > 0) {
246 const char *name = get_opt_name(index);
248 fprintf(dmp->f, "\n%s:\n", name);
249 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
251 foreach_pset(set, opt_entry_t, entry) {
252 fprintf(dmp->f, "%-16s %8u\n",
253 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
256 } /* simple_dump_opt_hash */
259 * dumps the register pressure for each block and for each register class
261 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
263 /* return if no be statistic information available */
264 be_block_entry_t *const b_first = pset_first(be_block_entry_t, entry->be_block_hash);
268 fprintf(dmp->f, "\nREG PRESSURE:\n");
269 fprintf(dmp->f, "%12s", "Block Nr");
271 /* print table head (register class names) */
272 foreach_pset(b_first->reg_pressure, reg_pressure_entry_t, rp_entry)
273 fprintf(dmp->f, "%15s", rp_entry->class_name);
274 fprintf(dmp->f, "\n");
276 /* print the reg pressure for all blocks and register classes */
277 foreach_pset(entry->block_hash, be_block_entry_t, b_entry) {
278 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
280 foreach_pset(b_entry->reg_pressure, reg_pressure_entry_t, rp_entry)
281 fprintf(dmp->f, "%15d", rp_entry->pressure);
282 fprintf(dmp->f, "\n");
284 } /* simple_dump_be_block_reg_pressure */
286 /** prints a distribution entry */
287 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env)
289 dumper_t *dmp = (dumper_t*)env;
290 fprintf(dmp->f, "%12u", cnt_to_uint(&entry->cnt));
291 } /* simple_dump_distrib_entry */
294 * dumps the distribution of the amount of ready nodes for each block
296 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
298 if (pset_count(entry->be_block_hash) > 0) {
301 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
302 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
303 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
305 foreach_pset(entry->be_block_hash, be_block_entry_t, b_entry) {
306 /* this ensures that all keys from 1 to 5 are in the table */
307 for (i = 1; i < 6; ++i)
308 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
310 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
311 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
312 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
313 fprintf(dmp->f, "\n");
316 } /* simple_dump_be_block_sched_ready */
319 * Adds the counter for given entry to another distribution table.
321 static void add_distrib_entry(const distrib_entry_t *entry, void *env)
323 distrib_tbl_t *sum_tbl = (distrib_tbl_t*)env;
325 stat_add_int_distrib_tbl(sum_tbl, (int)PTR_TO_INT(entry->object), &entry->cnt);
326 } /* add_distrib_entry */
329 * dumps permutation statistics for one and block and one class
331 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
333 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
334 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
338 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
347 foreach_pset(entry->perm_stat, perm_stat_entry_t, ps_ent) {
348 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
351 stat_get_count_distrib_tbl(ps_ent->chains),
352 stat_get_count_distrib_tbl(ps_ent->cycles),
357 /* sum up distribution table for chains */
358 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
360 /* sum up distribution table for cycles */
361 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
364 /* print chain distribution for all perms of this class in this block */
365 fprintf(dmp->f, "chain distribution:\n");
367 /* add all missing entries to chain distribution table */
368 for (i = 1; i <= entry->n_regs; i++) {
369 snprintf(buf, sizeof(buf), "length %d", i);
370 fprintf(dmp->f, "%12s", buf);
371 stat_insert_int_distrib_tbl(sum_chains, i);
373 fprintf(dmp->f, "\n");
374 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
375 fprintf(dmp->f, "\n");
377 /* print cycle distribution for all perms of this class in this block */
378 fprintf(dmp->f, "cycle distribution:\n");
380 /* add all missing entries to cycle distribution table */
381 for (i = 1; i <= entry->n_regs; i++) {
382 snprintf(buf, sizeof(buf), "length %d", i);
383 fprintf(dmp->f, "%12s", buf);
384 stat_insert_int_distrib_tbl(sum_cycles, i);
386 fprintf(dmp->f, "\n");
387 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
388 fprintf(dmp->f, "\n");
390 /* delete temporary sum distribution tables */
391 stat_delete_distrib_tbl(sum_chains);
392 stat_delete_distrib_tbl(sum_cycles);
394 } /* simple_dump_be_block_permstat_class */
397 * dumps statistics about perms
399 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
401 if (pset_count(entry->be_block_hash) > 0) {
402 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
403 foreach_pset(entry->be_block_hash, be_block_entry_t, b_entry) {
404 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
406 if (b_entry->perm_class_stat) {
407 foreach_pset(b_entry->perm_class_stat, perm_class_entry_t, pc_ent) {
408 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
409 simple_dump_be_block_permstat_class(dmp, pc_ent);
414 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
416 } /* simple_dump_be_block_permstat */
419 * dumps the number of real_function_call optimization
421 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
426 if (! cnt_eq(cnt, 0)) {
427 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
428 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
430 } /* simple_dump_real_func_calls */
433 * dumps the number of tail_recursion optimization
435 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
440 if (num_tail_recursion > 0) {
441 fprintf(dmp->f, "\nTail recursion optimized:\n");
442 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
444 } /* simple_dump_tail_recursion */
447 * dumps the edges count
449 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
454 fprintf(dmp->f, "%-16s %8u\n", "Edges", cnt_to_uint(cnt));
455 } /* simple_dump_edges */
460 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
468 ir_graph *const_irg = get_const_code_irg();
471 if (entry->irg == const_irg)
472 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
475 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
477 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
480 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
481 " was inlined : %u\n"
482 " got inlined : %u\n"
483 " strength red : %u\n"
484 " leaf function : %s\n"
485 " calls only leaf functions : %s\n"
490 " indirect calls : %u\n"
491 " external calls : %u\n",
492 entry->is_deleted ? "DELETED " : "",
493 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
494 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
495 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
496 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
497 entry->is_leaf ? "YES" : "NO",
498 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
499 entry->is_recursive ? "YES" : "NO",
500 entry->is_chain_call ? "YES" : "NO",
501 entry->is_strict ? "YES" : "NO",
502 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
503 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
504 cnt_to_uint(&entry->cnt[gcnt_external_calls])
507 for (i = 0; i < IF_RESULT_LAST; ++i) {
508 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
511 fprintf(dmp->f, "\nGlobals counts:\n");
512 fprintf(dmp->f, "--------------\n");
518 " pure address calc ops : %u\n"
519 " all address calc ops : %u\n",
520 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
521 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
524 /* Load/Store address classification */
526 " global Ld/St address : %u\n"
527 " local Ld/St address : %u\n"
528 " this Ld/St address : %u\n"
529 " param Ld/St address : %u\n"
530 " other Ld/St address : %u\n",
531 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
532 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
533 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
534 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
535 cnt_to_uint(&entry->cnt[gcnt_other_adr])
538 simple_dump_opcode_hash(dmp, entry->opcode_hash);
539 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
541 /* effects of optimizations */
545 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
546 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
548 for (i = 0; i != ARRAY_SIZE(entry->opt_hash); ++i) {
549 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
552 /* dump block info */
553 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
554 foreach_pset(entry->block_hash, block_entry_t, b_entry) {
555 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
557 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
558 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
559 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
560 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
561 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
562 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
563 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
567 /* dump block reg pressure */
568 simple_dump_be_block_reg_pressure(dmp, entry);
570 /* dump block ready nodes distribution */
571 simple_dump_be_block_sched_ready(dmp, entry);
573 /* dump block permutation statistics */
574 simple_dump_be_block_permstat(dmp, entry);
576 } /* simple_dump_graph */
579 * dumps the constant table
581 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
591 fprintf(dmp->f, "\nConstant Information:\n");
592 fprintf(dmp->f, "---------------------\n");
594 fprintf(dmp->f, "\nBit usage for integer constants\n");
595 fprintf(dmp->f, "-------------------------------\n");
597 for (i = 0; i < ARRAY_SIZE(tbl->int_bits_count); ++i) {
598 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
599 cnt_add(&sum, &tbl->int_bits_count[i]);
601 fprintf(dmp->f, "-------------------------------\n");
603 fprintf(dmp->f, "\nFloating point constants classification\n");
604 fprintf(dmp->f, "--------------------------------------\n");
605 for (i = 0; i < ARRAY_SIZE(tbl->floats); ++i) {
606 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name((float_classify_t)i), cnt_to_uint(&tbl->floats[i]));
607 cnt_add(&sum, &tbl->floats[i]);
609 fprintf(dmp->f, "--------------------------------------\n");
611 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
612 cnt_add(&sum, &tbl->others);
613 fprintf(dmp->f, "-------------------------------\n");
615 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
616 } /* simple_dump_const_tbl */
619 * Dumps a line of the parameter table
621 static void dump_tbl_line(const distrib_entry_t *entry, void *env)
623 dumper_t *dmp = (dumper_t*)env;
625 fprintf(dmp->f, "%ld : %u\n", (long int)PTR_TO_INT(entry->object),
626 cnt_to_uint(&entry->cnt));
627 } /* dump_tbl_line */
630 * dumps the parameter distribution table
632 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global)
634 fprintf(dmp->f, "\nCall parameter Information:\n");
635 fprintf(dmp->f, "---------------------\n");
637 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
638 fprintf(dmp->f, "-------------------------------\n");
640 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
641 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
642 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
643 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
644 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
645 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
646 } /* simple_dump_param_tbl */
649 * dumps the optimization counter table
651 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len)
655 fprintf(dmp->f, "\nOptimization counts:\n");
656 fprintf(dmp->f, "---------------------\n");
658 for (i = 0; i < len; ++i) {
659 unsigned cnt = cnt_to_uint(&tbl[i]);
662 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
665 } /* simple_dump_opt_cnt */
668 * initialize the simple dumper
670 static void simple_init(dumper_t *dmp, const char *name)
674 snprintf(fname, sizeof(fname), "%s.txt", name);
675 dmp->f = fopen(fname, "w");
682 * finishes the simple dumper
684 static void simple_finish(dumper_t *dmp)
689 } /* simple_finish */
692 * the simple human readable dumper
694 const dumper_t simple_dumper = {
696 simple_dump_const_tbl,
697 simple_dump_param_tbl,
705 FOURCC('S', 'M', 'P', 'L'),
708 /* ---------------------------------------------------------------------- */
711 * count the nodes as needed:
713 * 1 normal (data) Phi's
718 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
722 for (i = 0; i < 4; ++i)
725 foreach_pset(graph->opcode_hash, node_entry_t, entry) {
726 if (entry->op == op_Phi) {
728 cnt_add(&cnt[1], &entry->cnt_alive);
729 } else if (entry->op == dmp->status->op_PhiM) {
731 cnt_add(&cnt[2], &entry->cnt_alive);
732 } else if (entry->op == op_Proj) {
734 cnt_add(&cnt[3], &entry->cnt_alive);
736 /* all other nodes */
737 cnt_add(&cnt[0], &entry->cnt_alive);
740 } /* csv_count_nodes */
745 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
753 if (entry->irg && !entry->is_deleted) {
754 ir_graph *const_irg = get_const_code_irg();
756 if (entry->irg == const_irg) {
757 name = "<Const code Irg>";
761 name = get_entity_name(entry->ent);
763 name = "<UNKNOWN IRG>";
766 csv_count_nodes(dmp, entry, cnt);
768 fprintf(dmp->f, "%-40s, %p, %u, %u, %u, %u\n",
771 cnt_to_uint(&cnt[0]),
772 cnt_to_uint(&cnt[1]),
773 cnt_to_uint(&cnt[2]),
777 } /* csv_dump_graph */
782 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
787 } /* csv_dump_const_tbl */
790 * dumps the parameter distribution table
792 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global)
798 } /* csv_dump_param_tbl */
801 * dumps the optimization counter
803 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len)
809 } /* csv_dump_opt_cnt */
812 * initialize the simple dumper
814 static void csv_init(dumper_t *dmp, const char *name)
818 snprintf(fname, sizeof(fname), "%s.csv", name);
819 dmp->f = fopen(fname, "a");
825 * finishes the simple dumper
827 static void csv_finish(dumper_t *dmp)
835 * the simple human readable dumper
837 const dumper_t csv_dumper = {
848 FOURCC('C', 'S', 'V', '\0')