irprofile.c 17.1 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

Christian Würdig's avatar
Christian Würdig committed
6
7
8
/**
 * @file
 * @brief       Code instrumentation and execution count profiling.
9
10
 * @author      Adam M. Szalkowski, Steven Schaefer
 * @date        06.04.2006, 11.11.2010
11
12
 */
#include <math.h>
13
#include <stdio.h>
14
15
16
17

#include "hashptr.h"
#include "debug.h"
#include "obst.h"
18
#include "xmalloc.h"
19
20
21
22
23
#include "set.h"
#include "irgwalk.h"
#include "irdump_t.h"
#include "irnode_t.h"
#include "ircons_t.h"
24
#include "execfreq_t.h"
Michael Beck's avatar
Michael Beck committed
25
#include "irprofile.h"
26
#include "typerep.h"
27

28
/* Instrument blocks walker. */
29
typedef struct block_id_walker_data_t {
30
31
	unsigned int  id;       /**< current block id number */
	ir_node      *counters; /**< the node representing the counter array */
32
33
} block_id_walker_data_t;

34
35
36
37
38
39
40
41
42
43
44
45
46
/* Associate counters with blocks. */
typedef struct block_assoc_t {
	unsigned int i;          /**< current block id number */
	unsigned int *counters;  /**< block execution counts */
} block_assoc_t;

/* minimal execution frequency (an execfreq of 0 confuses algos) */
#define MIN_EXECFREQ 0.00001

/* keep the execcounts here because they are only read once per compiler run */
static set *profile = NULL;

/* Hook for vcg output. */
47
static void *hook;
48
49
50
51
52
53
54
55

/* The debug module handle. */
DEBUG_ONLY(static firm_dbg_module_t *dbg;)

/* Since the backend creates a new firm graph we cannot associate counts with
 * blocks directly. Instead we associate them with the block ids, which are
 * maintained.
 */
56
typedef struct execcount_t {
57
	unsigned long block; /**< block id */
58
	uint32_t      count; /**< execution count */
59
60
} execcount_t;

Michael Beck's avatar
Michael Beck committed
61
62
63
/**
 * Compare two execcount_t entries.
 */
64
65
static int cmp_execcount(const void *a, const void *b, size_t size)
{
66
67
	const execcount_t *ea = (const execcount_t*)a;
	const execcount_t *eb = (const execcount_t*)b;
68
	(void) size;
Michael Beck's avatar
Michael Beck committed
69
	return ea->block != eb->block;
70
}
71

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
uint32_t ir_profile_get_block_execcount(const ir_node *block)
{
	execcount_t *ec, query;

	query.block = get_irn_node_nr(block);
	ec = set_find(execcount_t, profile, &query, sizeof(query), query.block);

	if (ec != NULL) {
		return ec->count;
	} else {
		DBG((dbg, LEVEL_3,
			"Warning: Profile contains no data for %+F\n", block));
		return 0;
	}
}

Michael Beck's avatar
Michael Beck committed
88
89
90
/**
 * Block walker, count number of blocks.
 */
91
static void block_counter(ir_node *bb, void *data)
92
{
93
	unsigned *count = (unsigned*) data;
Michael Beck's avatar
Michael Beck committed
94
95
	(void) bb;
	++(*count);
96
97
}

Michael Beck's avatar
Michael Beck committed
98
/**
99
 * Returns the number of blocks the given graph.
Michael Beck's avatar
Michael Beck committed
100
 */
101
static unsigned int get_irg_n_blocks(ir_graph *irg)
102
{
103
104
105
106
107
108
	unsigned int count = 0;
	irg_block_walk_graph(irg, block_counter, NULL, &count);
	return count;
}

/**
109
 * Returns the number of basic blocks in the current ir program.
110
 */
111
static unsigned int get_irp_n_blocks(void)
112
{
113
114
	int i, n = get_irp_n_irgs();
	unsigned int count = 0;
Matthias Braun's avatar
fixes    
Matthias Braun committed
115

116
117
118
119
	for (i = 0; i < n; i++) {
		ir_graph *irg = get_irp_irg(i);
		count += get_irg_n_blocks(irg);
	}
Matthias Braun's avatar
fixes    
Matthias Braun committed
120

121
	return count;
122
123
}

124
125
/* vcg helper */
static void dump_profile_node_info(void *ctx, FILE *f, const ir_node *irn)
126
{
127
128
129
130
	(void) ctx;
	if (is_Block(irn)) {
		unsigned int execcount = ir_profile_get_block_execcount(irn);
		fprintf(f, "profiled execution count: %u\n", execcount);
131
132
133
	}
}

134
135
136
/**
 * Add the given method entity as a constructor.
 */
137
138
139
static void add_constructor(ir_entity *method)
{
    ir_type   *method_type  = get_entity_type(method);
140
    ir_type   *ptr_type     = new_type_pointer(method_type);
141

142
    ir_type   *constructors = get_segment_type(IR_SEGMENT_CONSTRUCTORS);
143
144
145
	ident     *ide = id_unique("constructor_ptr.%u");
    ir_entity *ptr = new_entity(constructors, ide, ptr_type);
    ir_graph  *irg = get_const_code_irg();
146
    ir_node   *val = new_r_Address(irg, method);
147
148

	set_entity_ld_ident(ptr, new_id_from_chars("", 0));
149
    set_entity_compiler_generated(ptr, 1);
150
151
    set_entity_linkage(ptr, IR_LINKAGE_CONSTANT | IR_LINKAGE_HIDDEN_USER);
    set_entity_visibility(ptr, ir_visibility_private);
152
153
    set_atomic_ent_value(ptr, val);
}
154

155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
/**
 * Returns an entity representing the __init_firmprof function from libfirmprof
 * This is the equivalent of:
 * extern void __init_firmprof(char *filename, uint *counters, uint size)
 */
static ir_entity *get_init_firmprof_ref(void)
{
	ident   *init_name = new_id_from_str("__init_firmprof");
	ir_type *init_type = new_type_method(3, 0);
	ir_type *uint      = new_type_primitive(mode_Iu);
	ir_type *uintptr   = new_type_pointer(uint);
	ir_type *string    = new_type_pointer(new_type_primitive(mode_Bs));
	ir_entity *result;

	set_method_param_type(init_type, 0, string);
	set_method_param_type(init_type, 1, uintptr);
	set_method_param_type(init_type, 2, uint);

	result = new_entity(get_glob_type(), init_name, init_type);
	set_entity_visibility(result, ir_visibility_external);

	return result;
}

179
180
/**
 * Generates a new irg which calls the initializer
Michael Beck's avatar
BugFix:    
Michael Beck committed
181
182
 *
 * Pseudocode:
183
184
185
186
 *    static void __firmprof_initializer(void) __attribute__ ((constructor))
 *    {
 *        __init_firmprof(ent_filename, bblock_counts, n_blocks);
 *    }
187
 */
188
189
static ir_graph *gen_initializer_irg(ir_entity *ent_filename,
                                     ir_entity *bblock_counts, int n_blocks)
190
{
191
192
	ir_graph *irg;
	ir_node  *ins[3];
193
	ir_node  *bb, *ret, *call;
194
	ir_type  *empty_frame_type;
195

196
	ir_entity *init_ent = get_init_firmprof_ref();
Adam Szalkowski's avatar
Adam Szalkowski committed
197

198
199
200
	ident     *name = new_id_from_str("__firmprof_initializer");
	ir_entity *ent  = new_entity(get_glob_type(), name, new_type_method(0, 0));
	set_entity_visibility(ent, ir_visibility_local);
Christian Würdig's avatar
Christian Würdig committed
201
202
	set_entity_ld_ident(ent, name);

203
	/* create the new ir_graph */
Christian Würdig's avatar
Christian Würdig committed
204
	irg = new_ir_graph(ent, 0);
205
	set_current_ir_graph(irg);
Christian Würdig's avatar
Christian Würdig committed
206
207
	empty_frame_type = get_irg_frame_type(irg);
	set_type_size_bytes(empty_frame_type, 0);
208
	set_type_state(empty_frame_type, layout_fixed);
209

210
	bb = get_r_cur_block(irg);
Adam Szalkowski's avatar
Adam Szalkowski committed
211

212
	ir_node *const callee = new_r_Address(irg, init_ent);
Adam Szalkowski's avatar
Adam Szalkowski committed
213

214
215
	ins[0] = new_r_Address(irg, ent_filename);
	ins[1] = new_r_Address(irg, bblock_counts);
216
	ins[2] = new_r_Const_long(irg, mode_Iu, n_blocks);
217

218
	call = new_r_Call(bb, get_irg_initial_mem(irg), callee, 3, ins,
219
220
	        get_entity_type(init_ent));
	ret  = new_r_Return(bb, new_r_Proj(call, mode_M, pn_Call_M), 0, NULL);
221
222
223
224
225
	mature_immBlock(bb);

	add_immBlock_pred(get_irg_end_block(irg), ret);
	mature_immBlock(get_irg_end_block(irg));

Matthias Braun's avatar
fixes    
Matthias Braun committed
226
227
	irg_finalize_cons(irg);

228
	/* add a pointer to the new function in the constructor section */
229
230
	add_constructor(ent);

231
232
233
	return irg;
}

234
/**
235
236
237
 * Instrument a block with code needed for profiling.
 * This just inserts the instruction nodes, it doesn't connect the memory
 * nodes in a meaningful way.
238
 */
239
static void instrument_block(ir_node *bb, ir_node *address, unsigned int id)
240
{
241
242
243
244
245
246
247
248
249
250
251
252
253
	ir_graph *irg = get_irn_irg(bb);
	ir_node  *load, *store, *offset, *add, *projm, *proji, *unknown, *cnst;

	/* We can't instrument the end block */
	if (bb == get_irg_end_block(irg))
		return;

	unknown = new_r_Unknown(irg, mode_M);
	cnst    = new_r_Const_long(irg, mode_Iu, get_mode_size_bytes(mode_Iu) * id);
	offset  = new_r_Add(bb, address, cnst, get_modeP_data());
	load    = new_r_Load(bb, unknown, offset, mode_Iu, cons_none);
	projm   = new_r_Proj(load, mode_M, pn_Load_M);
	proji   = new_r_Proj(load, mode_Iu, pn_Load_res);
254
	cnst    = new_r_Const(irg, get_mode_one(mode_Iu));
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
	add     = new_r_Add(bb, proji, cnst, mode_Iu);
	store   = new_r_Store(bb, projm, offset, add, cons_none);
	projm   = new_r_Proj(store, mode_M, pn_Store_M);

	set_irn_link(bb, projm);
	set_irn_link(projm, load);
}

/**
 * SSA Construction for instrumentation code memory.
 *
 * This introduces a new memory node and connects it to the instrumentation
 * codes, inserting phiM nodes as necessary. Note that afterwards, the new
 * memory is not connected to any return nodes and thus still dead.
 */
static void fix_ssa(ir_node *bb, void *data)
{
	ir_graph *irg = get_irn_irg(bb);
	ir_node *mem, *proj, *load;
	int n, arity = get_Block_n_cfgpreds(bb);

	(void) data;

	/* end blocks are not instrumented, skip! */
	if (bb == get_irg_end_block(irg))
		return;

	if (bb == get_irg_start_block(irg)) {
		mem = get_irg_initial_mem(irg);
	} else if (arity == 1) {
		ir_node *pred = get_Block_cfgpred_block(bb, 0);
		if (!is_Bad(pred))
			mem = (ir_node*) get_irn_link(pred);
		else
			mem = new_r_NoMem(irg);
290
	} else {
291
292
293
294
295
296
297
298
299
		ir_node **ins = ALLOCAN(ir_node*, arity);
		for (n = arity - 1; n >= 0; --n) {
			ir_node *pred = get_Block_cfgpred_block(bb, n);
			if (!is_Bad(pred))
				ins[n] = (ir_node*) get_irn_link(pred);
			else
				ins[n] = new_r_NoMem(irg);
		}
		mem = new_r_Phi(bb, arity, ins, mode_M);
300
	}
301
302
303
304
305
306
307

	/* The block link fields point to the projm from the instrumentation code,
	 * the projm in turn links to the initial load which lacks a memory
	 * argument at this point. */
	proj = (ir_node*) get_irn_link(bb);
	load = (ir_node*) get_irn_link(proj);
	set_Load_mem(load, mem);
308
309
310
}

/**
311
 * Instrument a single block.
312
 */
313
static void block_instrument_walker(ir_node *bb, void *data)
314
{
315
	block_id_walker_data_t *wd = (block_id_walker_data_t*)data;
316
	instrument_block(bb, wd->counters, wd->id);
317
318
319
	++wd->id;
}

320
321
322
323
324
325
326
327
328
329
330
/**
 * Synchronize the original memory input of node with the additional operand
 * from the profiling code.
 */
static ir_node *sync_mem(ir_node *bb, ir_node *mem)
{
	ir_node *ins[2];
	ins[0] = (ir_node*) get_irn_link(bb);
	ins[1] = mem;
	return new_r_Sync(bb, 2, ins);
}
331

332
333
334
335
336
337
/**
 * Instrument a single ir_graph, counters should point to the bblock
 * counters array.
 */
static void instrument_irg(ir_graph *irg, ir_entity *counters,
                           block_id_walker_data_t *wd)
338
{
339
340
341
	ir_node *end   = get_irg_end(irg);
	ir_node *endbb = get_irg_end_block(irg);
	int i;
342

343
	/* generate a node pointing to the count array */
344
	wd->counters = new_r_Address(irg, counters);
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374

	/* instrument each block in the current irg */
	irg_block_walk_graph(irg, block_instrument_walker, NULL, wd);
	irg_block_walk_graph(irg, fix_ssa, NULL, NULL);

	/* connect the new memory nodes to the return nodes */
	for (i = get_Block_n_cfgpreds(endbb) - 1; i >= 0; --i) {
		ir_node *node = skip_Proj(get_Block_cfgpred(endbb, i));
		ir_node *bb   = get_Block_cfgpred_block(endbb, i);
		ir_node *mem;

		switch (get_irn_opcode(node)) {
		case iro_Return:
			mem = get_Return_mem(node);
			set_Return_mem(node, sync_mem(bb, mem));
			break;
		case iro_Raise:
			mem = get_Raise_mem(node);
			set_Raise_mem(node, sync_mem(bb, mem));
			break;
		case iro_Bad:
			break;
		default:
			/* A fragile's op exception. There should be another path to End,
			 * so ignore it.
			 */
			assert(is_fragile_op(node) && \
				"unexpected End control flow predecessor");
		}
	}
375

376
377
378
379
380
381
382
383
	/* as well as calls with attribute noreturn */
	for (i = get_End_n_keepalives(end) - 1; i >= 0; --i) {
		ir_node *node = get_End_keepalive(end, i);
		if (is_Call(node)) {
			ir_node *bb  = get_nodes_block(node);
			ir_node *mem = get_Call_mem(node);
			set_Call_mem(node, sync_mem(bb, mem));
		}
384
	}
385
}
386

387
388
389
390
391
392
393
394
395
396
/**
 * Creates a new entity representing the equivalent of
 * static unsigned int name[size]
 */
static ir_entity *new_array_entity(ident *name, int size)
{
	ir_entity *result;
	ir_type *uint_type, *array_type;

	uint_type = new_type_primitive(mode_Iu);
397
	set_type_alignment_bytes(uint_type, get_type_size_bytes(uint_type));
398

399
400
401
	array_type = new_type_array(1, uint_type);
	set_array_bounds_int(array_type, 0, 0, size);
	set_type_size_bytes(array_type, size * get_mode_size_bytes(mode_Iu));
402
403
	set_type_alignment_bytes(array_type, get_mode_size_bytes(mode_Iu));
	set_type_state(array_type, layout_fixed);
Christian Würdig's avatar
Christian Würdig committed
404

405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
	result = new_entity(get_glob_type(), name, array_type);
	set_entity_visibility(result, ir_visibility_local);
	set_entity_compiler_generated(result, 1);

	return result;
}

/**
 * Creates a new entity representing the equivalent of
 * static const char name[strlen(string)+1] = string
 */
static ir_entity *new_static_string_entity(ident *name, const char *string)
{
	ir_entity *result;

	ir_type *char_type   = new_type_primitive(mode_Bs);
	ir_type *string_type = new_type_array(1, char_type);

	ir_initializer_t *contents;

	size_t i, length = strlen(string)+1;

	/* Create the type for a fixed-length string */
	set_array_bounds_int(string_type, 0, 0, length);
	set_type_size_bytes(string_type, length);
430
431
	set_type_alignment_bytes(string_type, 1);
	set_type_state(string_type, layout_fixed);
Christian Würdig's avatar
Christian Würdig committed
432

433
434
435
436
437
438
439
440
441
442
443
444
	result = new_entity(get_glob_type(), name, string_type);
	set_entity_visibility(result, ir_visibility_local);
	set_entity_linkage(result, IR_LINKAGE_CONSTANT);
	set_entity_compiler_generated(result, 1);

	/* There seems to be no simpler way to do this. Or at least, cparser
	 * does exactly the same thing... */
	contents = create_initializer_compound(length);
	for (i = 0; i < length; i++) {
		ir_tarval *c = new_tarval_from_long(string[i], mode_Bs);
		ir_initializer_t *init = create_initializer_tarval(c);
		set_initializer_compound_value(contents, i, init);
445
	}
446
	set_entity_initializer(result, contents);
447

448
449
	return result;
}
450

451
ir_graph *ir_profile_instrument(const char *filename)
452
453
454
455
456
457
{
	int n, n_blocks = 0;
	ident *counter_id, *filename_id;
	ir_entity *bblock_counts, *ent_filename;
	block_id_walker_data_t wd;
	FIRM_DBG_REGISTER(dbg, "firm.ir.profile");
458

459
460
461
	/* Don't do anything for modules without code. Else the linker will
	 * complain. */
	if (get_irp_n_irgs() == 0)
462
		return NULL;
463

464
465
466
467
468
469
470
471
472
473
474
475
476
477
	/* count the number of block first */
	n_blocks = get_irp_n_blocks();

	/* create all the necessary types and entities. Note that the
	 * types must have a fixed layout, because we are already running in the
	 * backend */
	counter_id    = new_id_from_str("__FIRMPROF__BLOCK_COUNTS");
	bblock_counts = new_array_entity(counter_id, n_blocks);

	filename_id  = new_id_from_str("__FIRMPROF__FILE_NAME");
	ent_filename = new_static_string_entity(filename_id, filename);

	/* initialize block id array and instrument blocks */
	wd.id  = 0;
Christian Würdig's avatar
Christian Würdig committed
478
	for (n = get_irp_n_irgs() - 1; n >= 0; --n) {
479
480
		ir_graph *irg = get_irp_irg(n);
		instrument_irg(irg, bblock_counts, &wd);
481
	}
482

483
	return gen_initializer_irg(ent_filename, bblock_counts, n_blocks);
484
485
}

486
static unsigned int *parse_profile(const char *filename, unsigned int num_blocks)
487
{
488
489
490
491
	FILE *f = fopen(filename, "rb");
	if (!f) {
		DBG((dbg, LEVEL_2, "Failed to open profile file (%s)\n", filename));
		return NULL;
492
493
	}

494
	/* check header */
495
496
497
	uint32_t *result = NULL;
	char      buf[8];
	size_t    ret = fread(buf, 8, 1, f);
498
499
500
501
	if (ret == 0 || strncmp(buf, "firmprof", 8) != 0) {
		DBG((dbg, LEVEL_2, "Broken fileheader in profile\n"));
		goto end;
	}
502

503
	result = XMALLOCN(unsigned int, num_blocks);
504
505
506

	/* The profiling output format is defined to be a sequence of integer
	 * values stored little endian format. */
507
	for (unsigned i = 0; i < num_blocks; ++i) {
Manuel Mohr's avatar
Manuel Mohr committed
508
		unsigned char bytes[4];
509

Manuel Mohr's avatar
Manuel Mohr committed
510
		if ((ret = fread(bytes, 1, 4, f)) < 1)
511
512
513
514
515
516
517
			break;

		result[i] = (bytes[0] <<  0) | (bytes[1] <<  8)
		          | (bytes[2] << 16) | (bytes[3] << 24);
	}

	if (ret < 1) {
518
		DBG((dbg, LEVEL_4, "Failed to read counters... (size: %u)\n",
519
			sizeof(unsigned int) * num_blocks));
520
		free(result);
521
522
523
524
525
526
		result = NULL;
	}

end:
	fclose(f);
	return result;
527
}
528

529
/**
530
 * Reads the corresponding profile info file if it exists.
531
 */
532
533
534
535
536
537
538
539
540
static void block_associate_walker(ir_node *bb, void *env)
{
	block_assoc_t *b = (block_assoc_t*) env;
	execcount_t query;

	query.block = get_irn_node_nr(bb);
	query.count = b->counters[(b->i)++];
	DBG((dbg, LEVEL_4, "execcount(%+F, %u): %u\n", bb, query.block,
	    query.count));
yb9976's avatar
yb9976 committed
541
	(void)set_insert(execcount_t, profile, &query, sizeof(query), query.block);
542
}
543

544
545
static void irp_associate_blocks(block_assoc_t *env)
{
546
	for (int n = get_irp_n_irgs() - 1; n >= 0; --n) {
547
548
		ir_graph *irg = get_irp_irg(n);
		irg_block_walk_graph(irg, block_associate_walker, NULL, env);
549
	}
550
}
551

552
void ir_profile_free(void)
553
{
554
	if (profile) {
555
		del_set(profile);
556
557
558
559
560
561
		profile = NULL;
	}

	if (hook != NULL) {
		dump_remove_node_info_callback(hook);
		hook = NULL;
562
	}
563
564
}

565
bool ir_profile_read(const char *filename)
Adam Szalkowski's avatar
Adam Szalkowski committed
566
{
567
568
	block_assoc_t env;
	FIRM_DBG_REGISTER(dbg, "firm.ir.profile");
Adam Szalkowski's avatar
Adam Szalkowski committed
569

570
571
572
573
574
	unsigned n_blocks = get_irp_n_blocks();
	env.i        = 0;
	env.counters = parse_profile(filename, n_blocks);
	if (!env.counters)
		return false;
575

576
577
	ir_profile_free();
	profile = new_set(cmp_execcount, 16);
578

579
	irp_associate_blocks(&env);
580
	free(env.counters);
581

582
583
584
	/* register the vcg hook */
	hook = dump_add_node_info_callback(dump_profile_node_info, NULL);
	return 1;
585
}
586

587
588
589
590
typedef struct initialize_execfreq_env_t {
	double freq_factor;
} initialize_execfreq_env_t;

591
592
static void initialize_execfreq(ir_node *block, void *data)
{
593
594
595
	const initialize_execfreq_env_t *env
		= (const initialize_execfreq_env_t*) data;
	ir_graph *irg = get_irn_irg(block);
596
597
	double freq;

598
	if (block == get_irg_start_block(irg) || block == get_irg_end_block(irg)) {
599
600
		freq = 1.0;
	} else {
Michael Beck's avatar
Michael Beck committed
601
		freq = ir_profile_get_block_execcount(block);
602
		freq *= env->freq_factor;
603
		if (freq < MIN_EXECFREQ)
604
			freq = MIN_EXECFREQ;
605
606
	}

607
	set_block_execfreq(block, freq);
608
609
}

610
static void ir_set_execfreqs_from_profile(ir_graph *irg)
611
{
612
	/* Find the first block containing instructions */
613
614
	ir_node *start_block = get_irg_start_block(irg);
	unsigned count       = ir_profile_get_block_execcount(start_block);
615
	if (count == 0) {
616
		/* the function was never executed, so fallback to estimated freqs */
617
618
		ir_estimate_execfreq(irg);
		return;
619
620
	}

621
	initialize_execfreq_env_t env;
622
	env.freq_factor = 1.0 / count;
623
	irg_block_walk_graph(irg, initialize_execfreq, NULL, &env);
624
}
625

626
627
628
629
630
631
void ir_create_execfreqs_from_profile(void)
{
	for (int n = get_irp_n_irgs() - 1; n >= 0; --n) {
		ir_graph *irg = get_irp_irg(n);
		ir_set_execfreqs_from_profile(irg);
	}
632
}