Added is_Const
[libfirm] / ir / stat / stat_dmp.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/ir/stat_dmp.c
4  * Purpose:     Statistics for Firm.
5  * Author:      Michael Beck
6  * Created:
7  * CVS-ID:      $Id$
8  * Copyright:   (c) 2004 Universität Karlsruhe
9  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
10  */
11 #ifdef HAVE_CONFIG_H
12 # include "config.h"
13 #endif
14
15 #include "stat_dmp.h"
16
17 /**
18  * names of the optimizations
19  */
20 static const char *opt_names[] = {
21   "straightening optimization",
22   "if simplification",
23   "constant evaluation",
24   "algebraic simplification",
25   "Phi optmization",
26   "Write-After-Write optimization",
27   "Write-After-Read optimization",
28   "Read-After-Write optimization",
29   "Read-After-Read optimization",
30   "Read-a-Const optimization",
31   "Tuple optimization",
32   "ID optimization",
33   "Common subexpression elimination",
34   "Strength reduction",
35   "Architecture dependant optimization",
36   "Reassociation optimization",
37   "Polymorphic call optimization",
38   "an if conversion was tried",
39   "Lowered",
40 };
41
42 static const char *if_conv_names[] = {
43   "if conv done             ",
44   "if conv side effect      ",
45   "if conv Phi node found   ",
46   "if conv to deep DAG's    ",
47   "if conv bad control flow ",
48 };
49
50 /**
51  * dumps a opcode hash into human readable form
52  */
53 static void simple_dump_opcode_hash(dumper_t *dmp, pset *set)
54 {
55   node_entry_t *entry;
56   counter_t f_alive;
57   counter_t f_new_node;
58   counter_t f_Id;
59
60   cnt_clr(&f_alive);
61   cnt_clr(&f_new_node);
62   cnt_clr(&f_Id);
63
64   fprintf(dmp->f, "%-16s %-8s %-8s %-8s\n", "Opcode", "alive", "created", "->Id");
65   for (entry = pset_first(set); entry; entry = pset_next(set)) {
66     fprintf(dmp->f, "%-16s %8u %8u %8u\n",
67       get_id_str(entry->op->name), entry->cnt_alive.cnt[0], entry->new_node.cnt[0], entry->into_Id.cnt[0]);
68
69     cnt_add(&f_alive,    &entry->cnt_alive);
70     cnt_add(&f_new_node, &entry->new_node);
71     cnt_add(&f_Id,       &entry->into_Id);
72   }
73   fprintf(dmp->f, "-------------------------------------------\n");
74   fprintf(dmp->f, "%-16s %8u %8u %8u\n", "Sum",
75      f_alive.cnt[0],
76      f_new_node.cnt[0],
77      f_Id.cnt[0]);
78 }
79
80 /**
81  * dumps an optimization hash into human readable form
82  */
83 static void simple_dump_opt_hash(dumper_t *dmp, pset *set, int index)
84 {
85   opt_entry_t *entry = pset_first(set);
86
87   if (entry) {
88     fprintf(dmp->f, "\n%s:\n", opt_names[index]);
89     fprintf(dmp->f, "%-16s %-8s\n", "Opcode", "deref");
90
91     for (; entry; entry = pset_next(set)) {
92       fprintf(dmp->f, "%-16s %8u\n",
93         get_id_str(entry->op->name), entry->count.cnt[0]);
94     }
95   }
96 }
97
98 /**
99  * dumps the number of real_function_call optimization
100  */
101 static void simple_dump_real_func_calls(dumper_t *dmp, counter_t *cnt)
102 {
103   if (! cnt_eq(cnt, 0)) {
104     fprintf(dmp->f, "\nReal Function Calls optimized:\n");
105     fprintf(dmp->f, "%-16s %8u\n",
106       "Call", cnt->cnt[0]);
107   }
108 }
109
110 /**
111  * dumps the number of tail_recursion optimization
112  */
113 static void simple_dump_tail_recursion(dumper_t *dmp, unsigned num_tail_recursion)
114 {
115   if (num_tail_recursion > 0) {
116     fprintf(dmp->f, "\nTail recursion optimized:\n");
117     fprintf(dmp->f, "%-16s %8u\n", "Call", num_tail_recursion);
118   }
119 }
120
121 /**
122  * dumps the edges count
123  */
124 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
125 {
126   fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt->cnt[0]);
127 }
128
129 /**
130  * dumps the IRG
131  */
132 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
133 {
134   int i, dump_opts = 1;
135   block_entry_t *b_entry;
136
137   if (entry->irg) {
138     ir_graph *const_irg = get_const_code_irg();
139
140     if (entry->irg == const_irg) {
141       fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
142     }
143     else {
144       if (entry->ent)
145         fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_name(entry->ent), (void *)entry->irg);
146       else
147         fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
148     }
149
150     fprintf(dmp->f, " %swalked %u over blocks %u:\n"
151                     " was inlined               : %u\n"
152                     " got inlined               : %u\n"
153                     " strength red              : %u\n"
154                     " leaf function             : %s\n"
155                     " calls only leaf functions : %s\n"
156                     " recursive                 : %s\n"
157                     " chain call                : %s\n"
158         " calls                     : %u\n"
159         " indirect calls            : %u\n",
160         entry->is_deleted ? "DELETED " : "",
161         entry->cnt_walked.cnt[0], entry->cnt_walked_blocks.cnt[0],
162         entry->cnt_was_inlined.cnt[0],
163         entry->cnt_got_inlined.cnt[0],
164               entry->cnt_strength_red.cnt[0],
165               entry->is_leaf ? "YES" : "NO",
166               entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
167               entry->is_recursive ? "YES" : "NO",
168               entry->is_chain_call ? "YES" : "NO",
169         entry->cnt_all_calls.cnt[0],
170         entry->cnt_indirect_calls.cnt[0]
171     );
172
173     for (i = 0; i < sizeof(entry->cnt_if_conv)/sizeof(entry->cnt_if_conv[0]); ++i) {
174       fprintf(dmp->f, " %s : %u\n", if_conv_names[i], entry->cnt_if_conv[i].cnt[0]);
175     }
176
177   }
178   else {
179     fprintf(dmp->f, "\nGlobals counts:\n");
180     fprintf(dmp->f, "--------------\n");
181     dump_opts = 0;
182   }
183
184   simple_dump_opcode_hash(dmp, entry->opcode_hash);
185   simple_dump_edges(dmp, &entry->cnt_edges);
186
187   /* effects of optimizations */
188   if (dump_opts) {
189     int i;
190
191     simple_dump_real_func_calls(dmp, &entry->cnt_real_func_call);
192     simple_dump_tail_recursion(dmp, entry->num_tail_recursion);
193
194     for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
195       simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
196     }
197
198     /* dump block info */
199     fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "Phi", "quot");
200     for (b_entry = pset_first(entry->block_hash);
201                b_entry;
202                b_entry = pset_next(entry->block_hash)) {
203       fprintf(dmp->f, "BLK %12ld %12u %12u %12u %12u %12u %4.8f\n",
204               b_entry->block_nr,
205               b_entry->cnt_nodes.cnt[0],
206               b_entry->cnt_edges.cnt[0],
207               b_entry->cnt_in_edges.cnt[0],
208               b_entry->cnt_out_edges.cnt[0],
209               b_entry->cnt_phi_data.cnt[0],
210               (double)b_entry->cnt_edges.cnt[0] / (double)b_entry->cnt_nodes.cnt[0]
211       );
212     }
213   }
214 }
215
216 /**
217  * initialize the simple dumper
218  */
219 static void simple_init(dumper_t *dmp, const char *name)
220 {
221   char fname[2048];
222
223   snprintf(fname, sizeof(fname), "%s.txt", name);
224   dmp->f = fopen(fname, "w");
225 }
226
227 /**
228  * finishes the simple dumper
229  */
230 static void simple_finish(dumper_t *dmp)
231 {
232   fclose(dmp->f);
233   dmp->f = NULL;
234 }
235
236 /**
237  * the simple human readable dumper
238  */
239 const dumper_t simple_dumper = {
240   simple_dump_graph,
241   simple_init,
242   simple_finish,
243   NULL,
244   NULL,
245   NULL,
246 };
247
248 /* ---------------------------------------------------------------------- */
249
250 /**
251  * count the nodes as needed:
252  *
253  * 1 normal (data) Phi's
254  * 2 memory Phi's
255  * 3 Proj
256  * 0 all other nodes
257  */
258 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
259 {
260   node_entry_t *entry;
261   int i;
262
263   for (i = 0; i < 4; ++i)
264     cnt_clr(&cnt[i]);
265
266   for (entry = pset_first(graph->opcode_hash); entry; entry = pset_next(graph->opcode_hash)) {
267     if (entry->op == op_Phi) {
268       /* normal Phi */
269       cnt_add(&cnt[1], &entry->cnt_alive);
270     }
271     else if (entry->op == dmp->status->op_PhiM) {
272       /* memory Phi */
273       cnt_add(&cnt[2], &entry->cnt_alive);
274     }
275     else if (entry->op == op_Proj) {
276       /* Proj */
277       cnt_add(&cnt[3], &entry->cnt_alive);
278     }
279     else {
280       /* all other nodes */
281       cnt_add(&cnt[0], &entry->cnt_alive);
282     }
283   }
284 }
285
286 /**
287  * dumps the IRG
288  */
289 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
290 {
291   const char *name;
292
293   counter_t cnt[4];
294
295   if (entry->irg && !entry->is_deleted) {
296     ir_graph *const_irg = get_const_code_irg();
297
298     if (entry->irg == const_irg) {
299       name = "<Const code Irg>";
300       return;
301     }
302     else {
303       if (entry->ent)
304         name = get_entity_name(entry->ent);
305       else
306         name = "<UNKNOWN IRG>";
307     }
308
309     csv_count_nodes(dmp, entry, cnt);
310
311     fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
312         name,
313         (void *)entry->irg,
314         cnt[0].cnt[0],
315         cnt[1].cnt[0],
316         cnt[2].cnt[0],
317         cnt[3].cnt[0]
318     );
319   }
320 }
321
322 /**
323  * initialize the simple dumper
324  */
325 static void csv_init(dumper_t *dmp, const char *name)
326 {
327   char fname[2048];
328
329   snprintf(fname, sizeof(fname), "%s.csv", name);
330   dmp->f = fopen(fname, "a");
331 }
332
333 /**
334  * finishes the simple dumper
335  */
336 static void csv_finish(dumper_t *dmp)
337 {
338   fclose(dmp->f);
339   dmp->f = NULL;
340 }
341
342 /**
343  * the simple human readable dumper
344  */
345 const dumper_t csv_dumper = {
346   csv_dump_graph,
347   csv_init,
348   csv_finish,
349   NULL,
350   NULL,
351   NULL,
352 };