be: inline arch_env_begin_codegeneration() into its only caller.
[libfirm] / ir / stat / firmstat_t.h
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
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.
10  *
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.
14  *
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
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief   Statistics for Firm. Internal data structures.
23  * @author  Michael Beck
24  */
25 #ifndef FIRM_STAT_FIRMSTAT_T_H
26 #define FIRM_STAT_FIRMSTAT_T_H
27
28 #include "firmstat.h"
29
30 #include "irop_t.h"
31 #include "irnode_t.h"
32 #include "irgraph_t.h"
33 #include "pset.h"
34 #include "pdeq.h"
35 #include "irprog.h"
36 #include "irgwalk.h"
37 #include "counter.h"
38 #include "irhooks.h"
39
40 /*
41  * just be make some things clear :-), the
42  * poor man "generics"
43  */
44 #define HASH_MAP(type) hmap_##type
45
46 typedef pset hmap_node_entry_t;
47 typedef pset hmap_graph_entry_t;
48 typedef pset hmap_opt_entry_t;
49 typedef pset hmap_block_entry_t;
50 typedef pset hmap_be_block_entry_t;
51 typedef pset hmap_reg_pressure_entry_t;
52 typedef pset hmap_perm_stat_entry_t;
53 typedef pset hmap_perm_class_entry_t;
54 typedef pset hmap_ir_op;
55 typedef pset hmap_distrib_entry_t;
56
57 /**
58  * Statistic options, can be or'ed.
59  */
60 enum firmstat_options_t {
61         FIRMSTAT_ENABLED         = 0x00000001,    /**< enable statistics */
62         FIRMSTAT_PATTERN_ENABLED = 0x00000002,    /**< enable pattern calculation */
63         FIRMSTAT_COUNT_STRONG_OP = 0x00000004,    /**< if set, count Mul/Div/Mod by constant */
64         FIRMSTAT_COUNT_DAG       = 0x00000008,    /**< if set, count DAG statistics */
65         FIRMSTAT_COUNT_DELETED   = 0x00000010,    /**< if set, count deleted graphs */
66         FIRMSTAT_COUNT_SELS      = 0x00000020,    /**< if set, count Sel(Sel(..)) differently */
67         FIRMSTAT_COUNT_CONSTS    = 0x00000040,    /**< if set, count Const statistics */
68         FIRMSTAT_CSV_OUTPUT      = 0x10000000     /**< CSV output of some mini-statistic */
69 };
70
71 /**
72  * Additional flags for statistics.
73  */
74 enum firmstat_optimizations_t {
75         FS_OPT_NEUTRAL_0  = HOOK_OPT_LAST,        /**< a op 0 = 0 op a = a */
76         FS_OPT_NEUTRAL_1,                         /**< a op 1 = 1 op a = a */
77         FS_OPT_ADD_A_A,                           /**< a + a = a * 2 */
78         FS_OPT_ADD_A_MINUS_B,                     /**< a + -b = a - b */
79         FS_OPT_ADD_SUB,                           /**< (a + x) - x = (a - x) + x */
80         FS_OPT_ADD_MUL_A_X_A,                     /**< a * x + a = a * (x + 1) */
81         FS_OPT_SUB_0_A,                           /**< 0 - a = -a */
82         FS_OPT_MINUS_SUB,                         /**< - (a - b) = b - a */
83         FS_OPT_SUB_MINUS,                         /**< a - (-b) = a + b */
84         FS_OPT_SUB_MUL_A_X_A,                     /**< a * x - a = a * (x - 1) */
85         FS_OPT_SUB_SUB_X_Y_Z,                     /**< (x - y) - z = x - (y + z) */
86         FS_OPT_SUB_C_NOT_X,                       /**< c - ~a = a + (c+1) */
87         FS_OPT_SUB_TO_ADD,                        /**< (-a) - b = -(a + b), a - (b - c) = a + (c - b), a - (b * C) -> a + (b * -C) */
88         FS_OPT_SUB_TO_NOT,                        /**< -1 - x -> ~x on two's complement */
89         FS_OPT_SUB_TO_CONV,                       /**< a - NULL = (int)a */
90         FS_OPT_MUL_MINUS,                         /**< (-a) * (b - c) -> a * (c - b) */
91         FS_OPT_MUL_MINUS_1,                       /**< a * -1 = -a */
92         FS_OPT_MINUS_MUL_C,                       /**< (-a) * C = a * (-C) */
93         FS_OPT_MUL_MINUS_MINUS,                   /**< (-a) * (-b) = a * b */
94         FS_OPT_OR,                                /**< a | a = a | 0 = 0 | a = a */
95         FS_OPT_AND,                               /**< a & 0b1...1 = 0b1...1 & a =  a & a = a */
96         FS_OPT_TO_EOR,                            /**< (a|b) & ~(a&b) = a^b */
97         FS_OPT_EOR_A_A,                           /**< a ^ a = 0 */
98         FS_OPT_EOR_A_B_A,                         /**< (a ^ b) ^ a = b */
99         FS_OPT_EOR_TO_NOT_BOOL,                   /**< bool ^ 1 = !bool */
100         FS_OPT_EOR_TO_NOT,                        /**< x ^ 0b1..1 = ~x, (a ^ b) & b -> ~a & b */
101         FS_OPT_NOT_CMP,                           /**< !(a cmp b) = a !cmp b */
102         FS_OPT_OR_SHFT_TO_ROTL,                   /**< (x << c) | (x >> (bits - c)) == Rotl(x, c) */
103         FS_OPT_REASSOC_SHIFT,                     /**< (x SHF c1) SHF c2 = x SHF (c1+c2) */
104         FS_OPT_SHIFT_AND,                         /**< (a SHF c) AND (b SHF c) = (a AND b) SHF c */
105         FS_OPT_SHIFT_OR,                          /**< (a SHF c) OR (b SHF c) = (a OR b) SHF c */
106         FS_OPT_SHIFT_EOR,                         /**< (a SHF c) XOR (b SHF c) = (a XOR b) SHF c */
107         FS_OPT_CONV,                              /**< a Conv could be removed */
108         FS_OPT_CAST,                              /**< a Cast could be removed */
109         FS_OPT_MIN_MAX_EQ,                        /**< Min(a,a) = Max(a,a) = a */
110         FS_OPT_MUX_COMBINE,                       /**< two Mux nodes where combined into one */
111         FS_OPT_MUX_CONV,                          /**< MuxI(sel, 1, 0) = (I)sel */
112         FS_OPT_MUX_BOOL,                          /**< Muxb(sel, true, false) = sel */
113         FS_OPT_MUX_NOT_BOOL,                      /**< Muxb(sel, false, true) = Not(sel) */
114         FS_OPT_MUX_OR_BOOL,                       /**< Muxb(sel, true, x) = Or(sel, x) */
115         FS_OPT_MUX_ORNOT_BOOL,                    /**< Muxb(sel, x, true) = Or(Not(sel), x) */
116         FS_OPT_MUX_AND_BOOL,                      /**< Muxb(sel, x, false) = And(sel, x) */
117         FS_OPT_MUX_ANDNOT_BOOL,                   /**< Muxb(sel, false, x) = And(Not(sel), x) */
118         FS_OPT_MUX_C,                             /**< Mux(C, f, t) = C ? t : f */
119         FS_OPT_MUX_EQ,                            /**< Mux(v, x, x) = x */
120         FS_OPT_MUX_TRANSFORM,                     /**< Mux(t ==/!= f, t, f) = f/t, Mux(t ==/!= 0, -t, t) = -t/t */
121         FS_OPT_MUX_TO_MIN,                        /**< Mux(a < b, a, b) = Min(a,b) */
122         FS_OPT_MUX_TO_MAX,                        /**< Mux(a > b, a, b) = Max(a,b) */
123         FS_OPT_MUX_TO_BITOP,                      /**< Mux((a & 2^x) ==/!= 0, 2^x, 0) = (a & 2^x) (xor 2^x) */
124         FS_OPT_INVOLUTION,                        /**< OP(OP(x)) = x */
125         FS_OPT_MINUS_NOT,                         /**< -(~x) = x + 1 */
126         FS_OPT_NOT_MINUS_1,                       /**< ~(x - 1) = -x */
127         FS_OPT_NOT_PLUS_1,                        /**< ~x + 1 = -x */
128         FS_OPT_ADD_X_NOT_X,                       /**< ~x + x = -1 */
129         FS_OPT_FP_INV_MUL,                        /**< x / y = x * (1.0/y) */
130         FS_OPT_CONST_PHI,                         /**< Constant evaluation on Phi */
131         FS_OPT_PREDICATE,                         /**< Predicate optimization */
132         FS_OPT_DEMORGAN,                          /**< optimization using DeMorgan's law */
133         FS_OPT_CMP_OP_OP,                         /**< CMP optimization: Cmp(OP(x), OP(y)) = Cmp(x, y) */
134         FS_OPT_CMP_OP_C,                          /**< CMP optimization: Cmp(OP(x), c1) = Cmp(x, c2) */
135         FS_OPT_CMP_CONV_CONV,                     /**< CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(x, y) */
136         FS_OPT_CMP_CONV,                          /**< CMP optimization: Cmp(Conv(x), Conv(y)) = Cmp(Conv(x), y) */
137         FS_OPT_CMP_TO_BOOL,                       /**< CMP optimization: Cmp(x, y) = BoolOP(x, y) */
138         FS_OPT_CMP_CNST_MAGN,                     /**< CMP optimization: reduced magnitude of a const */
139         FS_OPT_CMP_SHF_TO_AND,                    /**< CMP optimization: transformed shift into And */
140         FS_OPT_CMP_MOD_TO_AND,                    /**< CMP optimization: transformed Mod into And */
141         FS_OPT_NOP,                               /**< the operation is a NOP */
142         FS_OPT_GVN_FOLLOWER,                      /**< GVN-PRE: replaced a follower */
143         FS_OPT_GVN_FULLY,                         /**< GVN-PRE: replaced by fully redundant value */
144         FS_OPT_GVN_PARTLY,                        /**< GVN-PRE: replaced by partly redundant value */
145         FS_OPT_COMBO_CONST,                       /**< Combo: evaluated into Constant */
146         FS_OPT_COMBO_CF,                          /**< Combo: removed conditional control flow */
147         FS_OPT_COMBO_FOLLOWER,                    /**< Combo: replaced a follower */
148         FS_OPT_COMBO_CONGRUENT,                   /**< Combo: replaced by congruent */
149         FS_OPT_JUMPTHREADING,                     /**< Jump threading: removed conditional control flow */
150         FS_OPT_RTS_ABS,                           /**< RTS optimization: call to abs() replaced */
151         FS_OPT_RTS_ALLOCA,                        /**< RTS optimization: call to alloca() replaced */
152         FS_OPT_RTS_SQRT,                          /**< RTS optimization: call to sqrt() replaced */
153         FS_OPT_RTS_CBRT,                          /**< RTS optimization: call to cbrt() replaced */
154         FS_OPT_RTS_POW,                           /**< RTS optimization: call to pow() replaced */
155         FS_OPT_RTS_EXP,                           /**< RTS optimization: call to exp() replaced */
156         FS_OPT_RTS_LOG,                           /**< RTS optimization: call to log() replaced */
157         FS_OPT_RTS_SIN,                           /**< RTS optimization: call to sin() replaced */
158         FS_OPT_RTS_COS,                           /**< RTS optimization: call to cos() replaced */
159         FS_OPT_RTS_TAN,                           /**< RTS optimization: call to tan() replaced */
160         FS_OPT_RTS_ASIN,                          /**< RTS optimization: call to asin() replaced */
161         FS_OPT_RTS_ACOS,                          /**< RTS optimization: call to acos() replaced */
162         FS_OPT_RTS_ATAN,                          /**< RTS optimization: call to atan() replaced */
163         FS_OPT_RTS_SINH,                          /**< RTS optimization: call to sinh() replaced */
164         FS_OPT_RTS_COSH,                          /**< RTS optimization: call to cosh() replaced */
165         FS_OPT_RTS_TANH,                          /**< RTS optimization: call to tanh() replaced */
166         FS_OPT_RTS_SYMMETRIC,                     /**< RTS optimization: call to symmetric function f(-x) replaced by f(x) */
167         FS_OPT_RTS_STRCMP,                        /**< RTS optimization: call to strcmp() replaced */
168         FS_OPT_RTS_STRNCMP,                       /**< RTS optimization: call to strncmp() replaced */
169         FS_OPT_RTS_STRCPY,                        /**< RTS optimization: call to strcpy() replaced */
170         FS_OPT_RTS_STRLEN,                        /**< RTS optimization: call to strlen() replaced */
171         FS_OPT_RTS_MEMCPY,                        /**< RTS optimization: call to memcpy() replaced */
172         FS_OPT_RTS_MEMPCPY,                       /**< RTS optimization: call to mempcpy() replaced */
173         FS_OPT_RTS_MEMMOVE,                       /**< RTS optimization: call to memmove() replaced */
174         FS_OPT_RTS_MEMSET,                        /**< RTS optimization: call to memset() replaced */
175         FS_OPT_RTS_MEMCMP,                        /**< RTS optimization: call to memcmp() replaced */
176         FS_BE_IA32_LEA,                           /**< Lea was created */
177         FS_BE_IA32_LOAD_LEA,                      /**< Load merged with a Lea */
178         FS_BE_IA32_STORE_LEA,                     /**< Store merged with a Lea */
179         FS_BE_IA32_AM_S,                          /**< Source address mode node created */
180         FS_BE_IA32_AM_D,                          /**< Destination address mode node created */
181         FS_BE_IA32_CJMP,                          /**< CJmp created to save a cmp/test */
182         FS_BE_IA32_2ADDRCPY,                      /**< Copy created due to 2-Addresscode constraints */
183         FS_BE_IA32_SPILL2ST,                      /**< Created Store for a Spill */
184         FS_BE_IA32_RELOAD2LD,                     /**< Created Load for a Reload */
185         FS_BE_IA32_SUB2NEGADD,                    /**< Created Neg-Add for a Sub due to 2-Addresscode constraints */
186         FS_BE_IA32_LEA2ADD,                       /**< Transformed Lea back into Add */
187         FS_OPT_MAX
188 };
189
190 /**
191  * An entry in a distribution table
192  */
193 typedef struct distrib_entry_t {
194         counter_t   cnt;      /**< the current count */
195         const void *object;   /**< the object which is counted */
196 } distrib_entry_t;
197
198 /** The type of the hash function for objects in distribution tables. */
199 typedef unsigned (*distrib_hash_fun)(const void *object);
200
201 /**
202  * The distribution table.
203  */
204 typedef struct distrib_tbl_t {
205         struct obstack            cnts;       /**< obstack containing the distrib_entry_t entries */
206         HASH_MAP(distrib_entry_t) *hash_map;  /**< the hash map containing the distribution */
207         distrib_hash_fun          hash_func;  /**< the hash function for object in this distribution */
208         unsigned                  int_dist;   /**< non-zero, if it's a integer distribution */
209 } distrib_tbl_t;
210
211 /**
212  * possible address marker values
213  */
214 enum adr_marker_t {
215         MARK_ADDRESS_CALC     = 1,    /**< the node is an address expression */
216         MARK_REF_ADR          = 2,    /**< the node is referenced by an address expression */
217         MARK_REF_NON_ADR      = 4,    /**< the node is referenced by a non-address expression */
218 };
219
220 /**
221  * An entry in the address_mark set
222  */
223 typedef struct address_mark_entry_t {
224   ir_node  *node;               /**< the node which this entry belongs to, needed for compare */
225   unsigned mark;                /**< the mark, a bitmask of enum adr_marker_t */
226 } address_mark_entry_t;
227
228 /**
229  * An entry for ir_nodes, used in ir_graph statistics.
230  */
231 typedef struct node_entry_t {
232         counter_t   cnt_alive;    /**< amount of nodes in this entry */
233         counter_t   new_node;     /**< amount of new nodes for this entry */
234         counter_t   into_Id;      /**< amount of nodes that turned into Id's for this entry */
235         counter_t   normalized;   /**< amount of nodes that normalized for this entry */
236         const ir_op *op;          /**< the op for this entry */
237 } node_entry_t;
238
239 enum leaf_call_state_t {
240         LCS_UNKNOWN       = 0,      /**< state is unknown yet */
241         LCS_LEAF_CALL     = 1,      /**< only leaf functions will be called */
242         LCS_NON_LEAF_CALL = 2,      /**< at least one non-leaf function will be called or indetermined */
243 };
244
245 /**
246  * Graph counter indexes. The first one are accumulated once, the other are always deleted before an
247  * snapshot is taken.
248  */
249 enum graph_counter_names {
250         gcnt_acc_walked,               /**< walker walked over the graph, accumulated */
251         gcnt_acc_walked_blocks,        /**< walker walked over the graph blocks, accumulated */
252         gcnt_acc_was_inlined,          /**< number of times other graph were inlined, accumulated */
253         gcnt_acc_got_inlined,          /**< number of times this graph was inlined, accumulated */
254         gcnt_acc_strength_red,         /**< number of times strength reduction was successful on this graph, accumulated */
255         gcnt_acc_real_func_call,       /**< number real function call optimization, accumulated */
256
257         /* --- non-accumulated values from here */
258         _gcnt_non_acc,                 /**< first non-accumulated counter */
259
260         gcnt_edges = _gcnt_non_acc,    /**< number of DF edges in this graph */
261         gcnt_all_calls,                /**< number of all calls */
262         gcnt_call_with_cnst_arg,       /**< number of calls with const args */
263         gcnt_call_with_all_cnst_arg,   /**< number of calls with all const args */
264         gcnt_call_with_local_adr,      /**< number of calls with address of local var args */
265         gcnt_indirect_calls,           /**< number of indirect calls */
266         gcnt_external_calls,           /**< number of external calls */
267         gcnt_pure_adr_ops,             /**< number of pure address operation */
268         gcnt_all_adr_ops,              /**< number of all address operation */
269         gcnt_global_adr,               /**< number of global load/store addresses. */
270         gcnt_local_adr,                /**< number of local load/store addresses. */
271         gcnt_param_adr,                /**< number of parameter load/store addresses. */
272         gcnt_this_adr,                 /**< number of this load/store addresses. */
273         gcnt_other_adr,                /**< number of other load/store addresses. */
274         gcnt_if_conv,                  /**< number of if conversions */
275
276         /* --- must be the last enum constant --- */
277         _gcnt_last = gcnt_if_conv + IF_RESULT_LAST                 /**< number of counters */
278 };
279
280 /**
281  * An entry for ir_graphs. These numbers are calculated for every IR graph.
282  */
283 typedef struct graph_entry_t {
284         struct obstack             recalc_cnts;                  /**< obstack containing the counters that are recalculated */
285         HASH_MAP(node_entry_t)     *opcode_hash;                 /**< hash map containing the opcode counter */
286         HASH_MAP(block_entry_t)    *block_hash;                  /**< hash map containing the block counter */
287         HASH_MAP(be_block_entry_t) *be_block_hash;               /**< hash map containing backend block information */
288         counter_t                  cnt[_gcnt_last];               /**< counter */
289         unsigned                   num_tail_recursion;           /**< number of tail recursion optimizations */
290         HASH_MAP(opt_entry_t)      *opt_hash[FS_OPT_MAX];        /**< hash maps containing opcode counter for optimizations */
291         ir_graph                   *irg;                         /**< the graph of this object */
292         ir_entity                  *ent;                         /**< the entity of this graph if one exists */
293         set                        *address_mark;                /**< a set containing the address marks of the nodes */
294         unsigned                   is_deleted:1;                 /**< set if this irg was deleted */
295         unsigned                   is_leaf:1;                    /**< set, if this irg is a leaf function */
296         unsigned                   is_leaf_call:2;               /**< set, if this irg calls only leaf functions */
297         unsigned                   is_recursive:1;               /**< set, if this irg has recursive calls */
298         unsigned                   is_chain_call:1;              /**< set, if this irg is a chain call */
299         unsigned                   is_strict:1;                  /**< set, if this irg represents a strict program */
300         unsigned                   is_analyzed:1;                /**< helper: set, if this irg was already analysed */
301 } graph_entry_t;
302
303 /**
304  * An entry for optimized ir_nodes
305  */
306 typedef struct opt_entry_t {
307         counter_t   count;    /**< optimization counter */
308         const ir_op *op;      /**< the op for this entry */
309 } opt_entry_t;
310
311 /**
312  * An entry for register pressure.
313  */
314 typedef struct reg_pressure_entry_t {
315         const char *class_name; /**< name of the register class */
316         int         pressure;   /**< the register pressure for this class */
317 } reg_pressure_entry_t;
318
319 /**
320  * An entry for permutation statistics.
321  */
322 typedef struct perm_stat_entry_t {
323         ir_node       *perm;       /**< the perm node */
324         int            size;       /**< complete size */
325         int            real_size;  /**< number of pairs with different registers */
326         int            n_copies;   /**< number of copies created for lowering */
327         int            n_exchg;    /**< number of exchanges created for lowering */
328         distrib_tbl_t *cycles;     /**< distribution of cycle lengths */
329         distrib_tbl_t *chains;     /**< distribution of chain lengths */
330 } perm_stat_entry_t;
331
332 /**
333  * An entry for permutation statistics per class.
334  */
335 typedef struct perm_class_entry_t {
336         const char                  *class_name; /**< name of the register class */
337         int                          n_regs;     /**< number of register in this class */
338         HASH_MAP(perm_stat_entry_t) *perm_stat;  /**< statistics about all perm nodes of this class */
339 } perm_class_entry_t;
340
341 /**
342  * An entry for a block or extended block in a ir-graph
343  */
344 typedef struct be_block_entry_t {
345         long                           block_nr;         /**< block nr */
346         distrib_tbl_t                  *sched_ready;     /**< distribution of ready nodes per block */
347         /**< the highest register pressures for this block for each register class */
348         HASH_MAP(reg_pressure_entry_t) *reg_pressure;
349         HASH_MAP(perm_class_entry_t)   *perm_class_stat; /**< statistics about perm nodes for each register class */
350 } be_block_entry_t;
351
352 /**
353  * Block counter indexes. The first one are accumulated once, the other are always deleted before an
354  * snapshot is taken.
355  */
356 enum block_counter_names {
357         bcnt_nodes,     /**< the counter of nodes in this block */
358         bcnt_edges,     /**< the counter of edges in this block */
359         bcnt_in_edges,  /**< the counter of edges incoming from other blocks to this block */
360         bcnt_out_edges, /**< the counter of edges outgoing from this block to other blocks */
361         bcnt_phi_data,  /**< the counter of data Phi nodes in this block */
362
363         /* --- must be the last enum constant --- */
364         _bcnt_last      /**< number of counters */
365 };
366
367 /**
368  * An entry for a block or extended block in a ir-graph
369  */
370 typedef struct block_entry_t {
371         counter_t       cnt[_bcnt_last];  /**< counter */
372         long            block_nr;         /**< block nr */
373         unsigned        is_start:1;       /**< set, if it's the Start block. */
374         unsigned        is_end:1;         /**< set, if it's the End block. */
375 } block_entry_t;
376
377 /**
378  * Some potential interesting float values
379  */
380 typedef enum float_classify_t {
381         STAT_FC_0,                /**< the float value 0.0 */
382         STAT_FC_1,                /**< the float value 1.0 */
383         STAT_FC_2,                /**< the float value 2.0 */
384         STAT_FC_0_5,              /**< the float value 0.5 */
385         STAT_FC_POWER_OF_TWO,     /**< another 2^x value */
386         STAT_FC_OTHER,            /**< all other values */
387         STAT_FC_MAX               /**< last value */
388 } float_classify_t;
389
390 /**
391  * constant info
392  */
393 typedef struct constant_info_t {
394         counter_t  int_bits_count[32];  /**< distribution of bit sizes of integer constants */
395         counter_t  floats[STAT_FC_MAX]; /**< floating point constants */
396         counter_t  others;              /**< all other constants */
397 } constant_info_t;
398
399 /** forward */
400 typedef struct dumper_t dumper_t;
401
402 /**
403  * handler for dumping an IRG
404  *
405  * @param dmp   the dumper
406  * @param entry the IR-graph hash map entry
407  */
408 typedef void dump_graph_FUNC(dumper_t *dmp, graph_entry_t *entry);
409
410 /**
411  * handler for dumper a constant info table
412  *
413  * @param dmp   the dumper
414  */
415 typedef void dump_const_table_FUNC(dumper_t *dmp, const constant_info_t *tbl);
416
417 /**
418  * dumps the parameter distribution table
419  */
420 typedef void dump_param_tbl_FUNC(dumper_t *dmp, const distrib_tbl_t *tbl, graph_entry_t *global);
421
422 /**
423  * dumps the optimizations counter
424  */
425 typedef void dump_opt_cnt_FUNC(dumper_t *dumper, const counter_t *tbl, unsigned len);
426
427 /**
428  * handler for dumper init
429  *
430  * @param dmp   the dumper
431  * @param name  name of the file to dump to
432  */
433 typedef void dump_init_FUNC(dumper_t *dmp, const char *name);
434
435 /**
436  * handler for dumper finish
437  *
438  * @param dmp   the dumper
439  */
440 typedef void dump_finish_FUNC(dumper_t *dmp);
441
442 /**
443  * statistics info
444  */
445 typedef struct statistic_info_t {
446         unsigned                stat_options;        /**< statistic options: field must be first */
447         struct obstack          cnts;                /**< obstack containing the counters that are incremented */
448         struct obstack          be_data;             /**< obstack containing backend statistics data */
449         HASH_MAP(graph_entry_t) *irg_hash;           /**< hash map containing the counter for irgs */
450         HASH_MAP(ir_op)         *ir_op_hash;         /**< hash map containing all ir_ops (accessible by op_codes) */
451         pdeq                    *wait_q;             /**< wait queue for leaf call decision */
452         unsigned                recursive:1;         /**< flag for detecting recursive hook calls */
453         unsigned                in_dead_node_elim:1; /**< flag for dead node elimination runs */
454         ir_op                   *op_Phi0;            /**< pseudo op for Phi0 */
455         ir_op                   *op_PhiM;            /**< pseudo op for memory Phi */
456         ir_op                   *op_ProjM;           /**< pseudo op for memory Proj */
457         ir_op                   *op_MulC;            /**< pseudo op for multiplication by const */
458         ir_op                   *op_DivC;            /**< pseudo op for division by const */
459         ir_op                   *op_ModC;            /**< pseudo op for modulo by const */
460         ir_op                   *op_SelSel;          /**< pseudo op for Sel(Sel) */
461         ir_op                   *op_SelSelSel;       /**< pseudo op for Sel(Sel(Sel)) */
462         dumper_t                *dumper;             /**< list of dumper */
463         int                     reassoc_run;         /**< if set, reassociation is running */
464         constant_info_t         const_info;          /**< statistic info for constants */
465         distrib_tbl_t           *dist_param_cnt;     /**< distribution table for call parameters */
466
467         counter_t               num_opts[FS_OPT_MAX];/**< count optimizations */
468 } stat_info_t;
469
470 /**
471  * a dumper description
472  */
473 struct dumper_t {
474         dump_graph_FUNC       *dump_graph;     /**< handler for dumping an irg */
475         dump_const_table_FUNC *dump_const_tbl; /**< handler for dumping a const table */
476         dump_param_tbl_FUNC   *dump_param_tbl; /**< handler for dumping the Call parameter table */
477         dump_opt_cnt_FUNC     *dump_opt_cnt;   /**< handler for dumping the optimization table. */
478         dump_init_FUNC        *init;           /**< handler for init */
479         dump_finish_FUNC      *finish;         /**< handler for finish */
480         FILE                  *f;             /**< the file to dump to */
481         stat_info_t           *status;        /**< access to the global status */
482         dumper_t              *next;          /**< link to the next dumper */
483         pset                  *func_map;      /**< pset containing all registered functions */
484         unsigned               tag;            /**< the id tag of the dumper */
485 };
486
487 /**
488  * internal init function, mainly registers commandline arguments.
489  * (The use still has to call firm_init_stat() later
490  */
491 void init_stat(void);
492
493 /**
494  * helper: get an ir_op from an opcode
495  */
496 ir_op *stat_get_op_from_opcode(unsigned code);
497
498 /* API for distribution tables */
499
500 /**
501  * creates a new distribution table.
502  *
503  * @param cmp_func   Compare function for objects in the distribution
504  * @param hash_func  Hash function for objects in the distribution
505  */
506 distrib_tbl_t *stat_new_distrib_tbl(pset_cmp_fun cmp_func, distrib_hash_fun hash_func);
507
508 /**
509  * creates a new distribution table for an integer distribution.
510  */
511 distrib_tbl_t *stat_new_int_distrib_tbl(void);
512
513 /**
514  * destroys a distribution table.
515  */
516 void stat_delete_distrib_tbl(distrib_tbl_t *tbl);
517
518 /**
519  * adds a new object count into the distribution table.
520  */
521 void stat_add_distrib_tbl(distrib_tbl_t *tbl, const void *object, const counter_t *cnt);
522
523 /**
524  * adds a new key count into the integer distribution table.
525  */
526 void stat_add_int_distrib_tbl(distrib_tbl_t *tbl, int key, const counter_t *cnt);
527
528 /**
529  * increases object count by one
530  */
531 void stat_inc_distrib_tbl(distrib_tbl_t *tbl, const void *object);
532
533 /**
534  * increases key count by one
535  */
536 void stat_inc_int_distrib_tbl(distrib_tbl_t *tbl, int key);
537
538 /**
539  * inserts a new object with count 0 into the distribution table
540  * if object is already present, nothing happens
541  */
542 void stat_insert_distrib_tbl(distrib_tbl_t *tbl, const void *object);
543
544 /**
545  * inserts a new key with count 0 into the integer distribution table
546  * if key is already present, nothing happens
547  */
548 void stat_insert_int_distrib_tbl(distrib_tbl_t *tbl, int key);
549
550 /**
551  * returns the sum over all counters in a distribution table
552  */
553 int stat_get_count_distrib_tbl(distrib_tbl_t *tbl);
554
555 /**
556  * calculates the mean value of a distribution.
557  */
558 double stat_calc_mean_distrib_tbl(distrib_tbl_t *tbl);
559
560 /**
561  * calculates the average value of a distribution
562  */
563 double stat_calc_avg_distrib_tbl(distrib_tbl_t *tbl);
564
565 /** evaluates each entry of a distribution table. */
566 typedef void (*eval_distrib_entry_fun)(const distrib_entry_t *entry, void *env);
567
568 /**
569  * iterates over all entries in a distribution table
570  */
571 void stat_iterate_distrib_tbl(const distrib_tbl_t *tbl, eval_distrib_entry_fun eval, void *env);
572
573 /**
574  * update info on Consts.
575  *
576  * @param node   The Const node
577  * @param graph  The graph entry containing the call
578  */
579 void stat_update_const(stat_info_t *status, ir_node *node, graph_entry_t *graph);
580
581 /**
582  * clears the const statistics for a new snapshot.
583  */
584 void stat_const_clear(stat_info_t *status);
585
586 /**
587  * initialize the Const statistic.
588  */
589 void stat_init_const_cnt(stat_info_t *status);
590
591 /**
592  * return a human readable name for an float classification
593  */
594 const char *stat_fc_name(float_classify_t classification);
595
596 /**
597  * Update the register pressure of a block
598  *
599  * @param irg        the irg containing the block
600  * @param block      the block for which the reg pressure should be set
601  * @param pressure   the pressure
602  * @param class_name the name of the register class
603  */
604 void stat_be_block_regpressure(ir_graph *irg, ir_node *block, int pressure, const char *class_name);
605
606 /**
607  * Update the distribution of ready nodes of a block
608  *
609  * @param irg        the irg containing the block
610  * @param block      the block for which the reg pressure should be set
611  * @param num_ready  the number of ready nodes
612  */
613 void stat_be_block_sched_ready(ir_graph *irg, ir_node *block, int num_ready);
614
615 /**
616  * Update the permutation statistic of a block
617  *
618  * @param class_name the name of the register class
619  * @param perm       the perm node
620  * @param block      the block containing the perm
621  * @param size       the size of the perm
622  * @param real_size  number of pairs with different registers
623  */
624 void stat_be_block_stat_perm(const char *class_name, int n_regs, ir_node *perm, ir_node *block,
625                              int size, int real_size);
626
627 /**
628  * Update the permutation statistic of a single perm
629  *
630  * @param class_name the name of the register class
631  * @param perm       the perm node
632  * @param block      the block containing the perm
633  * @param is_chain   1 if chain, 0 if cycle
634  * @param size       length of the cycle/chain
635  * @param n_ops      the number of ops representing this cycle/chain after lowering
636  */
637 void stat_be_block_stat_permcycle(const char *class_name, ir_node *perm, ir_node *block,
638                                   int is_chain, int size, int n_ops);
639
640 /**
641  * Register an additional function for all dumper.  This function
642  * is called in dump_snapshot once for each graph_entry and dumper.
643  *
644  * @param func  the dump function to register
645  */
646 void stat_register_dumper_func(dump_graph_FUNC *func);
647
648 #endif /* FIRM_STAT_FIRMSTAT_T_H */