2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief Statistics for Firm. Dumping.
20 * names of the optimizations
26 { HOOK_OPT_DEAD_BLOCK, "dead block elimination" },
27 { HOOK_OPT_STG, "straightening optimization" },
28 { HOOK_OPT_IFSIM, "if simplification" },
29 { HOOK_OPT_CONST_EVAL, "constant evaluation" },
30 { HOOK_OPT_ALGSIM, "algebraic simplification" },
31 { HOOK_OPT_PHI, "Phi optmization" },
32 { HOOK_OPT_SYNC, "Sync optmization" },
33 { HOOK_OPT_WAW, "Write-After-Write optimization" },
34 { HOOK_OPT_WAR, "Write-After-Read optimization" },
35 { HOOK_OPT_RAW, "Read-After-Write optimization" },
36 { HOOK_OPT_RAR, "Read-After-Read optimization" },
37 { HOOK_OPT_RC, "Read-a-Const optimization" },
38 { HOOK_OPT_TUPLE, "Tuple optimization" },
39 { HOOK_OPT_ID, "ID optimization" },
40 { HOOK_OPT_CSE, "Common subexpression elimination" },
41 { HOOK_OPT_STRENGTH_RED, "Strength reduction" },
42 { HOOK_OPT_ARCH_DEP, "Architecture dependant optimization" },
43 { HOOK_OPT_REASSOC, "Reassociation optimization" },
44 { HOOK_OPT_POLY_CALL, "Polymorphic call optimization" },
45 { HOOK_OPT_IF_CONV, "an if conversion was tried" },
46 { HOOK_OPT_FUNC_CALL, "Real function call optimization" },
47 { HOOK_OPT_CONFIRM, "Confirm-based optimization: replacement" },
48 { HOOK_OPT_CONFIRM_C, "Confirm-based optimization: replaced by const" },
49 { HOOK_OPT_CONFIRM_E, "Confirm-based optimization: evaluated" },
50 { HOOK_OPT_EXC_REM, "a exception edge was removed due to a Confirmation prove" },
51 { HOOK_OPT_NORMALIZE, "a commutative node was normalized" },
52 { HOOK_LOWERED, "Lowered" },
53 { HOOK_BACKEND, "Backend transformation" },
54 { (hook_opt_kind)FS_OPT_NEUTRAL_0, "algebraic simplification: a op 0 = 0 op a = a" },
55 { (hook_opt_kind)FS_OPT_NEUTRAL_1, "algebraic simplification: a op 1 = 1 op a = a" },
56 { (hook_opt_kind)FS_OPT_ADD_A_A, "algebraic simplification: a + a = a * 2" },
57 { (hook_opt_kind)FS_OPT_ADD_A_MINUS_B, "algebraic simplification: a + -b = a - b" },
58 { (hook_opt_kind)FS_OPT_ADD_SUB, "algebraic simplification: (a + x) - x = (a - x) + x = a" },
59 { (hook_opt_kind)FS_OPT_ADD_MUL_A_X_A, "algebraic simplification: a * x + a = a * (x + 1)" },
60 { (hook_opt_kind)FS_OPT_SUB_0_A, "algebraic simplification: 0 - a = -a" },
61 { (hook_opt_kind)FS_OPT_MINUS_SUB, "algebraic simplification: -(a - b) = b - a" },
62 { (hook_opt_kind)FS_OPT_SUB_MINUS, "algebraic simplification: a - (-b) = a + b" },
63 { (hook_opt_kind)FS_OPT_SUB_MUL_A_X_A, "algebraic simplification: a * x - a = a * (x - 1)" },
64 { (hook_opt_kind)FS_OPT_SUB_SUB_X_Y_Z, "algebraic simplification: (x - y) - z = x - (y + z)" },
65 { (hook_opt_kind)FS_OPT_SUB_C_NOT_X, "algebraic simplification: c - ~a = a + (c+1)" },
66 { (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)" },
67 { (hook_opt_kind)FS_OPT_SUB_TO_NOT, "algebraic simplification: -1 - x -> ~x" },
68 { (hook_opt_kind)FS_OPT_SUB_TO_CONV, "algebraic simplification: a - NULL = (int)a" },
69 { (hook_opt_kind)FS_OPT_MUL_MINUS, "algebraic simplification: (-a) * (b - c) = a * (c - b)" },
70 { (hook_opt_kind)FS_OPT_MUL_MINUS_1, "algebraic simplification: a * -1 = -a" },
71 { (hook_opt_kind)FS_OPT_MINUS_MUL_C, "algebraic simplification: (-a) * C = a * (-C)" },
72 { (hook_opt_kind)FS_OPT_MUL_MINUS_MINUS,"algebraic simplification: (-a) * (-b) = a * b" },
73 { (hook_opt_kind)FS_OPT_OR, "algebraic simplification: a | a = a | 0 = 0 | a = a" },
74 { (hook_opt_kind)FS_OPT_AND, "algebraic simplification: a & 0b1...1 = 0b1...1 & a = a & a = (a|X) & a = a" },
75 { (hook_opt_kind)FS_OPT_TO_EOR, "algebraic simplification: (a|b) & ~(a&b) = a^b" },
76 { (hook_opt_kind)FS_OPT_EOR_A_A, "algebraic simplification: a ^ a = 0" },
77 { (hook_opt_kind)FS_OPT_EOR_A_B_A, "algebraic simplification: (a ^ b) ^ a = b" },
78 { (hook_opt_kind)FS_OPT_EOR_TO_NOT_BOOL,"boolean simplification: bool ^ 1 = !bool" },
79 { (hook_opt_kind)FS_OPT_EOR_TO_NOT, "algebraic simplification: x ^ 0b1..1 = ~x, (a ^ b) & b = ~a & b" },
80 { (hook_opt_kind)FS_OPT_NOT_CMP, "algebraic simplification: !(a cmp b) = a !cmp b" },
81 { (hook_opt_kind)FS_OPT_OR_SHFT_TO_ROTL,"algebraic simplification: (x << c) | (x >> (bits - c)) == Rotl(x, c)" },
82 { (hook_opt_kind)FS_OPT_REASSOC_SHIFT, "algebraic simplification: (x SHF c1) SHF c2 = x SHF (c1+c2)" },
83 { (hook_opt_kind)FS_OPT_SHIFT_AND, "algebraic simplification: (a SHF c) AND (b SHF c) = (a AND b) SHF c" },
84 { (hook_opt_kind)FS_OPT_SHIFT_OR, "algebraic simplification: (a SHF c) OR (b SHF c) = (a OR b) SHF c" },
85 { (hook_opt_kind)FS_OPT_SHIFT_EOR, "algebraic simplification: (a SHF c) XOR (b SHF c) = (a XOR b) SHF c" },
86 { (hook_opt_kind)FS_OPT_CONV, "algebraic simplification: Conv could be removed" },
87 { (hook_opt_kind)FS_OPT_MIN_MAX_EQ, "algebraic simplification: Min(a,a) = Max(a,a) = a" },
88 { (hook_opt_kind)FS_OPT_MUX_COMBINE, "boolean simplification: two Mux nodes where combined into one" },
89 { (hook_opt_kind)FS_OPT_MUX_CONV, "boolean simplification: MuxI(sel, 1, 0) = (I)sel" },
90 { (hook_opt_kind)FS_OPT_MUX_BOOL, "boolean simplification: Muxb(sel, true, false) = sel" },
91 { (hook_opt_kind)FS_OPT_MUX_NOT_BOOL, "boolean simplification: Muxb(sel, false, true) = Not(sel)" },
92 { (hook_opt_kind)FS_OPT_MUX_OR_BOOL, "boolean simplification: Muxb(sel, true, x) = Or(sel, x)" },
93 { (hook_opt_kind)FS_OPT_MUX_ORNOT_BOOL, "boolean simplification: Muxb(sel, x, true) = Or(Not(sel), x)" },
94 { (hook_opt_kind)FS_OPT_MUX_AND_BOOL, "boolean simplification: Muxb(sel, x, false) = And(sel, x)" },
95 { (hook_opt_kind)FS_OPT_MUX_ANDNOT_BOOL,"boolean simplification: Muxb(sel, false, x) = And(Not(sel), x)" },
96 { (hook_opt_kind)FS_OPT_MUX_C, "algebraic simplification: Mux(C, f, t) = C ? t : f" },
97 { (hook_opt_kind)FS_OPT_MUX_EQ, "algebraic simplification: Mux(v, x, x) = x" },
98 { (hook_opt_kind)FS_OPT_MUX_TRANSFORM, "algebraic simplification: Mux(t ==/!= f, t, f) = f/t, Mux(t ==/!= 0, -t, t) = -t/t" },
99 { (hook_opt_kind)FS_OPT_MUX_TO_MIN, "algebraic simplification: Mux(a < b, a, b) = Min(a,b)" },
100 { (hook_opt_kind)FS_OPT_MUX_TO_MAX, "algebraic simplification: Mux(a > b, a, b) = Max(a,b)" },
101 { (hook_opt_kind)FS_OPT_MUX_TO_BITOP, "algebraic simplification: Mux((a & 2^x) ==/!= 0, 2^x, 0) = (a & 2^x) (xor 2^x)" },
102 { (hook_opt_kind)FS_OPT_INVOLUTION, "algebraic simplification: OP(OP(x)) = x" },
103 { (hook_opt_kind)FS_OPT_MINUS_NOT, "algebraic simplification: -(~x) = x + 1" },
104 { (hook_opt_kind)FS_OPT_NOT_MINUS_1, "algebraic simplification: ~(x - 1) = -x" },
105 { (hook_opt_kind)FS_OPT_NOT_PLUS_1, "algebraic simplification: ~x + 1 = -x" },
106 { (hook_opt_kind)FS_OPT_ADD_X_NOT_X, "algebraic simplification: ~x + x = -1" },
107 { (hook_opt_kind)FS_OPT_FP_INV_MUL, "algebraic simplification: x / y = x * (1.0/y)" },
108 { (hook_opt_kind)FS_OPT_CONST_PHI, "constant evaluation on Phi node" },
109 { (hook_opt_kind)FS_OPT_PREDICATE, "predicate optimization" },
110 { (hook_opt_kind)FS_OPT_DEMORGAN, "optimization using DeMorgan's law" },
111 { (hook_opt_kind)FS_OPT_CMP_OP_OP, "CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y)" },
112 { (hook_opt_kind)FS_OPT_CMP_OP_C, "CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2)" },
113 { (hook_opt_kind)FS_OPT_CMP_CONV_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y)" },
114 { (hook_opt_kind)FS_OPT_CMP_CONV, "CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y)" },
115 { (hook_opt_kind)FS_OPT_CMP_TO_BOOL, "CMP optimization: Cmp(x, y) = BoolOP(x, y)" },
116 { (hook_opt_kind)FS_OPT_CMP_CNST_MAGN, "CMP optimization: reduced magnitude of a const" },
117 { (hook_opt_kind)FS_OPT_CMP_SHF_TO_AND, "CMP optimization: transformed shift into And" },
118 { (hook_opt_kind)FS_OPT_CMP_MOD_TO_AND, "CMP optimization: transformed Mod into And" },
119 { (hook_opt_kind)FS_OPT_NOP, "the operation is a NOP" },
120 { (hook_opt_kind)FS_OPT_GVN_FOLLOWER, "GVN-PRE: replaced a follower" },
121 { (hook_opt_kind)FS_OPT_GVN_FULLY, "GVN-PRE: replaced by fully redundant value" },
122 { (hook_opt_kind)FS_OPT_GVN_PARTLY, "GVN-PRE: replaced by partly redundant value" },
123 { (hook_opt_kind)FS_OPT_COMBO_CONST, "Combo: evaluated into Constant" },
124 { (hook_opt_kind)FS_OPT_COMBO_CF, "Combo: removed conditional control flow" },
125 { (hook_opt_kind)FS_OPT_COMBO_FOLLOWER, "Combo: removed a follower" },
126 { (hook_opt_kind)FS_OPT_COMBO_CONGRUENT,"Combo: replaced by congruent" },
127 { (hook_opt_kind)FS_OPT_JUMPTHREADING, "Jump threading: removed conditional control flow" },
128 { (hook_opt_kind)FS_OPT_RTS_ABS, "RTS optimization: call to abs() replaced" },
129 { (hook_opt_kind)FS_OPT_RTS_ALLOCA, "RTS optimization: call to alloca() replaced" },
130 { (hook_opt_kind)FS_OPT_RTS_SQRT, "RTS optimization: call to sqrt() replaced" },
131 { (hook_opt_kind)FS_OPT_RTS_CBRT, "RTS optimization: call to cbrt() replaced" },
132 { (hook_opt_kind)FS_OPT_RTS_POW, "RTS optimization: call to pow() replaced" },
133 { (hook_opt_kind)FS_OPT_RTS_EXP, "RTS optimization: call to exp() replaced" },
134 { (hook_opt_kind)FS_OPT_RTS_LOG, "RTS optimization: call to log() replaced" },
135 { (hook_opt_kind)FS_OPT_RTS_SIN, "RTS optimization: call to sin() replaced" },
136 { (hook_opt_kind)FS_OPT_RTS_COS, "RTS optimization: call to cos() replaced" },
137 { (hook_opt_kind)FS_OPT_RTS_TAN, "RTS optimization: call to tan() replaced" },
138 { (hook_opt_kind)FS_OPT_RTS_ASIN, "RTS optimization: call to asin() replaced" },
139 { (hook_opt_kind)FS_OPT_RTS_ACOS, "RTS optimization: call to atan() replaced" },
140 { (hook_opt_kind)FS_OPT_RTS_ATAN, "RTS optimization: call to acos() replaced" },
141 { (hook_opt_kind)FS_OPT_RTS_SINH, "RTS optimization: call to sinh() replaced" },
142 { (hook_opt_kind)FS_OPT_RTS_COSH, "RTS optimization: call to cosh() replaced" },
143 { (hook_opt_kind)FS_OPT_RTS_TANH, "RTS optimization: call to tanh() replaced" },
144 { (hook_opt_kind)FS_OPT_RTS_SYMMETRIC, "RTS optimization: call to symmetric function f(-x) replaced by f(x)" },
145 { (hook_opt_kind)FS_OPT_RTS_STRCMP, "RTS optimization: call to strcmp() replaced" },
146 { (hook_opt_kind)FS_OPT_RTS_STRNCMP, "RTS optimization: call to strncmp() replaced" },
147 { (hook_opt_kind)FS_OPT_RTS_STRCPY, "RTS optimization: call to strcpy() replaced" },
148 { (hook_opt_kind)FS_OPT_RTS_STRLEN, "RTS optimization: call to strlen() replaced" },
149 { (hook_opt_kind)FS_OPT_RTS_MEMCPY, "RTS optimization: call to memcpy() replaced" },
150 { (hook_opt_kind)FS_OPT_RTS_MEMPCPY, "RTS optimization: call to mempcpy() replaced" },
151 { (hook_opt_kind)FS_OPT_RTS_MEMMOVE, "RTS optimization: call to memmove() replaced" },
152 { (hook_opt_kind)FS_OPT_RTS_MEMSET, "RTS optimization: call to memset() replaced" },
153 { (hook_opt_kind)FS_OPT_RTS_MEMCMP, "RTS optimization: call to memcmp() replaced" },
154 { (hook_opt_kind)FS_BE_IA32_LEA, "ia32 Backend transformation: Lea was created" },
155 { (hook_opt_kind)FS_BE_IA32_LOAD_LEA, "ia32 Backend transformation: Load merged with a Lea" },
156 { (hook_opt_kind)FS_BE_IA32_STORE_LEA, "ia32 Backend transformation: Store merged with a Lea" },
157 { (hook_opt_kind)FS_BE_IA32_AM_S, "ia32 Backend transformation: Source address mode node created" },
158 { (hook_opt_kind)FS_BE_IA32_AM_D, "ia32 Backend transformation: Destination address mode node created" },
159 { (hook_opt_kind)FS_BE_IA32_CJMP, "ia32 Backend transformation: CJmp created to save a cmp/test" },
160 { (hook_opt_kind)FS_BE_IA32_2ADDRCPY, "ia32 Backend transformation: Copy created due to 2-Addresscode constraints" },
161 { (hook_opt_kind)FS_BE_IA32_SPILL2ST, "ia32 Backend transformation: Created Store for a Spill" },
162 { (hook_opt_kind)FS_BE_IA32_RELOAD2LD, "ia32 Backend transformation: Created Load for a Reload" },
163 { (hook_opt_kind)FS_BE_IA32_SUB2NEGADD, "ia32 Backend transformation: Created Neg-Add for a Sub due to 2-Addresscode constraints" },
164 { (hook_opt_kind)FS_BE_IA32_LEA2ADD, "ia32 Backend transformation: Transformed Lea back into Add" },
167 static const char *if_conv_names[IF_RESULT_LAST] = {
169 "if conv side effect ",
170 "if conv Phi node found ",
171 "if conv to deep DAG's ",
172 "if conv bad control flow ",
173 "if conv denied by arch ",
177 * dumps a opcode hash into human readable form
179 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
182 counter_t f_new_node;
184 counter_t f_normlized;
187 cnt_clr(&f_new_node);
189 cnt_clr(&f_normlized);
191 fprintf(dmp->f, "%-16s %-8s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id", "normalized");
192 foreach_pset(set, node_entry_t, entry) {
193 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n",
194 get_id_str(entry->op->name),
195 cnt_to_uint(&entry->cnt_alive),
196 cnt_to_uint(&entry->new_node),
197 cnt_to_uint(&entry->into_Id),
198 cnt_to_uint(&entry->normalized)
201 cnt_add(&f_alive, &entry->cnt_alive);
202 cnt_add(&f_new_node, &entry->new_node);
203 cnt_add(&f_Id, &entry->into_Id);
204 cnt_add(&f_normlized, &entry->normalized);
206 fprintf(dmp->f, "-------------------------------------------\n");
207 fprintf(dmp->f, "%-16s %8u %8u %8u %8u\n", "Sum",
208 cnt_to_uint(&f_alive),
209 cnt_to_uint(&f_new_node),
211 cnt_to_uint(&f_normlized)
216 * Return the name of an optimization.
218 static const char *get_opt_name(int index)
220 assert(index < (int) ARRAY_SIZE(opt_names) && "index out of range");
221 assert((int) opt_names[index].kind == index && "opt_names broken");
222 return opt_names[index].name;
226 * dumps an optimization hash into human readable form
228 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
230 if (pset_count(set) > 0) {
231 const char *name = get_opt_name(index);
233 fprintf(dmp->f, "\n%s:\n", name);
234 fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
236 foreach_pset(set, opt_entry_t, entry) {
237 fprintf(dmp->f, "%-16s %8u\n",
238 get_id_str(entry->op->name), cnt_to_uint(&entry->count));
244 * dumps the register pressure for each block and for each register class
246 static void simple_dump_be_block_reg_pressure(dumper_t *dmp, graph_entry_t *entry)
248 /* return if no be statistic information available */
249 be_block_entry_t *const b_first = pset_first(be_block_entry_t, entry->be_block_hash);
253 fprintf(dmp->f, "\nREG PRESSURE:\n");
254 fprintf(dmp->f, "%12s", "Block Nr");
256 /* print table head (register class names) */
257 foreach_pset(b_first->reg_pressure, reg_pressure_entry_t, rp_entry)
258 fprintf(dmp->f, "%15s", rp_entry->class_name);
259 fprintf(dmp->f, "\n");
261 /* print the reg pressure for all blocks and register classes */
262 foreach_pset(entry->block_hash, be_block_entry_t, b_entry) {
263 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
265 foreach_pset(b_entry->reg_pressure, reg_pressure_entry_t, rp_entry)
266 fprintf(dmp->f, "%15d", rp_entry->pressure);
267 fprintf(dmp->f, "\n");
271 /** prints a distribution entry */
272 static void simple_dump_distrib_entry(const distrib_entry_t *entry, void *env)
274 dumper_t *dmp = (dumper_t*)env;
275 fprintf(dmp->f, "%12u", cnt_to_uint(&entry->cnt));
279 * dumps the distribution of the amount of ready nodes for each block
281 static void simple_dump_be_block_sched_ready(dumper_t *dmp, graph_entry_t *entry)
283 if (pset_count(entry->be_block_hash) > 0) {
286 fprintf(dmp->f, "\nSCHEDULING: NUMBER OF READY NODES\n");
287 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s %12s\n",
288 "Block Nr", "1 node", "2 nodes", "3 nodes", "4 nodes", "5 or more", "AVERAGE");
290 foreach_pset(entry->be_block_hash, be_block_entry_t, b_entry) {
291 /* this ensures that all keys from 1 to 5 are in the table */
292 for (i = 1; i < 6; ++i)
293 stat_insert_int_distrib_tbl(b_entry->sched_ready, i);
295 fprintf(dmp->f, "BLK %6ld", b_entry->block_nr);
296 stat_iterate_distrib_tbl(b_entry->sched_ready, simple_dump_distrib_entry, dmp);
297 fprintf(dmp->f, "%12.2lf", stat_calc_avg_distrib_tbl(b_entry->sched_ready));
298 fprintf(dmp->f, "\n");
304 * Adds the counter for given entry to another distribution table.
306 static void add_distrib_entry(const distrib_entry_t *entry, void *env)
308 distrib_tbl_t *sum_tbl = (distrib_tbl_t*)env;
310 stat_add_int_distrib_tbl(sum_tbl, (int)PTR_TO_INT(entry->object), &entry->cnt);
314 * dumps permutation statistics for one and block and one class
316 static void simple_dump_be_block_permstat_class(dumper_t *dmp, perm_class_entry_t *entry)
318 distrib_tbl_t *sum_chains = stat_new_int_distrib_tbl();
319 distrib_tbl_t *sum_cycles = stat_new_int_distrib_tbl();
323 fprintf(dmp->f, "%12s %12s %12s %12s %12s %12s\n",
332 foreach_pset(entry->perm_stat, perm_stat_entry_t, ps_ent) {
333 fprintf(dmp->f, "%12d %12d %12d %12d %12d %12d\n",
336 stat_get_count_distrib_tbl(ps_ent->chains),
337 stat_get_count_distrib_tbl(ps_ent->cycles),
342 /* sum up distribution table for chains */
343 stat_iterate_distrib_tbl(ps_ent->chains, add_distrib_entry, sum_chains);
345 /* sum up distribution table for cycles */
346 stat_iterate_distrib_tbl(ps_ent->cycles, add_distrib_entry, sum_cycles);
349 /* print chain distribution for all perms of this class in this block */
350 fprintf(dmp->f, "chain distribution:\n");
352 /* add all missing entries to chain distribution table */
353 for (i = 1; i <= entry->n_regs; i++) {
354 snprintf(buf, sizeof(buf), "length %d", i);
355 fprintf(dmp->f, "%12s", buf);
356 stat_insert_int_distrib_tbl(sum_chains, i);
358 fprintf(dmp->f, "\n");
359 stat_iterate_distrib_tbl(sum_chains, simple_dump_distrib_entry, dmp);
360 fprintf(dmp->f, "\n");
362 /* print cycle distribution for all perms of this class in this block */
363 fprintf(dmp->f, "cycle distribution:\n");
365 /* add all missing entries to cycle distribution table */
366 for (i = 1; i <= entry->n_regs; i++) {
367 snprintf(buf, sizeof(buf), "length %d", i);
368 fprintf(dmp->f, "%12s", buf);
369 stat_insert_int_distrib_tbl(sum_cycles, i);
371 fprintf(dmp->f, "\n");
372 stat_iterate_distrib_tbl(sum_cycles, simple_dump_distrib_entry, dmp);
373 fprintf(dmp->f, "\n");
375 /* delete temporary sum distribution tables */
376 stat_delete_distrib_tbl(sum_chains);
377 stat_delete_distrib_tbl(sum_cycles);
382 * dumps statistics about perms
384 static void simple_dump_be_block_permstat(dumper_t *dmp, graph_entry_t *entry)
386 if (pset_count(entry->be_block_hash) > 0) {
387 fprintf(dmp->f, "\nPERMUTATION STATISTICS BEGIN:\n");
388 foreach_pset(entry->be_block_hash, be_block_entry_t, b_entry) {
389 fprintf(dmp->f, "BLOCK %ld:\n", b_entry->block_nr);
391 if (b_entry->perm_class_stat) {
392 foreach_pset(b_entry->perm_class_stat, perm_class_entry_t, pc_ent) {
393 fprintf(dmp->f, "register class %s:\n", pc_ent->class_name);
394 simple_dump_be_block_permstat_class(dmp, pc_ent);
399 fprintf(dmp->f, "PERMUTATION STATISTICS END\n");
404 * dumps the number of real_function_call optimization
406 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
411 if (! cnt_eq(cnt, 0)) {
412 fprintf(dmp->f, "\nReal Function Calls optimized:\n");
413 fprintf(dmp->f, "%-16s %8u\n", "Call", cnt_to_uint(cnt));
418 * dumps the number of tail_recursion optimization
420 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
425 if (num_tail_recursion > 0) {
426 fprintf(dmp->f, "\nTail recursion optimized:\n");
427 fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
432 * dumps the edges count
434 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
439 fprintf(dmp->f, "%-16s %8u\n", "Edges", cnt_to_uint(cnt));
445 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
453 ir_graph *const_irg = get_const_code_irg();
456 if (entry->irg == const_irg)
457 fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
460 fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_ld_name(entry->ent), (void *)entry->irg);
462 fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
465 fprintf(dmp->f, " %swalked %u over blocks %u:\n"
466 " was inlined : %u\n"
467 " got inlined : %u\n"
468 " strength red : %u\n"
469 " leaf function : %s\n"
470 " calls only leaf functions : %s\n"
475 " indirect calls : %u\n"
476 " external calls : %u\n",
477 entry->is_deleted ? "DELETED " : "",
478 cnt_to_uint(&entry->cnt[gcnt_acc_walked]), cnt_to_uint(&entry->cnt[gcnt_acc_walked_blocks]),
479 cnt_to_uint(&entry->cnt[gcnt_acc_was_inlined]),
480 cnt_to_uint(&entry->cnt[gcnt_acc_got_inlined]),
481 cnt_to_uint(&entry->cnt[gcnt_acc_strength_red]),
482 entry->is_leaf ? "YES" : "NO",
483 entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
484 entry->is_recursive ? "YES" : "NO",
485 entry->is_chain_call ? "YES" : "NO",
486 entry->is_strict ? "YES" : "NO",
487 cnt_to_uint(&entry->cnt[gcnt_all_calls]),
488 cnt_to_uint(&entry->cnt[gcnt_indirect_calls]),
489 cnt_to_uint(&entry->cnt[gcnt_external_calls])
492 for (i = 0; i < IF_RESULT_LAST; ++i) {
493 fprintf(dmp->f, " %s : %u\n", if_conv_names[i], cnt_to_uint(&entry->cnt[gcnt_if_conv + i]));
496 fprintf(dmp->f, "\nGlobals counts:\n");
497 fprintf(dmp->f, "--------------\n");
503 " pure address calc ops : %u\n"
504 " all address calc ops : %u\n",
505 cnt_to_uint(&entry->cnt[gcnt_pure_adr_ops]),
506 cnt_to_uint(&entry->cnt[gcnt_all_adr_ops])
509 /* Load/Store address classification */
511 " global Ld/St address : %u\n"
512 " local Ld/St address : %u\n"
513 " this Ld/St address : %u\n"
514 " param Ld/St address : %u\n"
515 " other Ld/St address : %u\n",
516 cnt_to_uint(&entry->cnt[gcnt_global_adr]),
517 cnt_to_uint(&entry->cnt[gcnt_local_adr]),
518 cnt_to_uint(&entry->cnt[gcnt_this_adr]),
519 cnt_to_uint(&entry->cnt[gcnt_param_adr]),
520 cnt_to_uint(&entry->cnt[gcnt_other_adr])
523 simple_dump_opcode_hash(dmp, entry->opcode_hash);
524 simple_dump_edges(dmp, &entry->cnt[gcnt_edges]);
526 /* effects of optimizations */
530 simple_dump_real_func_calls(dmp, &entry->cnt[gcnt_acc_real_func_call]);
531 simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
533 for (i = 0; i != ARRAY_SIZE(entry->opt_hash); ++i) {
534 simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
537 /* dump block info */
538 fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
539 foreach_pset(entry->block_hash, block_entry_t, b_entry) {
540 fprintf(dmp->f, "BLK %6ld %12u %12u %12u %12u %12u %4.8f %s\n",
542 cnt_to_uint(&b_entry->cnt[bcnt_nodes]),
543 cnt_to_uint(&b_entry->cnt[bcnt_edges]),
544 cnt_to_uint(&b_entry->cnt[bcnt_in_edges]),
545 cnt_to_uint(&b_entry->cnt[bcnt_out_edges]),
546 cnt_to_uint(&b_entry->cnt[bcnt_phi_data]),
547 cnt_to_dbl(&b_entry->cnt[bcnt_edges]) / cnt_to_dbl(&b_entry->cnt[bcnt_nodes]),
548 b_entry->is_start ? "START" : (b_entry->is_end ? "END" : "")
552 /* dump block reg pressure */
553 simple_dump_be_block_reg_pressure(dmp, entry);
555 /* dump block ready nodes distribution */
556 simple_dump_be_block_sched_ready(dmp, entry);
558 /* dump block permutation statistics */
559 simple_dump_be_block_permstat(dmp, entry);
564 * dumps the constant table
566 static void simple_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
576 fprintf(dmp->f, "\nConstant Information:\n");
577 fprintf(dmp->f, "---------------------\n");
579 fprintf(dmp->f, "\nBit usage for integer constants\n");
580 fprintf(dmp->f, "-------------------------------\n");
582 for (i = 0; i < ARRAY_SIZE(tbl->int_bits_count); ++i) {
583 fprintf(dmp->f, "%5u %12u\n", (unsigned) (i + 1), cnt_to_uint(&tbl->int_bits_count[i]));
584 cnt_add(&sum, &tbl->int_bits_count[i]);
586 fprintf(dmp->f, "-------------------------------\n");
588 fprintf(dmp->f, "\nFloating point constants classification\n");
589 fprintf(dmp->f, "--------------------------------------\n");
590 for (i = 0; i < ARRAY_SIZE(tbl->floats); ++i) {
591 fprintf(dmp->f, "%-10s %12u\n", stat_fc_name((float_classify_t)i), cnt_to_uint(&tbl->floats[i]));
592 cnt_add(&sum, &tbl->floats[i]);
594 fprintf(dmp->f, "--------------------------------------\n");
596 fprintf(dmp->f, "other %12u\n", cnt_to_uint(&tbl->others));
597 cnt_add(&sum, &tbl->others);
598 fprintf(dmp->f, "-------------------------------\n");
600 fprintf(dmp->f, "sum %12u\n", cnt_to_uint(&sum));
604 * Dumps a line of the parameter table
606 static void dump_tbl_line(const distrib_entry_t *entry, void *env)
608 dumper_t *dmp = (dumper_t*)env;
610 fprintf(dmp->f, "%ld : %u\n", (long int)PTR_TO_INT(entry->object),
611 cnt_to_uint(&entry->cnt));
615 * dumps the parameter distribution table
617 static void simple_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global)
619 fprintf(dmp->f, "\nCall parameter Information:\n");
620 fprintf(dmp->f, "---------------------\n");
622 stat_iterate_distrib_tbl(tbl, dump_tbl_line, dmp);
623 fprintf(dmp->f, "-------------------------------\n");
625 fprintf(dmp->f, "Number of Calls %12u\n", cnt_to_uint(&global->cnt[gcnt_all_calls]));
626 fprintf(dmp->f, "indirect calls %12u\n", cnt_to_uint(&global->cnt[gcnt_indirect_calls]));
627 fprintf(dmp->f, "external calls %12u\n", cnt_to_uint(&global->cnt[gcnt_external_calls]));
628 fprintf(dmp->f, "with const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_cnst_arg]));
629 fprintf(dmp->f, "with all const params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_all_cnst_arg]));
630 fprintf(dmp->f, "with local var adr params %12u\n", cnt_to_uint(&global->cnt[gcnt_call_with_local_adr]));
634 * dumps the optimization counter table
636 static void simple_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len)
640 fprintf(dmp->f, "\nOptimization counts:\n");
641 fprintf(dmp->f, "---------------------\n");
643 for (i = 0; i < len; ++i) {
644 unsigned cnt = cnt_to_uint(&tbl[i]);
647 fprintf(dmp->f, "%8u %s\n", cnt, get_opt_name(i));
653 * initialize the simple dumper
655 static void simple_init(dumper_t *dmp, const char *name)
659 snprintf(fname, sizeof(fname), "%s.txt", name);
660 dmp->f = fopen(fname, "w");
667 * finishes the simple dumper
669 static void simple_finish(dumper_t *dmp)
677 * the simple human readable dumper
679 const dumper_t simple_dumper = {
681 simple_dump_const_tbl,
682 simple_dump_param_tbl,
690 FOURCC('S', 'M', 'P', 'L'),
693 /* ---------------------------------------------------------------------- */
696 * count the nodes as needed:
698 * 1 normal (data) Phi's
703 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
707 for (i = 0; i < 4; ++i)
710 foreach_pset(graph->opcode_hash, node_entry_t, entry) {
711 if (entry->op == op_Phi) {
713 cnt_add(&cnt[1], &entry->cnt_alive);
714 } else if (entry->op == dmp->status->op_PhiM) {
716 cnt_add(&cnt[2], &entry->cnt_alive);
717 } else if (entry->op == op_Proj) {
719 cnt_add(&cnt[3], &entry->cnt_alive);
721 /* all other nodes */
722 cnt_add(&cnt[0], &entry->cnt_alive);
730 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
738 if (entry->irg && !entry->is_deleted) {
739 ir_graph *const_irg = get_const_code_irg();
741 if (entry->irg == const_irg) {
745 name = get_entity_name(entry->ent);
747 name = "<UNKNOWN IRG>";
750 csv_count_nodes(dmp, entry, cnt);
752 fprintf(dmp->f, "%-40s, %p, %u, %u, %u, %u\n",
755 cnt_to_uint(&cnt[0]),
756 cnt_to_uint(&cnt[1]),
757 cnt_to_uint(&cnt[2]),
766 static void csv_dump_const_tbl(dumper_t *dmp, const constant_info_t *tbl)
774 * dumps the parameter distribution table
776 static void csv_dump_param_tbl(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global)
785 * dumps the optimization counter
787 static void csv_dump_opt_cnt(dumper_t *dmp, const counter_t *tbl, unsigned len)
796 * initialize the simple dumper
798 static void csv_init(dumper_t *dmp, const char *name)
802 snprintf(fname, sizeof(fname), "%s.csv", name);
803 dmp->f = fopen(fname, "a");
809 * finishes the simple dumper
811 static void csv_finish(dumper_t *dmp)
819 * the simple human readable dumper
821 const dumper_t csv_dumper = {
832 FOURCC('C', 'S', 'V', '\0')