added new licence header
[libfirm] / ir / be / beprofile.c
1 /*
2  * Copyright (C) 1995-2007 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 /** vim: set sw=4 ts=4:
21  * @file   beprofile.c
22  * @date   2006-04-06
23  * @author Adam M. Szalkowski
24  * @cvs-id $Id$
25  *
26  * Code instrumentation and execution count profiling
27  *
28  * Copyright (C) 2006 Universitaet Karlsruhe
29  * Released under the GPL
30  */
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34
35 #include <math.h>
36
37 #include "hashptr.h"
38 #include "debug.h"
39 #include "obst.h"
40 #include "set.h"
41 #include "list.h"
42 #include "pmap.h"
43
44 #include "entity.h"
45 #include "irprintf.h"
46 #include "irgwalk.h"
47 #include "irdump_t.h"
48 #include "irnode_t.h"
49 #include "ircons_t.h"
50 #include "irloop_t.h"
51 #include "iredges.h"
52 #include "execfreq.h"
53 #include "irvrfy.h"
54 #include "type.h"
55
56 #include "be_t.h"
57 #include "belive_t.h"
58 #include "besched_t.h"
59 #include "beirgmod.h"
60 #include "bearch_t.h"
61 #include "beabi.h"
62 #include "benode_t.h"
63 #include "beutil.h"
64 #include "ircons.h"
65 #include "irhooks.h"
66 #include "iredges.h"
67
68 #include "bechordal_t.h"
69
70 #include "beprofile.h"
71
72 /** An entry in the id-to-location map */
73 typedef struct loc_entry {
74         ir_entity    *fname;   /**< the entity holding the file name */
75         unsigned int lineno;   /**< line number */
76 } loc_entry;
77
78 typedef struct _block_id_walker_data_t {
79         tarval         **array;    /**< the entity the holds the block counts */
80         unsigned int   id;         /**< current block id number */
81         ir_node        *symconst;  /**< the SymConst representing array */
82         pmap           *fname_map; /**< set containing all found filenames */
83         loc_entry      *locs;      /**< locations */
84         ir_type        *tp_char;   /**< the character type */
85         unsigned       flags;      /**< profile flags */
86 } block_id_walker_data_t;
87
88 typedef struct _execcount_t {
89         unsigned int block;
90         unsigned int count;
91 } execcount_t;
92
93 static int
94 cmp_execcount(const void * a, const void * b, size_t size)
95 {
96         return ((execcount_t*)a)->block != ((execcount_t*)b)->block;
97 }
98
99 static void
100 block_counter(ir_node * bb, void * data)
101 {
102         unsigned int  *count = data;
103         *count = *count + 1;
104 }
105
106 static unsigned int
107 count_blocks(ir_graph * irg)
108 {
109         unsigned int count = 0;
110
111         irg_block_walk_graph(irg, block_counter, NULL, &count);
112         return count;
113 }
114
115 /* keep the execcounts here because they are only read once per compiler run */
116 static set * profile = NULL;
117 static hook_entry_t hook;
118
119 /**
120  * Instrument a block with code needed for profiling
121  */
122 static void
123 instrument_block(ir_node * bb, ir_node * address, unsigned int id)
124 {
125         ir_graph *irg = get_irn_irg(bb);
126         ir_node  *start_block = get_irg_start_block(irg);
127         ir_node  *load, *store, *offset, *add, *projm, *proji, *unknown;
128         ir_node  *cnst;
129
130         /**
131          * We can't instrument the start and end block as there are no real
132          * instructions in these blocks
133          */
134         if(bb == start_block || bb == get_irg_end_block(irg))
135                 return;
136
137         unknown = new_r_Unknown(irg, mode_M);
138         cnst    = new_r_Const_long(irg, start_block, mode_Iu, get_mode_size_bytes(mode_Iu) * id);
139         offset  = new_r_Add(irg, bb, address, cnst, mode_P);
140         load    = new_r_Load(irg, bb, unknown, offset, mode_Iu);
141         projm   = new_r_Proj(irg, bb, load, mode_M, pn_Load_M);
142         proji   = new_r_Proj(irg, bb, load, mode_Iu, pn_Load_res);
143         cnst    = new_r_Const_long(irg, start_block, mode_Iu, 1);
144         add     = new_r_Add(irg, bb, proji, cnst, mode_Iu);
145         store   = new_r_Store(irg, bb, projm, offset, add);
146         projm   = new_r_Proj(irg, bb, store, mode_M, pn_Store_M);
147         set_irn_link(bb, projm);
148         set_irn_link(projm, load);
149 }
150
151 typedef struct fix_env {
152         ir_node *start_block;
153         ir_node *end_block;
154 } fix_env;
155
156 /**
157  * SSA Construction for instrumentation code memory
158  */
159 static void
160 fix_ssa(ir_node * bb, void * data)
161 {
162         fix_env *env = data;
163         ir_node *mem;
164         int     arity = get_Block_n_cfgpreds(bb);
165
166         /* start and end block are not instrumented, skip! */
167         if (bb == env->start_block || bb == env->end_block)
168                 return;
169
170         if (arity == 1) {
171                 mem = get_irn_link(get_Block_cfgpred_block(bb, 0));
172         } else {
173                 int n;
174                 ir_node **ins;
175                 ir_graph *irg = current_ir_graph;
176
177                 NEW_ARR_A(ir_node*, ins, arity);
178                 for (n = arity - 1; n >= 0; --n) {
179                         ins[n] = get_irn_link(get_Block_cfgpred_block(bb, n));
180                 }
181                 mem = new_r_Phi(irg, bb, arity, ins, mode_M);
182         }
183         set_Load_mem(get_irn_link(get_irn_link(bb)), mem);
184 }
185
186
187 /**
188  * Generates a new irg which calls the initializer
189  *
190  * Pseudocode:
191  *       void __firmprof_initializer(void) { __init_firmprof(ent_filename, bblock_id, bblock_counts, n_blocks); }
192  */
193 static ir_graph *
194 gen_initializer_irg(ir_entity * ent_filename, ir_entity * bblock_id, ir_entity * bblock_counts, int n_blocks)
195 {
196         ir_node *start_block;
197
198         ir_node   *ins[4];
199         ident     *name = new_id_from_str("__firmprof_initializer");
200         ir_entity *ent  = new_entity(get_glob_type(), name, new_type_method(name, 0, 0));
201         ir_node   *ret, *call, *symconst;
202         symconst_symbol sym;
203
204         ident     *init_name = new_id_from_str("__init_firmprof");
205         ir_type   *init_type = new_type_method(init_name, 4, 0);
206         ir_type   *uint, *uintptr, *string;
207         ir_entity *init_ent;
208         ir_graph  *irg;
209         ir_node   *bb;
210         ir_type   *empty_frame_type;
211
212         set_entity_ld_ident(ent, name);
213
214         uint    = new_type_primitive(new_id_from_str("__uint"), mode_Iu);
215         uintptr = new_type_pointer(new_id_from_str("__uintptr"), uint, mode_P);
216         string  = new_type_pointer(new_id_from_str("__charptr"), new_type_primitive(new_id_from_str("__char"), mode_Bs), mode_P);
217
218         set_method_param_type(init_type, 0, string);
219         set_method_param_type(init_type, 1, uintptr);
220         set_method_param_type(init_type, 2, uintptr);
221         set_method_param_type(init_type, 3, uint);
222         init_ent = new_entity(get_glob_type(), init_name, init_type);
223         set_entity_ld_ident(init_ent, init_name);
224
225         irg = new_ir_graph(ent, 0);
226         empty_frame_type = get_irg_frame_type(irg);
227         set_type_size_bytes(empty_frame_type, 0);
228
229         bb = get_cur_block();
230
231         start_block = get_irg_start_block(irg);
232
233         sym.entity_p = init_ent;
234         symconst     = new_r_SymConst(irg, start_block, sym, symconst_addr_ent);
235
236         sym.entity_p = ent_filename;
237         ins[0] = new_r_SymConst(irg, start_block, sym, symconst_addr_ent);
238         sym.entity_p = bblock_id;
239         ins[1] = new_r_SymConst(irg, start_block, sym, symconst_addr_ent);
240         sym.entity_p = bblock_counts;
241         ins[2] = new_r_SymConst(irg, start_block, sym, symconst_addr_ent);
242         ins[3] = new_r_Const_long(irg, start_block, mode_Iu, n_blocks);
243
244         call = new_r_Call(irg, bb, get_irg_initial_mem(irg), symconst, 4, ins, init_type);
245         ret = new_r_Return(irg, bb, new_r_Proj(irg, bb, call, mode_M, pn_Call_M_regular), 0, NULL);
246         mature_immBlock(bb);
247
248         add_immBlock_pred(get_irg_end_block(irg), ret);
249         mature_immBlock(get_irg_end_block(irg));
250
251         irg_finalize_cons(irg);
252
253         return irg;
254 }
255
256 /**
257  * Create the location data for the given debug info.
258  */
259 static void create_location_data(dbg_info *dbg, block_id_walker_data_t *wd)
260 {
261         unsigned lineno;
262         const char *fname = be_retrieve_dbg_info(dbg, &lineno);
263
264         if (fname) {
265                 pmap_entry *entry = pmap_find(wd->fname_map, (void *)fname);
266                 ir_entity  *ent;
267
268                 if (! entry) {
269                         static unsigned nr = 0;
270                         ident   *id;
271                         char    buf[128];
272                         ir_type *arr;
273                         int     i, len = strlen(fname) + 1;
274                         tarval  **tarval_string;
275
276                         snprintf(buf, sizeof(buf), "firm_name_arr.%d", nr);
277                         arr = new_type_array(new_id_from_str(buf), 1, wd->tp_char);
278                         set_array_bounds_int(arr, 0, 0, len);
279
280                         snprintf(buf, sizeof(buf), "__firm_name.%d", nr++);
281                         id = new_id_from_str(buf);
282                         ent = new_entity(get_glob_type(), id, arr);
283                         set_entity_ld_ident(ent, id);
284
285                         pmap_insert(wd->fname_map, (void *)fname, ent);
286
287                         /* initialize file name string constant */
288                         tarval_string = alloca(sizeof(*tarval_string) * (len));
289                         for (i = 0; i < len; ++i) {
290                                 tarval_string[i] = new_tarval_from_long(fname[i], mode_Bs);
291                         }
292                         set_entity_variability(ent, variability_constant);
293                         set_array_entity_values(ent, tarval_string, len);
294                 } else {
295                         ent = entry->value;
296                 }
297                 wd->locs[wd->id].fname  = ent;
298                 wd->locs[wd->id].lineno = lineno;
299         } else {
300                 wd->locs[wd->id].fname  = NULL;
301                 wd->locs[wd->id].lineno = 0;
302         }
303 }
304
305 /**
306  * Walker: assigns an ID to every block.
307  * Builds the string table
308  */
309 static void
310 block_id_walker(ir_node * bb, void * data)
311 {
312         block_id_walker_data_t *wd = data;
313
314         wd->array[wd->id] = new_tarval_from_long(get_irn_node_nr(bb), mode_Iu);
315         instrument_block(bb, wd->symconst, wd->id);
316
317         if (wd->flags & profile_with_locations) {
318                 dbg_info *dbg = get_irn_dbg_info(bb);
319                 create_location_data(dbg, wd);
320         }
321         ++wd->id;
322 }
323
324 #define IDENT(x)        new_id_from_chars(x, sizeof(x) - 1)
325
326 ir_graph *
327 be_profile_instrument(const char *filename, unsigned flags)
328 {
329         int n, i;
330         int n_blocks = 0;
331         ir_entity *bblock_id;
332         ir_entity *bblock_counts;
333         ir_entity *ent_filename;
334         ir_entity *ent_locations = NULL;
335         ir_entity *loc_lineno = NULL;
336         ir_entity *loc_name = NULL;
337         ir_entity *ent;
338         ir_type *array_type;
339         ir_type *uint_type;
340         ir_type *string_type;
341         ir_type *character_type;
342         ir_type *loc_type = NULL;
343         ir_type *charptr_type;
344         ir_type *gtp;
345         tarval **tarval_array;
346         tarval **tarval_string;
347         tarval *tv;
348         int filename_len = strlen(filename)+1;
349         ident *cur_ident;
350         int align_l, align_n, size;
351         ir_graph *rem;
352         block_id_walker_data_t  wd;
353         symconst_symbol sym;
354
355         /* count the number of block first */
356         for (n = get_irp_n_irgs() - 1; n >= 0; --n) {
357                 ir_graph *irg = get_irp_irg(n);
358
359                 n_blocks += count_blocks(irg);
360         }
361
362         /* create all the necessary types and entities. Note that the
363            types must have a fixed layout, because we already running in the
364            backend */
365         uint_type      = new_type_primitive(IDENT("__uint"), mode_Iu);
366         set_type_alignment_bytes(uint_type, get_type_size_bytes(uint_type));
367         array_type     = new_type_array(IDENT("__block_info_array"), 1, uint_type);
368         set_array_bounds_int(array_type, 0, 0, n_blocks);
369
370         character_type = new_type_primitive(IDENT("__char"), mode_Bs);
371         string_type    = new_type_array(IDENT("__filename"), 1, character_type);
372         set_array_bounds_int(string_type, 0, 0, filename_len);
373
374         gtp            = get_glob_type();
375
376         cur_ident      = IDENT("__FIRMPROF__BLOCK_IDS");
377         bblock_id      = new_entity(gtp, cur_ident, array_type);
378         set_entity_ld_ident(bblock_id, cur_ident);
379         set_entity_variability(bblock_id, variability_initialized);
380
381         cur_ident      = IDENT("__FIRMPROF__BLOCK_COUNTS");
382         bblock_counts  = new_entity(gtp, cur_ident, array_type);
383         set_entity_ld_ident(bblock_counts, cur_ident);
384         set_entity_variability(bblock_counts, variability_initialized);
385
386         cur_ident      = IDENT("__FIRMPROF__FILE_NAME");
387         ent_filename   = new_entity(gtp, cur_ident, string_type);
388         set_entity_ld_ident(ent_filename, cur_ident);
389
390         if (flags & profile_with_locations) {
391                 loc_type       = new_type_struct(IDENT("__location"));
392                 loc_lineno     = new_entity(loc_type, IDENT("lineno"), uint_type);
393                 align_l        = get_type_alignment_bytes(uint_type);
394                 size           = get_type_size_bytes(uint_type);
395                 set_entity_offset(loc_lineno, 0);
396
397                 charptr_type   = new_type_pointer(IDENT("__charptr"), character_type, mode_P_data);
398                 align_n        = get_type_size_bytes(charptr_type);
399                 set_type_alignment_bytes(charptr_type, align_n);
400                 loc_name       = new_entity(loc_type, IDENT("name"), charptr_type);
401                 size           = (size + align_n - 1) & -align_n;
402                 set_entity_offset(loc_name, size);
403                 size          += align_n;
404
405                 if (align_n > align_l)
406                         align_l = align_n;
407                 size = (size + align_l - 1) & -align_l;
408                 set_type_size_bytes(loc_type, size);
409                 set_type_state(loc_type, layout_fixed);
410
411                 loc_type = new_type_array(IDENT("__locarray"), 1, loc_type);
412                 set_array_bounds_int(string_type, 0, 0, n_blocks);
413
414                 cur_ident      = IDENT("__FIRMPROF__LOCATIONS");
415                 ent_locations   = new_entity(gtp, cur_ident, loc_type);
416                 set_entity_ld_ident(ent_locations, cur_ident);
417         }
418
419         /* initialize count array */
420         NEW_ARR_A(tarval *, tarval_array, n_blocks);
421         tv = get_tarval_null(mode_Iu);
422         for (i = 0; i < n_blocks; ++i) {
423                 tarval_array[i] = tv;
424         }
425         set_array_entity_values(bblock_counts, tarval_array, n_blocks);
426
427         /* initialize function name string constant */
428         tarval_string = alloca(sizeof(*tarval_string) * (filename_len));
429         for (i = 0; i < filename_len; ++i) {
430                 tarval_string[i] = new_tarval_from_long(filename[i], mode_Bs);
431         }
432         set_entity_variability(ent_filename, variability_constant);
433         set_array_entity_values(ent_filename, tarval_string, filename_len);
434
435         /* initialize block id array and instrument blocks */
436         wd.array     = tarval_array;
437         wd.id        = 0;
438         wd.tp_char   = character_type;
439         wd.flags     = flags;
440         if (flags & profile_with_locations) {
441                 wd.fname_map = pmap_create();
442                 NEW_ARR_A(loc_entry, wd.locs, n_blocks);
443         }
444
445         for (n = get_irp_n_irgs() - 1; n >= 0; --n) {
446                 ir_graph      *irg = get_irp_irg(n);
447                 int            i;
448                 ir_node       *endbb = get_irg_end_block(irg);
449                 fix_env       env;
450
451                 set_current_ir_graph(irg);
452
453                 /* generate a symbolic constant pointing to the count array */
454                 sym.entity_p = bblock_counts;
455                 wd.symconst  = new_r_SymConst(irg, get_irg_start_block(irg), sym, symconst_addr_ent);
456
457                 irg_block_walk_graph(irg, block_id_walker, NULL, &wd);
458                 env.start_block = get_irg_start_block(irg);
459                 env.end_block   = get_irg_end_block(irg);
460                 set_irn_link(env.start_block, get_irg_no_mem(irg));
461                 irg_block_walk_graph(irg, fix_ssa, NULL, &env);
462                 for (i = get_Block_n_cfgpreds(endbb) - 1; i >= 0; --i) {
463                         ir_node *node = skip_Proj(get_Block_cfgpred(endbb, i));
464                         ir_node *bb   = get_Block_cfgpred_block(endbb, i);
465                         ir_node *sync;
466                         ir_node *ins[2];
467
468                         switch (get_irn_opcode(node)) {
469                         case iro_Return:
470                                 ins[0] = get_irn_link(bb);
471                                 ins[1] = get_Return_mem(node);
472                                 sync   = new_r_Sync(irg, bb, 2, ins);
473                                 set_Return_mem(node, sync);
474                                 break;
475                         case iro_Raise:
476                                 ins[0] = get_irn_link(bb);
477                                 ins[1] = get_Raise_mem(node);
478                                 sync   = new_r_Sync(irg, bb, 2, ins);
479                                 set_Raise_mem(node, sync);
480                                 break;
481                         default:
482                                 /* a fragile's op exception. There should be another path to End,
483                                    so ignore it */
484                                 assert(is_fragile_op(node) && "unexpected End control flow predecessor");
485                         }
486                 }
487         }
488         set_array_entity_values(bblock_id, tarval_array, n_blocks);
489
490         if (flags & profile_with_locations) {
491                 /* build the initializer for the locations */
492                 rem = current_ir_graph;
493                 current_ir_graph = get_const_code_irg();
494                 ent = get_array_element_entity(loc_type);
495                 set_entity_variability(ent_locations, variability_constant);
496                 for (i = 0; i < n_blocks; ++i) {
497                         compound_graph_path *path;
498                         tarval *tv;
499                         ir_node *n;
500
501                         /* lineno */
502                         path = new_compound_graph_path(loc_type, 2);
503                         set_compound_graph_path_array_index(path, 0, i);
504                         set_compound_graph_path_node(path, 0, ent);
505                         set_compound_graph_path_node(path, 1, loc_lineno);
506                         tv = new_tarval_from_long(wd.locs[i].lineno, mode_Iu);
507                         add_compound_ent_value_w_path(ent_locations, new_Const(mode_Iu, tv), path);
508
509                         /* name */
510                         path = new_compound_graph_path(loc_type, 2);
511                         set_compound_graph_path_array_index(path, 0, i);
512                         set_compound_graph_path_node(path, 0, ent);
513                         set_compound_graph_path_node(path, 1, loc_name);
514                         if (wd.locs[i].fname) {
515                                 sym.entity_p = wd.locs[i].fname;
516                                 n = new_SymConst(sym, symconst_addr_ent);
517                         } else {
518                                 n = new_Const(mode_P_data, get_mode_null(mode_P_data));
519                         }
520                         add_compound_ent_value_w_path(ent_locations, n, path);
521                 }
522                 pmap_destroy(wd.fname_map);
523         }
524         return gen_initializer_irg(ent_filename, bblock_id, bblock_counts, n_blocks);
525 }
526
527 static void
528 profile_node_info(void *ctx, FILE *f, const ir_node *irn)
529 {
530         if(is_Block(irn)) {
531                 fprintf(f, "profiled execution count: %u\n", be_profile_get_block_execcount(irn));
532         }
533 }
534
535 static void
536 register_vcg_hook(void)
537 {
538         memset(&hook, 0, sizeof(hook));
539         hook.hook._hook_node_info = profile_node_info;
540         register_hook(hook_node_info, &hook);
541 }
542
543 static void
544 unregister_vcg_hook(void)
545 {
546         unregister_hook(hook_node_info, &hook);
547 }
548
549 /**
550  * Reads the corresponding profile info file if it exists and returns a
551  * profile info struct
552  */
553 void
554 be_profile_read(const char *filename)
555 {
556         FILE   *f;
557         char    buf[8];
558         size_t  ret;
559
560         f = fopen(filename, "r");
561         if(f == NULL) {
562                 return;
563         }
564         printf("found profile data '%s'.\n", filename);
565
566         /* check magic */
567         ret = fread(buf, 8, 1, f);
568         if(ret == 0 || strncmp(buf, "firmprof", 8) != 0) {
569                 return;
570         }
571
572         if(profile) be_profile_free();
573         profile = new_set(cmp_execcount, 16);
574
575         do {
576                 execcount_t  query;
577                 ret = fread(&query, sizeof(unsigned int), 2, f);
578
579                 if(ret != 2) break;
580
581                 set_insert(profile, &query, sizeof(query), query.block);
582         } while(1);
583
584         fclose(f);
585         register_vcg_hook();
586 }
587
588 /**
589  * Frees the profile info
590  */
591 void
592 be_profile_free(void)
593 {
594         if(profile) {
595                 unregister_vcg_hook();
596                 del_set(profile);
597         }
598 }
599
600 /**
601  * Tells whether profile module has acquired data
602  */
603 int
604 be_profile_has_data(void)
605 {
606         return (profile != NULL);
607 }
608
609 /**
610  * Get block execution count as determined be profiling
611  */
612 unsigned int
613 be_profile_get_block_execcount(const ir_node *block)
614 {
615         execcount_t *ec, query;
616
617         if(!profile)
618                 return 1;
619
620         query.block = get_irn_node_nr(block);
621         ec = set_find(profile, &query, sizeof(query), get_irn_node_nr(block));
622
623         if(ec != NULL) {
624                 return ec->count;
625         } else {
626                 ir_fprintf(stderr, "Warning: Profile contains no data for %+F\n",
627                            block);
628                 return 1;
629         }
630 }
631
632 typedef struct _intialize_execfreq_env_t {
633         ir_graph *irg;
634         ir_exec_freq *execfreqs;
635         double freq_factor;
636 } initialize_execfreq_env_t;
637
638 // minimal execution frequency (an execfreq of 0 confuses algos)
639 static const double MIN_EXECFREQ = 0.00001;
640
641 static void initialize_execfreq(ir_node *block, void *data) {
642         initialize_execfreq_env_t *env = data;
643         double freq;
644
645         if(block == get_irg_start_block(env->irg)
646            || block == get_irg_end_block(env->irg)) {
647                 freq = 1.0;
648         } else {
649                 freq = be_profile_get_block_execcount(block);
650                 freq *= env->freq_factor;
651                 if(freq < MIN_EXECFREQ)
652                         freq = MIN_EXECFREQ;
653         }
654
655         set_execfreq(env->execfreqs, block, freq);
656 }
657
658 ir_exec_freq *be_create_execfreqs_from_profile(ir_graph *irg)
659 {
660         ir_node *block2 = NULL;
661         ir_node *start_block;
662         const ir_edge_t *edge;
663         initialize_execfreq_env_t env;
664         unsigned count;
665
666         env.irg = irg;
667         env.execfreqs = create_execfreq(irg);
668
669         // find the successor to the start block
670         start_block = get_irg_start_block(irg);
671         foreach_block_succ(start_block, edge) {
672                 ir_node *succ = get_edge_src_irn(edge);
673                 if(succ != start_block) {
674                         block2 = succ;
675                         break;
676                 }
677         }
678         assert(block2 != NULL);
679
680         count = be_profile_get_block_execcount(block2);
681         if(count == 0) {
682                 // the function was never executed, so fallback to estimated freqs
683                 free_execfreq(env.execfreqs);
684
685                 return compute_execfreq(irg, 10);
686         }
687
688         env.freq_factor = 1.0 / count;
689         irg_block_walk_graph(irg, initialize_execfreq, NULL, &env);
690
691         return env.execfreqs;
692 }