Correct comment: xvcg wants LF, not CR.
[libfirm] / ir / ir / irprofile.c
1 /*
2  * Copyright (C) 1995-2011 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       Code instrumentation and execution count profiling.
23  * @author      Adam M. Szalkowski, Steven Schaefer
24  * @date        06.04.2006, 11.11.2010
25  */
26 #include "config.h"
27
28 #include <math.h>
29 #include <stdio.h>
30
31 #include "hashptr.h"
32 #include "debug.h"
33 #include "obst.h"
34 #include "xmalloc.h"
35 #include "set.h"
36 #include "irtools.h"
37
38 #include "irgwalk.h"
39 #include "irdump_t.h"
40 #include "irnode_t.h"
41 #include "ircons_t.h"
42 #include "execfreq.h"
43 #include "typerep.h"
44
45 #include "irprofile.h"
46
47 /* Instrument blocks walker. */
48 typedef struct block_id_walker_data_t {
49         unsigned int id;   /**< current block id number */
50         ir_node *symconst; /**< the SymConst representing the counter array */
51 } block_id_walker_data_t;
52
53 /* Associate counters with blocks. */
54 typedef struct block_assoc_t {
55         unsigned int i;          /**< current block id number */
56         unsigned int *counters;  /**< block execution counts */
57 } block_assoc_t;
58
59 typedef struct intialize_execfreq_env_t {
60         ir_graph *irg;
61         ir_exec_freq *execfreqs;
62         double freq_factor;
63 } initialize_execfreq_env_t;
64
65 /* minimal execution frequency (an execfreq of 0 confuses algos) */
66 #define MIN_EXECFREQ 0.00001
67
68 /* keep the execcounts here because they are only read once per compiler run */
69 static set *profile = NULL;
70
71 /* Hook for vcg output. */
72 static void *hook;
73
74 /* The debug module handle. */
75 DEBUG_ONLY(static firm_dbg_module_t *dbg;)
76
77 /* Since the backend creates a new firm graph we cannot associate counts with
78  * blocks directly. Instead we associate them with the block ids, which are
79  * maintained.
80  */
81 typedef struct execcount_t {
82         unsigned long block; /**< block id */
83         unsigned int  count; /**< execution count */
84 } execcount_t;
85
86 /**
87  * Compare two execcount_t entries.
88  */
89 static int cmp_execcount(const void *a, const void *b, size_t size)
90 {
91         const execcount_t *ea = (const execcount_t*)a;
92         const execcount_t *eb = (const execcount_t*)b;
93         (void) size;
94         return ea->block != eb->block;
95 }
96
97 /**
98  * Block walker, count number of blocks.
99  */
100 static void block_counter(ir_node *bb, void *data)
101 {
102         unsigned *count = (unsigned*) data;
103         (void) bb;
104         ++(*count);
105 }
106
107 /**
108  * Returns the number of blocks the given graph.
109  */
110 static unsigned int get_irg_n_blocks(ir_graph *irg)
111 {
112         unsigned int count = 0;
113         irg_block_walk_graph(irg, block_counter, NULL, &count);
114         return count;
115 }
116
117 /**
118  * Returns the number of basic blocks in the current ir program.
119  */
120 static unsigned int get_irp_n_blocks(void)
121 {
122         int i, n = get_irp_n_irgs();
123         unsigned int count = 0;
124
125         for (i = 0; i < n; i++) {
126                 ir_graph *irg = get_irp_irg(i);
127                 count += get_irg_n_blocks(irg);
128         }
129
130         return count;
131 }
132
133 /* vcg helper */
134 static void dump_profile_node_info(void *ctx, FILE *f, const ir_node *irn)
135 {
136         (void) ctx;
137         if (is_Block(irn)) {
138                 unsigned int execcount = ir_profile_get_block_execcount(irn);
139                 fprintf(f, "profiled execution count: %u\n", execcount);
140         }
141 }
142
143 /**
144  * Add the given method entity as a constructor.
145  */
146 static void add_constructor(ir_entity *method)
147 {
148     ir_type   *method_type  = get_entity_type(method);
149     ir_type   *ptr_type     = new_type_pointer(method_type);
150
151     ir_type   *constructors = get_segment_type(IR_SEGMENT_CONSTRUCTORS);
152         ident     *ide = id_unique("constructor_ptr.%u");
153     ir_entity *ptr = new_entity(constructors, ide, ptr_type);
154     ir_graph  *irg = get_const_code_irg();
155     ir_node   *val = new_rd_SymConst_addr_ent(NULL, irg, mode_P_code, method);
156
157         set_entity_ld_ident(ptr, new_id_from_chars("", 0));
158     set_entity_compiler_generated(ptr, 1);
159     set_entity_linkage(ptr, IR_LINKAGE_CONSTANT | IR_LINKAGE_HIDDEN_USER);
160     set_entity_visibility(ptr, ir_visibility_private);
161     set_atomic_ent_value(ptr, val);
162 }
163
164 /**
165  * Returns an entity representing the __init_firmprof function from libfirmprof
166  * This is the equivalent of:
167  * extern void __init_firmprof(char *filename, uint *counters, uint size)
168  */
169 static ir_entity *get_init_firmprof_ref(void)
170 {
171         ident   *init_name = new_id_from_str("__init_firmprof");
172         ir_type *init_type = new_type_method(3, 0);
173         ir_type *uint      = new_type_primitive(mode_Iu);
174         ir_type *uintptr   = new_type_pointer(uint);
175         ir_type *string    = new_type_pointer(new_type_primitive(mode_Bs));
176         ir_entity *result;
177
178         set_method_param_type(init_type, 0, string);
179         set_method_param_type(init_type, 1, uintptr);
180         set_method_param_type(init_type, 2, uint);
181
182         result = new_entity(get_glob_type(), init_name, init_type);
183         set_entity_visibility(result, ir_visibility_external);
184
185         return result;
186 }
187
188 /**
189  * Generates a new irg which calls the initializer
190  *
191  * Pseudocode:
192  *    static void __firmprof_initializer(void) __attribute__ ((constructor))
193  *    {
194  *        __init_firmprof(ent_filename, bblock_counts, n_blocks);
195  *    }
196  */
197 static ir_graph *gen_initializer_irg(ir_entity *ent_filename,
198                                      ir_entity *bblock_counts, int n_blocks)
199 {
200         ir_graph *irg;
201         ir_node  *ins[3];
202         ir_node  *bb, *ret, *call, *symconst;
203         ir_type  *empty_frame_type;
204         symconst_symbol sym;
205
206         ir_entity *init_ent = get_init_firmprof_ref();
207
208         ident     *name = new_id_from_str("__firmprof_initializer");
209         ir_entity *ent  = new_entity(get_glob_type(), name, new_type_method(0, 0));
210         set_entity_visibility(ent, ir_visibility_local);
211         set_entity_ld_ident(ent, name);
212
213         /* create the new ir_graph */
214         irg = new_ir_graph(ent, 0);
215         set_current_ir_graph(irg);
216         empty_frame_type = get_irg_frame_type(irg);
217         set_type_size_bytes(empty_frame_type, 0);
218         set_type_state(empty_frame_type, layout_fixed);
219
220         bb = get_r_cur_block(irg);
221
222         sym.entity_p = init_ent;
223         symconst     = new_r_SymConst(irg, mode_P_data, sym, symconst_addr_ent);
224
225         sym.entity_p = ent_filename;
226         ins[0] = new_r_SymConst(irg, mode_P_data, sym, symconst_addr_ent);
227         sym.entity_p = bblock_counts;
228         ins[1] = new_r_SymConst(irg, mode_P_data, sym, symconst_addr_ent);
229         ins[2] = new_r_Const_long(irg, mode_Iu, n_blocks);
230
231         call = new_r_Call(bb, get_irg_initial_mem(irg), symconst, 3, ins,
232                 get_entity_type(init_ent));
233         ret  = new_r_Return(bb, new_r_Proj(call, mode_M, pn_Call_M), 0, NULL);
234         mature_immBlock(bb);
235
236         add_immBlock_pred(get_irg_end_block(irg), ret);
237         mature_immBlock(get_irg_end_block(irg));
238
239         irg_finalize_cons(irg);
240
241         /* add a pointer to the new function in the constructor section */
242         add_constructor(ent);
243
244         return irg;
245 }
246
247 /**
248  * Instrument a block with code needed for profiling.
249  * This just inserts the instruction nodes, it doesn't connect the memory
250  * nodes in a meaningful way.
251  */
252 static void instrument_block(ir_node *bb, ir_node *address, unsigned int id)
253 {
254         ir_graph *irg = get_irn_irg(bb);
255         ir_node  *load, *store, *offset, *add, *projm, *proji, *unknown, *cnst;
256
257         /* We can't instrument the end block */
258         if (bb == get_irg_end_block(irg))
259                 return;
260
261         unknown = new_r_Unknown(irg, mode_M);
262         cnst    = new_r_Const_long(irg, mode_Iu, get_mode_size_bytes(mode_Iu) * id);
263         offset  = new_r_Add(bb, address, cnst, get_modeP_data());
264         load    = new_r_Load(bb, unknown, offset, mode_Iu, cons_none);
265         projm   = new_r_Proj(load, mode_M, pn_Load_M);
266         proji   = new_r_Proj(load, mode_Iu, pn_Load_res);
267         cnst    = new_r_Const(irg, get_mode_one(mode_Iu));
268         add     = new_r_Add(bb, proji, cnst, mode_Iu);
269         store   = new_r_Store(bb, projm, offset, add, cons_none);
270         projm   = new_r_Proj(store, mode_M, pn_Store_M);
271
272         set_irn_link(bb, projm);
273         set_irn_link(projm, load);
274 }
275
276 /**
277  * SSA Construction for instrumentation code memory.
278  *
279  * This introduces a new memory node and connects it to the instrumentation
280  * codes, inserting phiM nodes as necessary. Note that afterwards, the new
281  * memory is not connected to any return nodes and thus still dead.
282  */
283 static void fix_ssa(ir_node *bb, void *data)
284 {
285         ir_graph *irg = get_irn_irg(bb);
286         ir_node *mem, *proj, *load;
287         int n, arity = get_Block_n_cfgpreds(bb);
288
289         (void) data;
290
291         /* end blocks are not instrumented, skip! */
292         if (bb == get_irg_end_block(irg))
293                 return;
294
295         if (bb == get_irg_start_block(irg)) {
296                 mem = get_irg_initial_mem(irg);
297         } else if (arity == 1) {
298                 ir_node *pred = get_Block_cfgpred_block(bb, 0);
299                 if (!is_Bad(pred))
300                         mem = (ir_node*) get_irn_link(pred);
301                 else
302                         mem = new_r_NoMem(irg);
303         } else {
304                 ir_node **ins = ALLOCAN(ir_node*, arity);
305                 for (n = arity - 1; n >= 0; --n) {
306                         ir_node *pred = get_Block_cfgpred_block(bb, n);
307                         if (!is_Bad(pred))
308                                 ins[n] = (ir_node*) get_irn_link(pred);
309                         else
310                                 ins[n] = new_r_NoMem(irg);
311                 }
312                 mem = new_r_Phi(bb, arity, ins, mode_M);
313         }
314
315         /* The block link fields point to the projm from the instrumentation code,
316          * the projm in turn links to the initial load which lacks a memory
317          * argument at this point. */
318         proj = (ir_node*) get_irn_link(bb);
319         load = (ir_node*) get_irn_link(proj);
320         set_Load_mem(load, mem);
321 }
322
323 /**
324  * Instrument a single block.
325  */
326 static void block_instrument_walker(ir_node *bb, void *data)
327 {
328         block_id_walker_data_t *wd = (block_id_walker_data_t*)data;
329         instrument_block(bb, wd->symconst, wd->id);
330         ++wd->id;
331 }
332
333 /**
334  * Synchronize the original memory input of node with the additional operand
335  * from the profiling code.
336  */
337 static ir_node *sync_mem(ir_node *bb, ir_node *mem)
338 {
339         ir_node *ins[2];
340         ins[0] = (ir_node*) get_irn_link(bb);
341         ins[1] = mem;
342         return new_r_Sync(bb, 2, ins);
343 }
344
345 /**
346  * Instrument a single ir_graph, counters should point to the bblock
347  * counters array.
348  */
349 static void instrument_irg(ir_graph *irg, ir_entity *counters,
350                            block_id_walker_data_t *wd)
351 {
352         ir_node *end   = get_irg_end(irg);
353         ir_node *endbb = get_irg_end_block(irg);
354         int i;
355
356         /* generate a symbolic constant pointing to the count array */
357         symconst_symbol sym;
358         sym.entity_p = counters;
359         wd->symconst = new_r_SymConst(irg, mode_P_data, sym, symconst_addr_ent);
360
361         /* instrument each block in the current irg */
362         irg_block_walk_graph(irg, block_instrument_walker, NULL, wd);
363         irg_block_walk_graph(irg, fix_ssa, NULL, NULL);
364
365         /* connect the new memory nodes to the return nodes */
366         for (i = get_Block_n_cfgpreds(endbb) - 1; i >= 0; --i) {
367                 ir_node *node = skip_Proj(get_Block_cfgpred(endbb, i));
368                 ir_node *bb   = get_Block_cfgpred_block(endbb, i);
369                 ir_node *mem;
370
371                 switch (get_irn_opcode(node)) {
372                 case iro_Return:
373                         mem = get_Return_mem(node);
374                         set_Return_mem(node, sync_mem(bb, mem));
375                         break;
376                 case iro_Raise:
377                         mem = get_Raise_mem(node);
378                         set_Raise_mem(node, sync_mem(bb, mem));
379                         break;
380                 case iro_Bad:
381                         break;
382                 default:
383                         /* A fragile's op exception. There should be another path to End,
384                          * so ignore it.
385                          */
386                         assert(is_fragile_op(node) && \
387                                 "unexpected End control flow predecessor");
388                 }
389         }
390
391         /* as well as calls with attribute noreturn */
392         for (i = get_End_n_keepalives(end) - 1; i >= 0; --i) {
393                 ir_node *node = get_End_keepalive(end, i);
394                 if (is_Call(node)) {
395                         ir_node *bb  = get_nodes_block(node);
396                         ir_node *mem = get_Call_mem(node);
397                         set_Call_mem(node, sync_mem(bb, mem));
398                 }
399         }
400 }
401
402 /**
403  * Creates a new entity representing the equivalent of
404  * static unsigned int name[size]
405  */
406 static ir_entity *new_array_entity(ident *name, int size)
407 {
408         ir_entity *result;
409         ir_type *uint_type, *array_type;
410
411         uint_type = new_type_primitive(mode_Iu);
412         set_type_alignment_bytes(uint_type, get_type_size_bytes(uint_type));
413
414         array_type = new_type_array(1, uint_type);
415         set_array_bounds_int(array_type, 0, 0, size);
416         set_type_size_bytes(array_type, size * get_mode_size_bytes(mode_Iu));
417         set_type_alignment_bytes(array_type, get_mode_size_bytes(mode_Iu));
418         set_type_state(array_type, layout_fixed);
419
420         result = new_entity(get_glob_type(), name, array_type);
421         set_entity_visibility(result, ir_visibility_local);
422         set_entity_compiler_generated(result, 1);
423
424         return result;
425 }
426
427 /**
428  * Creates a new entity representing the equivalent of
429  * static const char name[strlen(string)+1] = string
430  */
431 static ir_entity *new_static_string_entity(ident *name, const char *string)
432 {
433         ir_entity *result;
434
435         ir_type *char_type   = new_type_primitive(mode_Bs);
436         ir_type *string_type = new_type_array(1, char_type);
437
438         ir_initializer_t *contents;
439
440         size_t i, length = strlen(string)+1;
441
442         /* Create the type for a fixed-length string */
443         set_array_bounds_int(string_type, 0, 0, length);
444         set_type_size_bytes(string_type, length);
445         set_type_alignment_bytes(string_type, 1);
446         set_type_state(string_type, layout_fixed);
447
448         result = new_entity(get_glob_type(), name, string_type);
449         set_entity_visibility(result, ir_visibility_local);
450         set_entity_linkage(result, IR_LINKAGE_CONSTANT);
451         set_entity_compiler_generated(result, 1);
452
453         /* There seems to be no simpler way to do this. Or at least, cparser
454          * does exactly the same thing... */
455         contents = create_initializer_compound(length);
456         for (i = 0; i < length; i++) {
457                 ir_tarval *c = new_tarval_from_long(string[i], mode_Bs);
458                 ir_initializer_t *init = create_initializer_tarval(c);
459                 set_initializer_compound_value(contents, i, init);
460         }
461         set_entity_initializer(result, contents);
462
463         return result;
464 }
465
466 ir_graph *ir_profile_instrument(const char *filename)
467 {
468         int n, n_blocks = 0;
469         ident *counter_id, *filename_id;
470         ir_entity *bblock_counts, *ent_filename;
471         block_id_walker_data_t wd;
472         FIRM_DBG_REGISTER(dbg, "firm.ir.profile");
473
474         /* Don't do anything for modules without code. Else the linker will
475          * complain. */
476         if (get_irp_n_irgs() == 0)
477                 return NULL;
478
479         /* count the number of block first */
480         n_blocks = get_irp_n_blocks();
481
482         /* create all the necessary types and entities. Note that the
483          * types must have a fixed layout, because we are already running in the
484          * backend */
485         counter_id    = new_id_from_str("__FIRMPROF__BLOCK_COUNTS");
486         bblock_counts = new_array_entity(counter_id, n_blocks);
487
488         filename_id  = new_id_from_str("__FIRMPROF__FILE_NAME");
489         ent_filename = new_static_string_entity(filename_id, filename);
490
491         /* initialize block id array and instrument blocks */
492         wd.id  = 0;
493         for (n = get_irp_n_irgs() - 1; n >= 0; --n) {
494                 ir_graph *irg = get_irp_irg(n);
495                 instrument_irg(irg, bblock_counts, &wd);
496         }
497
498         return gen_initializer_irg(ent_filename, bblock_counts, n_blocks);
499 }
500
501 static unsigned int *
502 parse_profile(const char *filename, unsigned int num_blocks)
503 {
504         unsigned int *result = NULL;
505         char          buf[8];
506         size_t        ret;
507         unsigned int  i;
508
509         FILE *f = fopen(filename, "rb");
510         if (!f) {
511                 DBG((dbg, LEVEL_2, "Failed to open profile file (%s)\n", filename));
512                 return NULL;
513         }
514
515         /* check header */
516         ret = fread(buf, 8, 1, f);
517         if (ret == 0 || strncmp(buf, "firmprof", 8) != 0) {
518                 DBG((dbg, LEVEL_2, "Broken fileheader in profile\n"));
519                 goto end;
520         }
521
522         result = XMALLOCN(unsigned int, num_blocks);
523
524         /* The profiling output format is defined to be a sequence of integer
525          * values stored little endian format. */
526         for (i = 0; i < num_blocks; ++i) {
527                 unsigned char bytes[4];
528
529                 if ((ret = fread(bytes, 1, 4, f)) < 1)
530                         break;
531
532                 result[i] = (bytes[0] <<  0) | (bytes[1] <<  8)
533                           | (bytes[2] << 16) | (bytes[3] << 24);
534         }
535
536         if (ret < 1) {
537                 DBG((dbg, LEVEL_4, "Failed to read counters... (size: %u)\n",
538                         sizeof(unsigned int) * num_blocks));
539                 xfree(result);
540                 result = NULL;
541         }
542
543 end:
544         fclose(f);
545         return result;
546 }
547
548 /**
549  * Reads the corresponding profile info file if it exists.
550  */
551 static void block_associate_walker(ir_node *bb, void *env)
552 {
553         block_assoc_t *b = (block_assoc_t*) env;
554         execcount_t query;
555
556         query.block = get_irn_node_nr(bb);
557         query.count = b->counters[(b->i)++];
558         DBG((dbg, LEVEL_4, "execcount(%+F, %u): %u\n", bb, query.block,
559             query.count));
560         set_insert(profile, &query, sizeof(query), query.block);
561 }
562
563 static void irp_associate_blocks(block_assoc_t *env)
564 {
565         int n;
566         for (n = get_irp_n_irgs() - 1; n >= 0; --n) {
567                 ir_graph *irg = get_irp_irg(n);
568                 irg_block_walk_graph(irg, block_associate_walker, NULL, env);
569         }
570 }
571
572 bool ir_profile_read(const char *filename)
573 {
574         block_assoc_t env;
575         FIRM_DBG_REGISTER(dbg, "firm.ir.profile");
576
577         env.i = 0;
578         env.counters = parse_profile(filename, get_irp_n_blocks());
579         if (!env.counters)
580                 return false;
581
582         if (profile)
583                 ir_profile_free();
584         profile = new_set(cmp_execcount, 16);
585
586         irp_associate_blocks(&env);
587         xfree(env.counters);
588
589         /* register the vcg hook */
590         hook = dump_add_node_info_callback(dump_profile_node_info, NULL);
591         return true;
592 }
593
594 void ir_profile_free(void)
595 {
596         if (profile) {
597                 del_set(profile);
598                 profile = NULL;
599         }
600
601         if (hook != NULL) {
602                 dump_remove_node_info_callback(hook);
603                 hook = NULL;
604         }
605 }
606
607 bool ir_profile_has_data(void)
608 {
609         return profile != NULL;
610 }
611
612 unsigned int ir_profile_get_block_execcount(const ir_node *block)
613 {
614         execcount_t *ec, query;
615
616         if (!ir_profile_has_data())
617                 return 1;
618
619         query.block = get_irn_node_nr(block);
620         ec = (execcount_t*)set_find(profile, &query, sizeof(query), query.block);
621
622         if (ec != NULL) {
623                 return ec->count;
624         } else {
625                 DBG((dbg, LEVEL_3,
626                         "Warning: Profile contains no data for %+F\n", block));
627                 return 1;
628         }
629 }
630
631 static void initialize_execfreq(ir_node *block, void *data)
632 {
633         initialize_execfreq_env_t *env = (initialize_execfreq_env_t*)data;
634         double freq;
635
636         if (block == get_irg_start_block(env->irg)
637            || block == get_irg_end_block(env->irg)) {
638                 freq = 1.0;
639         } else {
640                 freq = ir_profile_get_block_execcount(block);
641                 freq *= env->freq_factor;
642                 if (freq < MIN_EXECFREQ)
643                         freq = MIN_EXECFREQ;
644         }
645
646         set_execfreq(env->execfreqs, block, freq);
647 }
648
649 ir_exec_freq *ir_create_execfreqs_from_profile(ir_graph *irg)
650 {
651         ir_node *start_block;
652         initialize_execfreq_env_t env;
653         unsigned count;
654
655         env.irg = irg;
656         env.execfreqs = create_execfreq(irg);
657
658         /* Find the first block containing instructions */
659         start_block = get_irg_start_block(irg);
660         count = ir_profile_get_block_execcount(start_block);
661         if (count == 0) {
662                 /* the function was never executed, so fallback to estimated freqs */
663                 free_execfreq(env.execfreqs);
664                 return compute_execfreq(irg, 10);
665         }
666
667         env.freq_factor = 1.0 / count;
668         irg_block_walk_graph(irg, initialize_execfreq, NULL, &env);
669
670         return env.execfreqs;
671 }