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_COMBINE, "boolean simplification: two Mux nodes where combined into one" },
103 { FS_OPT_MUX_CONV, "boolean simplification: MuxI(sel, 1, 0) = (I)sel" },
104 { FS_OPT_MUX_BOOL, "boolean simplification: Muxb(sel, true, false) = sel" },
105 { FS_OPT_MUX_NOT_BOOL, "boolean simplification: Muxb(sel, false, true) = Not(sel)" },
106 { FS_OPT_MUX_OR_BOOL, "boolean simplification: Muxb(sel, true, x) = Or(sel, x)" },
107 { FS_OPT_MUX_ORNOT_BOOL, "boolean simplification: Muxb(sel, x, true) = Or(Not(sel), x)" },
108 { FS_OPT_MUX_AND_BOOL, "boolean simplification: Muxb(sel, x, false) = And(sel, x)" },
109 { FS_OPT_MUX_ANDNOT_BOOL,"boolean simplification: Muxb(sel, false, x) = And(Not(sel), x)" },
110 { FS_OPT_MUX_C, "algebraic simplification: Mux(C, f, t) = C ? t : f" },
111 { FS_OPT_MUX_EQ, "algebraic simplification: Mux(v, x, x) = x" },
112 { FS_OPT_MUX_TRANSFORM, "algebraic simplification: Mux(t ==/!= f, t, f) = f/t, Mux(t ==/!= 0, -t, t) = -t/t" },
113 { FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
114 { FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
115 { FS_OPT_MUX_TO_ABS, "algebraic simplification: Mux(a > 0, a, -a) = Abs(a)" },
116 { FS_OPT_MUX_TO_BITOP, "algebraic simplification: Mux((a & 2^x) ==/!= 0, 2^x, 0) = (a & 2^x) (xor 2^x)" },
117 { FS_OPT_IDEM_UNARY, "algebraic simplification: Idempotent unary operation" },
118 { FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
119 { FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
120 { FS_OPT_NOT_PLUS_1, "algebraic simplification: ~x + 1 = -x" },
121 { FS_OPT_ADD_X_NOT_X, "algebraic simplification: ~x + x = -1" },
122 { FS_OPT_FP_INV_MUL, "algebraic simplification: x / y = x * (1.0/y)" },
123 { FS_OPT_ABS_MINUS_X, "algebraic simplification: Abs(-x) = Abs(x)" },
124 { FS_OPT_CONST_PHI, "constant evaluation on Phi node" },
125 { FS_OPT_PREDICATE, "predicate optimization" },
126 { FS_OPT_DEMORGAN, "optimization using DeMorgan's law" },
127 { FS_OPT_CMP_OP_OP, "CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y)" },
128 { FS_OPT_CMP_OP_C, "CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2)" },
129 { FS_OPT_CMP_CONV_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y)" },
130 { FS_OPT_CMP_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y)" },
131 { FS_OPT_CMP_TO_BOOL, "CMP optimization: Cmp(x, y) = BoolOP(x, y)" },
132 { FS_OPT_CMP_CNST_MAGN, "CMP optimization: reduced magnitude of a const" },
133 { FS_OPT_CMP_SHF_TO_AND, "CMP optimization: transformed shift into And" },
134 { FS_OPT_CMP_MOD_TO_AND, "CMP optimization: transformed Mod into And" },
135 { FS_OPT_NOP, "the operation is a NOP" },
136 { FS_OPT_GVN_FOLLOWER, "GVN-PRE: replaced a follower" },
137 { FS_OPT_GVN_FULLY, "GVN-PRE: replaced by fully redundant value" },
138 { FS_OPT_GVN_PARTLY, "GVN-PRE: replaced by partly redundant value" },
139 { FS_OPT_COMBO_CONST, "Combo: evaluated into Constant" },
140 { FS_OPT_COMBO_CF, "Combo: removed conditional control flow" },
141 { FS_OPT_COMBO_FOLLOWER, "Combo: removed a follower" },
142 { FS_OPT_COMBO_CONGRUENT,"Combo: replaced by congruent" },
143 { FS_OPT_COND_EVAL, "Conditional evaluation: removed conditional control flow" },
144 { FS_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
145 { FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
146 { FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
147 { FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
148 { FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
149 { FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
150 { FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
151 { FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
152 { FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
153 { FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
154 { FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
155 { FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
156 { FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
157 { FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
158 { FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
159 { FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
160 { FS_OPT_RTS_SYMMETRIC, "RTS optimization: call to symmetric function f(-x) replaced by f(x)" },
161 { FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
162 { FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
163 { FS_OPT_RTS_STRCPY, "RTS optimization: call to strcpy() replaced" },
164 { FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
165 { FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
166 { FS_OPT_RTS_MEMPCPY, "RTS optimization: call to mempcpy() replaced" },
167 { FS_OPT_RTS_MEMMOVE, "RTS optimization: call to memmove() replaced" },
168 { FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
169 { FS_OPT_RTS_MEMCMP, "RTS optimization: call to memcmp() replaced" },
170 { FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
171 { FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
172 { FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
173 { FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
174 { FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
175 { FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
176 { FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
177 { FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
178 { FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
179 { FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
180 { FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
183 static const char *if_conv_names[IF_RESULT_LAST] = {
185 "if conv side effect ",
186 "if conv Phi node found ",
187 "if conv to deep DAG's ",
188 "if conv bad control flow ",
189 "if conv denied by arch ",
193 * dumps a opcode hash into human readable form
195 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
199 counter_t f_new_node;
201 counter_t f_normlized;
204 cnt_clr(&f_new_node);
206 cnt_clr(&f_normlized);
208 fprintf(dmp->f, "%-16s %-8s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id", "normalized");
209 foreach_pset(set, entry) {
210 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n",
211 get_id_str(entry->op->name),
212 cnt_to_uint(&entry->cnt_alive),
213 cnt_to_uint(&entry->new_node),
214 cnt_to_uint(&entry->into_Id),
215 cnt_to_uint(&entry->normalized)
218 cnt_add(&f_alive, &entry->cnt_alive);
219 cnt_add(&f_new_node, &entry->new_node);
220 cnt_add(&f_Id, &entry->into_Id);
221 cnt_add(&f_normlized, &entry->normalized);
223 fprintf(dmp->f, "-------------------------------------------\n");
224 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n", "Sum",
225 cnt_to_uint(&f_alive),
226 cnt_to_uint(&f_new_node),
228 cnt_to_uint(&f_normlized)
230 } /* simple_dump_opcode_hash */
233 * Return the name of an optimization.
235 static const char *get_opt_name(int index) {
236 assert(index < (int) ARR_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, 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 = 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, 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 = pset_next(entry->be_block_hash)) {
284 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
286 foreach_pset(b_entry->reg_pressure, 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 fprintf(dmp->f, "%12d", cnt_to_uint(&entry->cnt));
296 } /* simple_dump_distrib_entry */
299 * dumps the distribution of the amount of ready nodes for each block
301 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
303 if (pset_count(entry->be_block_hash) > 0) {
304 be_block_entry_t *b_entry;
307 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
308 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
309 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
311 foreach_pset(entry->be_block_hash, b_entry) {
312 /* this ensures that all keys from 1 to 5 are in the table */
313 for (i = 1; i < 6; ++i)
314 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
316 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
317 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
318 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
319 fprintf(dmp->f, "\n");
322 } /* simple_dump_be_block_sched_ready */
325 * Adds the counter for given entry to another distribution table.
327 static void add_distrib_entry(const distrib_entry_t *entry, void *env) {
328 distrib_tbl_t *sum_tbl = env;
330 stat_add_int_distrib_tbl(sum_tbl, PTR_TO_INT(entry->object), &entry->cnt);
331 } /* add_distrib_entry */
334 * dumps permutation statistics for one and block and one class
336 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
338 perm_stat_entry_t *ps_ent;
339 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
340 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
344 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
353 foreach_pset(entry->perm_stat, ps_ent) {
354 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
357 stat_get_count_distrib_tbl(ps_ent->chains),
358 stat_get_count_distrib_tbl(ps_ent->cycles),
363 /* sum up distribution table for chains */
364 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
366 /* sum up distribution table for cycles */
367 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
370 /* print chain distribution for all perms of this class in this block */
371 fprintf(dmp->f, "chain distribution:\n");
373 /* add all missing entries to chain distribution table */
374 for (i = 1; i <= entry->n_regs; i++) {
375 snprintf(buf, sizeof(buf), "length %d", i);
376 fprintf(dmp->f, "%12s", buf);
377 stat_insert_int_distrib_tbl(sum_chains, i);
379 fprintf(dmp->f, "\n");
380 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
381 fprintf(dmp->f, "\n");
383 /* print cycle distribution for all perms of this class in this block */
384 fprintf(dmp->f, "cycle distribution:\n");
386 /* add all missing entries to cycle distribution table */
387 for (i = 1; i <= entry->n_regs; i++) {
388 snprintf(buf, sizeof(buf), "length %d", i);
389 fprintf(dmp->f, "%12s", buf);
390 stat_insert_int_distrib_tbl(sum_cycles, i);
392 fprintf(dmp->f, "\n");
393 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
394 fprintf(dmp->f, "\n");
396 /* delete temporary sum distribution tables */
397 stat_delete_distrib_tbl(sum_chains);
398 stat_delete_distrib_tbl(sum_cycles);
400 } /* simple_dump_be_block_permstat_class */
403 * dumps statistics about perms
405 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
407 if (pset_count(entry->be_block_hash) > 0) {
408 be_block_entry_t *b_entry;
410 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
411 foreach_pset(entry->be_block_hash, b_entry) {
412 perm_class_entry_t *pc_ent;
414 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
416 if (b_entry->perm_class_stat) {
417 foreach_pset(b_entry->perm_class_stat, pc_ent) {
418 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
419 simple_dump_be_block_permstat_class(dmp, pc_ent);
424 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
426 } /* simple_dump_be_block_permstat */
429 * dumps the number of real_function_call optimization
431 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
436 if (! cnt_eq(cnt, 0)) {
437 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
438 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
440 } /* simple_dump_real_func_calls */
443 * dumps the number of tail_recursion optimization
445 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
450 if (num_tail_recursion > 0) {
451 fprintf(dmp->f, "\nTail recursion optimized:\n");
452 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
454 } /* simple_dump_tail_recursion */
457 * dumps the edges count
459 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
464 fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt_to_uint(cnt));
465 } /* simple_dump_edges */
470 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
472 int i, dump_opts = 1;
473 block_entry_t *b_entry;
474 extbb_entry_t *eb_entry;
480 ir_graph *const_irg = get_const_code_irg();
482 if (entry->irg == const_irg)
483 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
486 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
488 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
491 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
492 " was inlined : %u\n"
493 " got inlined : %u\n"
494 " strength red : %u\n"
495 " leaf function : %s\n"
496 " calls only leaf functions : %s\n"
501 " indirect calls : %u\n"
502 " external calls : %u\n",
503 entry->is_deleted ? "DELETED " : "",
504 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
505 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
506 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
507 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
508 entry->is_leaf ? "YES" : "NO",
509 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
510 entry->is_recursive ? "YES" : "NO",
511 entry->is_chain_call ? "YES" : "NO",
512 entry->is_strict ? "YES" : "NO",
513 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
514 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
515 cnt_to_uint(&entry->cnt[gcnt_external_calls])
518 for (i = 0; i < IF_RESULT_LAST; ++i) {
519 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
522 fprintf(dmp->f, "\nGlobals counts:\n");
523 fprintf(dmp->f, "--------------\n");
529 " pure address calc ops : %u\n"
530 " all address calc ops : %u\n",
531 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
532 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
535 /* Load/Store address classification */
537 " global Ld/St address : %u\n"
538 " local Ld/St address : %u\n"
539 " this Ld/St address : %u\n"
540 " param Ld/St address : %u\n"
541 " other Ld/St address : %u\n",
542 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
543 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
544 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
545 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
546 cnt_to_uint(&entry->cnt[gcnt_other_adr])
549 simple_dump_opcode_hash(dmp, entry->opcode_hash);
550 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
552 /* effects of optimizations */
556 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
557 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
559 for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
560 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
563 /* dump block info */
564 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
565 foreach_pset(entry->block_hash, b_entry) {
566 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
568 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
569 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
570 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
571 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
572 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
573 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
574 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
578 /* dump block reg pressure */
579 simple_dump_be_block_reg_pressure(dmp, entry);
581 /* dump block ready nodes distribution */
582 simple_dump_be_block_sched_ready(dmp, entry);
584 /* dump block permutation statistics */
585 simple_dump_be_block_permstat(dmp, entry);
587 if (dmp->status->stat_options & FIRMSTAT_COUNT_EXTBB && entry->extbb_hash) {
588 /* dump extended block info */
589 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Extbb Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
590 foreach_pset(entry->extbb_hash, eb_entry) {
591 fprintf(dmp->f, "ExtBB %6ld %12u %12u %12u %12u %12u %4.8f\n",
593 cnt_to_uint(&eb_entry->cnt[bcnt_nodes]),
594 cnt_to_uint(&eb_entry->cnt[bcnt_edges]),
595 cnt_to_uint(&eb_entry->cnt[bcnt_in_edges]),
596 cnt_to_uint(&eb_entry->cnt[bcnt_out_edges]),
597 cnt_to_uint(&eb_entry->cnt[bcnt_phi_data]),
598 cnt_to_dbl(&eb_entry->cnt[bcnt_edges]) / cnt_to_dbl(&eb_entry->cnt[bcnt_nodes])
603 } /* simple_dump_graph */
606 * dumps the constant table
608 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
618 fprintf(dmp->f, "\nConstant Information:\n");
619 fprintf(dmp->f, "---------------------\n");
621 fprintf(dmp->f, "\nBit usage for integer constants\n");
622 fprintf(dmp->f, "-------------------------------\n");
624 for (i = 0; i < ARR_SIZE(tbl->int_bits_count); ++i) {
625 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
626 cnt_add(&sum, &tbl->int_bits_count[i]);
628 fprintf(dmp->f, "-------------------------------\n");
630 fprintf(dmp->f, "\nFloating point constants classification\n");
631 fprintf(dmp->f, "--------------------------------------\n");
632 for (i = 0; i < ARR_SIZE(tbl->floats); ++i) {
633 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name(i), cnt_to_uint(&tbl->floats[i]));
634 cnt_add(&sum, &tbl->floats[i]);
636 fprintf(dmp->f, "--------------------------------------\n");
638 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
639 cnt_add(&sum, &tbl->others);
640 fprintf(dmp->f, "-------------------------------\n");
642 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
643 } /* simple_dump_const_tbl */
646 * Dumps a line of the parameter table
648 static void dump_tbl_line(const distrib_entry_t *entry, void *env) {
651 fprintf(dmp->f, "%d : %u\n", PTR_TO_INT(entry->object), cnt_to_uint(&entry->cnt));
652 } /* dump_tbl_line */
655 * dumps the parameter distribution table
657 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
658 fprintf(dmp->f, "\nCall parameter Information:\n");
659 fprintf(dmp->f, "---------------------\n");
661 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
662 fprintf(dmp->f, "-------------------------------\n");
664 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
665 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
666 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
667 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
668 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
669 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
670 } /* simple_dump_param_tbl */
673 * dumps the optimization counter table
675 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
678 fprintf(dmp->f, "\nOptimization counts:\n");
679 fprintf(dmp->f, "---------------------\n");
681 for (i = 0; i < len; ++i) {
682 unsigned cnt = cnt_to_uint(&tbl[i]);
685 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
688 } /* simple_dump_opt_cnt */
691 * initialize the simple dumper
693 static void simple_init(dumper_t *dmp, const char *name) {
696 snprintf(fname, sizeof(fname), "%s.txt", name);
697 dmp->f = fopen(fname, "w");
704 * finishes the simple dumper
706 static void simple_finish(dumper_t *dmp) {
710 } /* simple_finish */
713 * the simple human readable dumper
715 const dumper_t simple_dumper = {
717 simple_dump_const_tbl,
718 simple_dump_param_tbl,
726 FOURCC('S', 'M', 'P', 'L'),
729 /* ---------------------------------------------------------------------- */
732 * count the nodes as needed:
734 * 1 normal (data) Phi's
739 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
744 for (i = 0; i < 4; ++i)
747 foreach_pset(graph->opcode_hash, entry) {
748 if (entry->op == op_Phi) {
750 cnt_add(&cnt[1], &entry->cnt_alive);
751 } else if (entry->op == dmp->status->op_PhiM) {
753 cnt_add(&cnt[2], &entry->cnt_alive);
754 } else if (entry->op == op_Proj) {
756 cnt_add(&cnt[3], &entry->cnt_alive);
758 /* all other nodes */
759 cnt_add(&cnt[0], &entry->cnt_alive);
762 } /* csv_count_nodes */
767 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
775 if (entry->irg && !entry->is_deleted) {
776 ir_graph *const_irg = get_const_code_irg();
778 if (entry->irg == const_irg) {
779 name = "<Const code Irg>";
783 name = get_entity_name(entry->ent);
785 name = "<UNKNOWN IRG>";
788 csv_count_nodes(dmp, entry, cnt);
790 fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
793 cnt_to_uint(&cnt[0]),
794 cnt_to_uint(&cnt[1]),
795 cnt_to_uint(&cnt[2]),
799 } /* csv_dump_graph */
804 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
809 } /* csv_dump_const_tbl */
812 * dumps the parameter distribution table
814 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global) {
819 } /* csv_dump_param_tbl */
822 * dumps the optimization counter
824 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len) {
829 } /* csv_dump_opt_cnt */
832 * initialize the simple dumper
834 static void csv_init(dumper_t *dmp, const char *name)
838 snprintf(fname, sizeof(fname), "%s.csv", name);
839 dmp->f = fopen(fname, "a");
845 * finishes the simple dumper
847 static void csv_finish(dumper_t *dmp)
855 * the simple human readable dumper
857 const dumper_t csv_dumper = {
868 FOURCC('C', 'S', 'V', '\0')