added missing parentesis
[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 %8d %8d %8d\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 %8d %8d %8d\n", "Sum",
75      f_alive.cnt[0],
76      f_new_node.cnt[0],
77      f_Id.cnt[0]);
78 }
79
80 /**
81  * dumps a 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 %8d\n",
93         get_id_str(entry->op->name), entry->count.cnt[0]);
94     }
95   }
96 }
97
98 /**
99  * dumps the edges count
100  */
101 static void simple_dump_edges(dumper_t *dmp, counter_t *cnt)
102 {
103   fprintf(dmp->f, "%-16s %8d\n", "Edges", cnt->cnt[0]);
104 }
105
106 /**
107  * dumps the IRG
108  */
109 static void simple_dump_graph(dumper_t *dmp, graph_entry_t *entry)
110 {
111   int i, dump_opts = 1;
112   block_entry_t *b_entry;
113
114   if (entry->irg) {
115     ir_graph *const_irg = get_const_code_irg();
116
117     if (entry->irg == const_irg) {
118       fprintf(dmp->f, "\nConst code Irg %p", (void *)entry->irg);
119     }
120     else {
121       if (entry->ent)
122         fprintf(dmp->f, "\nEntity %s, Irg %p", get_entity_name(entry->ent), (void *)entry->irg);
123       else
124         fprintf(dmp->f, "\nIrg %p", (void *)entry->irg);
125     }
126
127     fprintf(dmp->f, " %swalked %u over blocks %u:\n"
128                     " was inlined               : %u\n"
129                     " got inlined               : %u\n"
130                     " strength red              : %u\n"
131                     " leaf function             : %s\n"
132                     " calls only leaf functions : %s\n"
133                     " recursive                 : %s\n"
134                     " chain call                : %s\n"
135                     " calls                     : %u\n"
136                     " indirect calls            : %u\n",
137         entry->is_deleted ? "DELETED " : "",
138         entry->cnt_walked.cnt[0], entry->cnt_walked_blocks.cnt[0],
139         entry->cnt_was_inlined.cnt[0],
140         entry->cnt_got_inlined.cnt[0],
141               entry->cnt_strength_red.cnt[0],
142               entry->is_leaf ? "YES" : "NO",
143               entry->is_leaf_call == LCS_NON_LEAF_CALL ? "NO" : (entry->is_leaf_call == LCS_LEAF_CALL ? "Yes" : "Maybe"),
144               entry->is_recursive ? "YES" : "NO",
145               entry->is_chain_call ? "YES" : "NO",
146         entry->cnt_all_calls.cnt[0],
147         entry->cnt_indirect_calls.cnt[0]
148     );
149
150     for (i = 0; i < sizeof(entry->cnt_if_conv)/sizeof(entry->cnt_if_conv[0]); ++i) {
151       fprintf(dmp->f, " %s : %u\n", if_conv_names[i], entry->cnt_if_conv[i].cnt[0]);
152     }
153
154   }
155   else {
156     fprintf(dmp->f, "\nGlobals counts:\n");
157     fprintf(dmp->f, "--------------\n");
158     dump_opts = 0;
159   }
160
161   simple_dump_opcode_hash(dmp, entry->opcode_hash);
162   simple_dump_edges(dmp, &entry->cnt_edges);
163
164   /* effects of optimizations */
165   if (dump_opts) {
166     int i;
167
168     for (i = 0; i < sizeof(entry->opt_hash)/sizeof(entry->opt_hash[0]); ++i) {
169       simple_dump_opt_hash(dmp, entry->opt_hash[i], i);
170     }
171
172     /* dump block info */
173     fprintf(dmp->f, "\n%12s %12s %12s %12s %12s %12s\n", "Block Nr", "Nodes", "intern E", "incoming E", "outgoing E", "quot");
174     for (b_entry = pset_first(entry->block_hash);
175          b_entry;
176          b_entry = pset_next(entry->block_hash)) {
177       fprintf(dmp->f, "BLK %12ld %12u %12u %12u %12u %4.8f\n",
178           b_entry->block_nr,
179           b_entry->cnt_nodes.cnt[0],
180           b_entry->cnt_edges.cnt[0],
181           b_entry->cnt_in_edges.cnt[0],
182           b_entry->cnt_out_edges.cnt[0],
183           (double)b_entry->cnt_edges.cnt[0] / (double)b_entry->cnt_nodes.cnt[0]
184       );
185     }
186   }
187 }
188
189 /**
190  * initialize the simple dumper
191  */
192 static void simple_init(dumper_t *dmp, const char *name)
193 {
194   char fname[2048];
195
196   snprintf(fname, sizeof(fname), "%s.txt", name);
197   dmp->f = fopen(fname, "w");
198 }
199
200 /**
201  * finishes the simple dumper
202  */
203 static void simple_finish(dumper_t *dmp)
204 {
205   fclose(dmp->f);
206   dmp->f = NULL;
207 }
208
209 /**
210  * the simple human readable dumper
211  */
212 const dumper_t simple_dumper = {
213   simple_dump_graph,
214   simple_init,
215   simple_finish,
216   NULL,
217   NULL,
218   NULL,
219 };
220
221 /* ---------------------------------------------------------------------- */
222
223 /**
224  * count the nodes as needed:
225  *
226  * 1 normal (data) Phi's
227  * 2 memory Phi's
228  * 3 Proj
229  * 0 all other nodes
230  */
231 static void csv_count_nodes(dumper_t *dmp, graph_entry_t *graph, counter_t cnt[])
232 {
233   node_entry_t *entry;
234   int i;
235
236   for (i = 0; i < 4; ++i)
237     cnt_clr(&cnt[i]);
238
239   for (entry = pset_first(graph->opcode_hash); entry; entry = pset_next(graph->opcode_hash)) {
240     if (entry->op == op_Phi) {
241       /* normal Phi */
242       cnt_add(&cnt[1], &entry->cnt_alive);
243     }
244     else if (entry->op == dmp->status->op_PhiM) {
245       /* memory Phi */
246       cnt_add(&cnt[2], &entry->cnt_alive);
247     }
248     else if (entry->op == op_Proj) {
249       /* Proj */
250       cnt_add(&cnt[3], &entry->cnt_alive);
251     }
252     else {
253       /* all other nodes */
254       cnt_add(&cnt[0], &entry->cnt_alive);
255     }
256   }
257 }
258
259 /**
260  * dumps the IRG
261  */
262 static void csv_dump_graph(dumper_t *dmp, graph_entry_t *entry)
263 {
264   const char *name;
265
266   counter_t cnt[4];
267
268   if (entry->irg && !entry->is_deleted) {
269     ir_graph *const_irg = get_const_code_irg();
270
271     if (entry->irg == const_irg) {
272       name = "<Const code Irg>";
273       return;
274     }
275     else {
276       if (entry->ent)
277         name = get_entity_name(entry->ent);
278       else
279         name = "<UNKNOWN IRG>";
280     }
281
282     csv_count_nodes(dmp, entry, cnt);
283
284     fprintf(dmp->f, "%-40s, %p, %d, %d, %d, %d\n",
285         name,
286         (void *)entry->irg,
287         cnt[0].cnt[0],
288         cnt[1].cnt[0],
289         cnt[2].cnt[0],
290         cnt[3].cnt[0]
291     );
292   }
293 }
294
295 /**
296  * initialize the simple dumper
297  */
298 static void csv_init(dumper_t *dmp, const char *name)
299 {
300   char fname[2048];
301
302   snprintf(fname, sizeof(fname), "%s.csv", name);
303   dmp->f = fopen(fname, "a");
304 }
305
306 /**
307  * finishes the simple dumper
308  */
309 static void csv_finish(dumper_t *dmp)
310 {
311   fclose(dmp->f);
312   dmp->f = NULL;
313 }
314
315 /**
316  * the simple human readable dumper
317  */
318 const dumper_t csv_dumper = {
319   csv_dump_graph,
320   csv_init,
321   csv_finish,
322   NULL,
323   NULL,
324   NULL,
325 };