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