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