bemain.c 30 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

20
/**
Christian Würdig's avatar
Christian Würdig committed
21
22
23
24
25
 * @file
 * @brief       Main Backend driver.
 * @author      Sebastian Hack
 * @date        25.11.2004
 * @version     $Id$
26
 */
Michael Beck's avatar
Michael Beck committed
27
#include "config.h"
28

Sebastian Hack's avatar
Sebastian Hack committed
29
#include <stdarg.h>
30
#include <stdio.h>
31

Matthias Braun's avatar
Matthias Braun committed
32
33
#include "lc_opts.h"
#include "lc_opts_enum.h"
34

Sebastian Hack's avatar
Sebastian Hack committed
35
36
37
38
#include "obst.h"
#include "bitset.h"

#include "irprog.h"
Sebastian Hack's avatar
Sebastian Hack committed
39
#include "irgopt.h"
Sebastian Hack's avatar
Sebastian Hack committed
40
#include "irgraph.h"
Daniel Grund's avatar
Daniel Grund committed
41
#include "irdump.h"
Sebastian Hack's avatar
Sebastian Hack committed
42
43
#include "irdom_t.h"
#include "iredges_t.h"
44
#include "irloop_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
45
#include "irtools.h"
46
#include "irvrfy.h"
47
#include "irprintf.h"
Matthias Braun's avatar
Matthias Braun committed
48
#include "iroptimize.h"
Christian Würdig's avatar
Christian Würdig committed
49
#include "firmstat.h"
50
#include "execfreq.h"
51
#include "irprofile.h"
Sebastian Hack's avatar
Sebastian Hack committed
52

53
#include "bearch.h"
Sebastian Hack's avatar
Sebastian Hack committed
54
#include "be_t.h"
55
#include "bemodule.h"
56
#include "beutil.h"
57
#include "benode.h"
58
#include "beirgmod.h"
59
#include "besched.h"
60
61
#include "belistsched.h"
#include "belive_t.h"
62
63
64
65
#include "bera.h"
#include "bechordal_t.h"
#include "beifg.h"
#include "beifg_impl.h"
Daniel Grund's avatar
Daniel Grund committed
66
#include "becopyopt.h"
67
#include "becopystat.h"
68
#include "bessadestr.h"
Sebastian Hack's avatar
Sebastian Hack committed
69
#include "beabi.h"
Christian Würdig's avatar
Christian Würdig committed
70
#include "belower.h"
Sebastian Hack's avatar
Sebastian Hack committed
71
#include "beschedmris.h"
72
#include "bestat.h"
73
#include "beverify.h"
74
#include "be_dbgout.h"
75
#include "beirg.h"
Sebastian Hack's avatar
Sebastian Hack committed
76

77
78
#define NEW_ID(s) new_id_from_chars(s, sizeof(s) - 1)

79
80
81
82
#ifdef WITH_ILP
#include "beilpsched.h"
#endif /* WITH_ILP */

Sebastian Hack's avatar
Sebastian Hack committed
83
/* options visible for anyone */
Sebastian Hack's avatar
Sebastian Hack committed
84
static be_options_t be_options = {
85
	DUMP_NONE,                         /* dump flags */
86
	BE_TIME_OFF,                       /* no timing */
87
	0,                                 /* no opt profile */
Michael Beck's avatar
Michael Beck committed
88
	0,                                 /* try to omit frame pointer */
89
	0,                                 /* try to omit leaf frame pointer */
90
	0,                                 /* create PIC code */
91
	0,                                 /* create gprof compatible profiling code */
92
	BE_VRFY_WARN,                      /* verification level: warn */
93
	BE_SCHED_LIST,                     /* scheduler: list scheduler */
94
	"linux",                           /* target OS name */
95
	"i44pc52.info.uni-karlsruhe.de",   /* ilp server */
Christian Würdig's avatar
Christian Würdig committed
96
	"cplex",                           /* ilp solver */
Sebastian Hack's avatar
Sebastian Hack committed
97
	0,                                 /* enable statistic event dumping */
98
	"",                                /* print stat events */
Sebastian Hack's avatar
Sebastian Hack committed
99
100
};

101
102
103
/* config file. */
static char config_file[256] = { 0 };

Sebastian Hack's avatar
Sebastian Hack committed
104
/* back end instruction set architecture to use */
105
static const arch_isa_if_t *isa_if = NULL;
Michael Beck's avatar
Michael Beck committed
106

Sebastian Hack's avatar
Sebastian Hack committed
107
108
/* possible dumping options */
static const lc_opt_enum_mask_items_t dump_items[] = {
109
	{ "none",       DUMP_NONE },
Sebastian Hack's avatar
Sebastian Hack committed
110
	{ "initial",    DUMP_INITIAL },
111
	{ "abi",        DUMP_ABI    },
Sebastian Hack's avatar
Sebastian Hack committed
112
113
	{ "sched",      DUMP_SCHED  },
	{ "prepared",   DUMP_PREPARED },
114
	{ "regalloc",   DUMP_RA },
Sebastian Hack's avatar
Sebastian Hack committed
115
	{ "final",      DUMP_FINAL },
116
117
	{ "be",         DUMP_BE },
	{ "all",        2 * DUMP_BE - 1 },
Sebastian Hack's avatar
Sebastian Hack committed
118
119
120
	{ NULL,         0 }
};

Christian Würdig's avatar
Christian Würdig committed
121
122
123
124
125
/* verify options. */
static const lc_opt_enum_int_items_t vrfy_items[] = {
	{ "off",    BE_VRFY_OFF    },
	{ "warn",   BE_VRFY_WARN   },
	{ "assert", BE_VRFY_ASSERT },
Christian Würdig's avatar
Christian Würdig committed
126
	{ NULL,     0 }
Christian Würdig's avatar
Christian Würdig committed
127
};
128

129
130
131
132
133
134
135
136
137
/* scheduling options. */
static const lc_opt_enum_int_items_t sched_items[] = {
	{ "list", BE_SCHED_LIST },
#ifdef WITH_ILP
	{ "ilp",  BE_SCHED_ILP  },
#endif /* WITH_ILP */
	{ NULL,   0 }
};

Sebastian Hack's avatar
Sebastian Hack committed
138
static lc_opt_enum_mask_var_t dump_var = {
139
	&be_options.dump_flags, dump_items
140
141
};

Christian Würdig's avatar
Christian Würdig committed
142
static lc_opt_enum_int_var_t vrfy_var = {
143
	&be_options.vrfy_option, vrfy_items
Christian Würdig's avatar
Christian Würdig committed
144
145
};

146
147
148
149
static lc_opt_enum_int_var_t sched_var = {
	&be_options.scheduler, sched_items
};

Sebastian Hack's avatar
Sebastian Hack committed
150
static const lc_opt_table_entry_t be_main_options[] = {
151
152
153
154
155
156
	LC_OPT_ENT_STR      ("config",     "read another config file containing backend options", config_file, sizeof(config_file)),
	LC_OPT_ENT_ENUM_MASK("dump",       "dump irg on several occasions",                       &dump_var),
	LC_OPT_ENT_BOOL     ("omitfp",     "omit frame pointer",                                  &be_options.omit_fp),
	LC_OPT_ENT_BOOL     ("omitleaffp", "omit frame pointer in leaf routines",                 &be_options.omit_leaf_fp),
	LC_OPT_ENT_BOOL     ("pic",        "create PIC code",                                     &be_options.pic),
	LC_OPT_ENT_BOOL     ("gprof",      "create gprof profiling code",                         &be_options.gprof),
157
	LC_OPT_ENT_ENUM_PTR ("verify",       "verify the backend irg",                              &vrfy_var),
158
159
160
161
	LC_OPT_ENT_BOOL     ("time",       "get backend timing statistics",                       &be_options.timing),
	LC_OPT_ENT_BOOL     ("profile",    "instrument the code for execution count profiling",   &be_options.opt_profile),
	LC_OPT_ENT_ENUM_PTR ("sched",      "select a scheduler",                                  &sched_var),
	LC_OPT_ENT_STR      ("os",         "specify target operating system",                     &be_options.target_os, sizeof(be_options.target_os)),
162
#ifdef FIRM_STATISTICS
163
164
	LC_OPT_ENT_BOOL     ("statev",     "dump statistic events",                               &be_options.statev),
	LC_OPT_ENT_STR      ("filtev",     "filter for stat events (regex if support is active",  &be_options.filtev, sizeof(be_options.filtev)),
165
#endif
166

Christian Würdig's avatar
Christian Würdig committed
167
#ifdef WITH_ILP
168
169
	LC_OPT_ENT_STR ("ilp.server", "the ilp server name", be_options.ilp_server, sizeof(be_options.ilp_server)),
	LC_OPT_ENT_STR ("ilp.solver", "the ilp solver name", be_options.ilp_solver, sizeof(be_options.ilp_solver)),
Christian Würdig's avatar
Christian Würdig committed
170
#endif /* WITH_ILP */
171
	LC_OPT_LAST
Sebastian Hack's avatar
Sebastian Hack committed
172
173
};

174
175
static be_module_list_entry_t *isa_ifs = NULL;

176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239

unsigned short asm_constraint_flags[256];

void be_init_default_asm_constraint_flags(void)
{
	asm_constraint_flags['?'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
	asm_constraint_flags['!'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
	asm_constraint_flags['&'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT
		| ASM_CONSTRAINT_FLAG_MODIFIER_EARLYCLOBBER;
	asm_constraint_flags['%'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT
		| ASM_CONSTRAINT_FLAG_MODIFIER_COMMUTATIVE;
	asm_constraint_flags['!'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;

	asm_constraint_flags['='] = ASM_CONSTRAINT_FLAG_MODIFIER_WRITE
		| ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ;
	asm_constraint_flags['+'] = ASM_CONSTRAINT_FLAG_MODIFIER_READ
		| ASM_CONSTRAINT_FLAG_MODIFIER_WRITE;

	asm_constraint_flags['i'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['s'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['E'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['F'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['G'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['H'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['I'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['J'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['K'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['L'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['M'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['N'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['O'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;
	asm_constraint_flags['P'] = ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;

	asm_constraint_flags['m'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
	asm_constraint_flags['o'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
	asm_constraint_flags['V'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
	asm_constraint_flags['<'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;
	asm_constraint_flags['>'] = ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP;

	asm_constraint_flags['p'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['0'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['1'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['2'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['3'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['4'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['5'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['6'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['7'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['8'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;
	asm_constraint_flags['9'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER;

	asm_constraint_flags['X'] = ASM_CONSTRAINT_FLAG_SUPPORTS_REGISTER
		| ASM_CONSTRAINT_FLAG_SUPPORTS_MEMOP
		| ASM_CONSTRAINT_FLAG_SUPPORTS_IMMEDIATE;

	/* these should have been catched by the parsing code already */
	asm_constraint_flags['#']  = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
	asm_constraint_flags['*']  = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
	asm_constraint_flags[' ']  = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
	asm_constraint_flags['\t'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
	asm_constraint_flags['\n'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
	asm_constraint_flags['\r'] = ASM_CONSTRAINT_FLAG_NO_SUPPORT;
}

240
asm_constraint_flags_t be_parse_asm_constraints(const char *constraint)
241
{
242
	asm_constraint_flags_t  flags = 0;
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
	const char             *c;
	asm_constraint_flags_t  tflags;

	for (c = constraint; *c != '\0'; ++c) {
		switch (*c) {
		case '#':
			/* 'comment' stuff */
			while(*c != 0 && *c != ',')
				++c;
			break;
		case '*':
			/* 'comment' character */
			++c;
			break;
		case ' ':
		case '\t':
		case '\n':
		case '\r':
			break;
		default:
			tflags = asm_constraint_flags[(int) *c];
			if (tflags != 0) {
				flags |= tflags;
			} else {
				flags |= isa_if->parse_asm_constraint(isa_if, &c);
			}
			break;
		}
	}

273
274
275
276
277
278
279
	if ((
	    	flags & ASM_CONSTRAINT_FLAG_MODIFIER_WRITE &&
	    	flags & ASM_CONSTRAINT_FLAG_MODIFIER_NO_WRITE
	    ) || (
	    	flags & ASM_CONSTRAINT_FLAG_MODIFIER_READ &&
	    	flags & ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ
	    )) {
280
281
		flags |= ASM_CONSTRAINT_FLAG_INVALID;
	}
282
283
284
285
286
	if (!(flags & (ASM_CONSTRAINT_FLAG_MODIFIER_READ     |
	               ASM_CONSTRAINT_FLAG_MODIFIER_WRITE    |
	               ASM_CONSTRAINT_FLAG_MODIFIER_NO_WRITE |
	               ASM_CONSTRAINT_FLAG_MODIFIER_NO_READ)
	    )) {
287
288
		flags |= ASM_CONSTRAINT_FLAG_MODIFIER_READ;
	}
289
290
291
292

	return flags;
}

293
int be_is_valid_clobber(const char *clobber)
294
295
296
297
{
	/* memory is a valid clobber. (the frontend has to detect this case too,
	 * because it has to add memory edges to the asm) */
	if (strcmp(clobber, "memory") == 0)
298
		return 1;
299
300
	/* cc (condition code) is always valid */
	if (strcmp(clobber, "cc") == 0)
301
		return 1;
302
303
304
305

	return isa_if->is_valid_clobber(isa_if, clobber);
}

306
307
void be_register_isa_if(const char *name, const arch_isa_if_t *isa)
{
308
	if (isa_if == NULL)
309
310
311
312
313
		isa_if = isa;

	be_add_module_to_list(&isa_ifs, name, (void*) isa);
}

Sebastian Hack's avatar
Sebastian Hack committed
314
315
void be_opt_register(void)
{
316
	lc_opt_entry_t *be_grp;
317
318
	static int run_once = 0;

319
	if (run_once)
320
		return;
321
	run_once = 1;
322

323
324
	be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
	lc_opt_add_table(be_grp, be_main_options);
325
326
327

	be_add_module_list_opt(be_grp, "isa", "the instruction set architecture",
	                       &isa_ifs, (void**) &isa_if);
328
329

	be_init_modules();
330
}
Sebastian Hack's avatar
Sebastian Hack committed
331

332
333
/* Parse one argument. */
int be_parse_arg(const char *arg) {
334
	lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
Michael Beck's avatar
Michael Beck committed
335
	if (strcmp(arg, "help") == 0 || (arg[0] == '?' && arg[1] == '\0')) {
336
		lc_opt_print_help_for_entry(be_grp, '-', stdout);
Michael Beck's avatar
Michael Beck committed
337
338
		return -1;
	}
339
	return lc_opt_from_single_arg(be_grp, NULL, arg, NULL);
340
341
}

342
/** The be parameters returned by default, all off. */
343
static const backend_params be_params = {
344
	0,    /* need dword lowering */
345
	0,    /* don't support inline assembler yet */
346
347
348
349
	NULL, /* will be set later */
	NULL, /* but yet no creator function */
	NULL, /* context for create_intrinsic_fkt */
	NULL, /* no if conversion settings */
350
	NULL, /* no float arithmetic mode */
351
352
	0,    /* no trampoline support: size 0 */
	0,    /* no trampoline support: align 0 */
353
354
	NULL, /* no trampoline support: no trampoline builder */
	4     /* alignment of stack parameter */
355
};
Sebastian Hack's avatar
Sebastian Hack committed
356

Christian Würdig's avatar
Christian Würdig committed
357
/* Perform schedule verification if requested. */
358
static void be_sched_vrfy(be_irg_t *birg, int vrfy_opt) {
Christian Würdig's avatar
Christian Würdig committed
359
	if (vrfy_opt == BE_VRFY_WARN) {
360
		be_verify_schedule(birg);
361
	} else if (vrfy_opt == BE_VRFY_ASSERT) {
362
		assert(be_verify_schedule(birg) && "Schedule verification failed.");
Christian Würdig's avatar
Christian Würdig committed
363
364
365
	}
}

366
367
/* Initialize the Firm backend. Must be run first in init_firm()! */
void firm_be_init(void)
368
{
Sebastian Hack's avatar
Sebastian Hack committed
369
	be_opt_register();
370
	be_init_modules();
371
}
372

yb9976's avatar
yb9976 committed
373
374
375
376
377
378
/* Finalize the Firm backend. */
void firm_be_finish(void)
{
	be_quit_modules();
}

379
380
381
/* Returns the backend parameter */
const backend_params *be_get_backend_param(void)
{
382
383
384
	if (isa_if->get_params)
		return isa_if->get_params();
	return &be_params;
385
386
}

387
388
389
390
391
392
/**
 * Initializes the main environment for the backend.
 *
 * @param env          an empty environment
 * @param file_handle  the file handle where the output will be written to
 */
393
static be_main_env_t *be_init_env(be_main_env_t *env, FILE *file_handle)
Sebastian Hack's avatar
Sebastian Hack committed
394
{
Sebastian Hack's avatar
Sebastian Hack committed
395
	memset(env, 0, sizeof(*env));
396
397
398
399
400
	env->options              = &be_options;
	env->ent_trampoline_map   = pmap_create();
	env->pic_trampolines_type = new_type_class(NEW_ID("$PIC_TRAMPOLINE_TYPE"));
	env->ent_pic_symbol_map   = pmap_create();
	env->pic_symbols_type     = new_type_struct(NEW_ID("$PIC_SYMBOLS_TYPE"));
401
402
403
404

	remove_irp_type(env->pic_trampolines_type);
	remove_irp_type(env->pic_symbols_type);
	set_class_final(env->pic_trampolines_type, 1);
Sebastian Hack's avatar
Sebastian Hack committed
405

406
	memset(asm_constraint_flags, 0, sizeof(asm_constraint_flags));
407
	env->arch_env = arch_env_init(isa_if, file_handle, env);
Sebastian Hack's avatar
Sebastian Hack committed
408

409
	be_dbg_open();
Sebastian Hack's avatar
Sebastian Hack committed
410
	return env;
411
412
}

413
414
415
/**
 * Called when the be_main_env_t can be destroyed.
 */
Sebastian Hack's avatar
Sebastian Hack committed
416
static void be_done_env(be_main_env_t *env)
417
{
Michael Beck's avatar
Michael Beck committed
418
	arch_env_done(env->arch_env);
419
	be_dbg_close();
420

421
422
	pmap_destroy(env->ent_trampoline_map);
	pmap_destroy(env->ent_pic_symbol_map);
423
424
	free_type(env->pic_trampolines_type);
	free_type(env->pic_symbols_type);
Sebastian Hack's avatar
Sebastian Hack committed
425
}
Sebastian Hack's avatar
Sebastian Hack committed
426

427
428
429
430
431
432
433
434
435
/**
 * A wrapper around a firm dumper. Dumps only, if
 * flags are enabled.
 *
 * @param mask    a bitmask containing the reason what will be dumped
 * @param irg     the IR graph to dump
 * @param suffix  the suffix for the dumper
 * @param dumper  the dumper to be called
 */
Sebastian Hack's avatar
Sebastian Hack committed
436
static void dump(int mask, ir_graph *irg, const char *suffix,
437
                 void (*dumper)(ir_graph *, const char *))
Sebastian Hack's avatar
Sebastian Hack committed
438
{
439
	if(be_options.dump_flags & mask)
Christian Würdig's avatar
Christian Würdig committed
440
		be_dump(irg, suffix, dumper);
Sebastian Hack's avatar
Sebastian Hack committed
441
}
442

Michael Beck's avatar
Michael Beck committed
443
/**
444
 * Prepare a backend graph for code generation and initialize its birg
Michael Beck's avatar
Michael Beck committed
445
 */
446
static void initialize_birg(be_irg_t *birg, ir_graph *irg, be_main_env_t *env)
Sebastian Hack's avatar
Sebastian Hack committed
447
{
448
449
450
451
452
453
454
455
456
457
458
459
	memset(birg, 0, sizeof(*birg));
	birg->irg = irg;
	birg->main_env = env;

	edges_deactivate_kind(irg, EDGE_KIND_DEP);
	edges_activate_kind(irg, EDGE_KIND_DEP);

	dump(DUMP_INITIAL, irg, "-begin", dump_ir_block_graph);

	/* set the current graph (this is important for several firm functions) */
	current_ir_graph = irg;

460
461
462
	/* Normalize proj nodes. */
	normalize_proj_nodes(irg);

463
464
	/* we do this before critical edge split. As this produces less returns,
	   because sometimes (= 164.gzip) multiple returns are slower */
465
	normalize_n_returns(irg);
Sebastian Hack's avatar
Sebastian Hack committed
466

Sebastian Hack's avatar
Sebastian Hack committed
467
	/* Remove critical edges */
468
	remove_critical_cf_edges_ex(irg, /*ignore_exception_edges=*/0);
Sebastian Hack's avatar
Sebastian Hack committed
469

Sebastian Hack's avatar
Sebastian Hack committed
470
	/* Ensure, that the ir_edges are computed. */
Sebastian Hack's avatar
Sebastian Hack committed
471
	edges_assure(irg);
Sebastian Hack's avatar
Sebastian Hack committed
472

473
	set_irg_phase_state(irg, phase_backend);
474
	be_info_init_irg(irg);
475
476

	dump(DUMP_INITIAL, irg, "-prepared", dump_ir_block_graph);
Sebastian Hack's avatar
Sebastian Hack committed
477
478
}

Matthias Braun's avatar
Matthias Braun committed
479
480
481
#define BE_TIMER_ONLY(code)   do { if (be_timing) { code; } } while(0)

int be_timing;
Matthias Braun's avatar
Matthias Braun committed
482
483
ir_timer_t *t_abi;
ir_timer_t *t_codegen;
484
ir_timer_t *t_ra_preparation;
Matthias Braun's avatar
Matthias Braun committed
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
ir_timer_t *t_sched;
ir_timer_t *t_constr;
ir_timer_t *t_finish;
ir_timer_t *t_emit;
ir_timer_t *t_other;
ir_timer_t *t_verify;
ir_timer_t *t_heights;
ir_timer_t *t_live;
ir_timer_t *t_execfreq;
ir_timer_t *t_ssa_constr;
ir_timer_t *t_ra_constr;
ir_timer_t *t_ra_prolog;
ir_timer_t *t_ra_epilog;
ir_timer_t *t_ra_spill;
ir_timer_t *t_ra_spill_apply;
ir_timer_t *t_ra_color;
ir_timer_t *t_ra_ifg;
ir_timer_t *t_ra_copymin;
ir_timer_t *t_ra_ssa;
ir_timer_t *t_ra_other;
505

Michael Beck's avatar
Michael Beck committed
506
507
508
509
/**
 * The Firm backend main loop.
 * Do architecture specific lowering for all graphs
 * and call the architecture specific code generator.
510
511
 *
 * @param file_handle   the file handle the output will be written to
512
 * @param cup_name      name of the compilation unit
Michael Beck's avatar
Michael Beck committed
513
 */
514
static void be_main_loop(FILE *file_handle, const char *cup_name)
515
{
Adam Szalkowski's avatar
Adam Szalkowski committed
516
	static const char suffix[] = ".prof";
517
518
519
520
521
522
523

	int           i, num_birgs, stat_active = 0;
	be_main_env_t env;
	char          prof_filename[256];
	be_irg_t      *birgs;
	ir_graph      **irg_list, **backend_irg_list;
	arch_env_t    *arch_env;
524

Matthias Braun's avatar
Matthias Braun committed
525
526
527
	be_timing = (be_options.timing == BE_TIME_ON);

	if (be_timing) {
528
529
		t_abi        = ir_timer_register("bemain_time_beabi",       "be abi introduction");
		t_codegen    = ir_timer_register("bemain_time_codegen",     "codegeneration");
530
		t_ra_preparation = ir_timer_register("bemain_time_ra_preparation", "ra preparation");
531
532
533
534
535
536
537
538
539
540
541
542
543
544
		t_sched      = ir_timer_register("bemain_time_sched",       "scheduling");
		t_constr     = ir_timer_register("bemain_time_constr",      "assure constraints");
		t_finish     = ir_timer_register("bemain_time_finish",      "graph finish");
		t_emit       = ir_timer_register("bemain_time_emiter",      "code emiter");
		t_verify     = ir_timer_register("bemain_time_verify",      "graph verification");
		t_other      = ir_timer_register("bemain_time_other",       "other");
		t_heights    = ir_timer_register("bemain_time_heights",     "heights");
		t_live       = ir_timer_register("bemain_time_liveness",    "be liveness");
		t_execfreq   = ir_timer_register("bemain_time_execfreq",    "execfreq");
		t_ssa_constr = ir_timer_register("bemain_time_ssa_constr",  "ssa reconstruction");
		t_ra_prolog  = ir_timer_register("bemain_time_ra_prolog",   "regalloc prolog");
		t_ra_epilog  = ir_timer_register("bemain_time_ra_epilog",   "regalloc epilog");
		t_ra_constr  = ir_timer_register("bemain_time_ra_constr",   "regalloc constraints");
		t_ra_spill   = ir_timer_register("bemain_time_ra_spill",    "spiller");
Matthias Braun's avatar
Matthias Braun committed
545
		t_ra_spill_apply
546
547
548
549
550
551
			= ir_timer_register("bemain_time_ra_spill_apply", "apply spills");
		t_ra_color   = ir_timer_register("bemain_time_ra_color",    "graph coloring");
		t_ra_ifg     = ir_timer_register("bemain_time_ra_ifg",      "interference graph");
		t_ra_copymin = ir_timer_register("bemain_time_ra_copymin",  "copy minimization");
		t_ra_ssa     = ir_timer_register("bemain_time_ra_ssadestr", "ssa destruction");
		t_ra_other   = ir_timer_register("bemain_time_ra_other",    "regalloc other");
552
	}
553

554
	be_init_env(&env, file_handle);
555
	env.cup_name = cup_name;
Sebastian Hack's avatar
Sebastian Hack committed
556

557
558
	be_dbg_so(cup_name);
	be_dbg_types();
559

560
561
	arch_env = env.arch_env;

562
563
	/* backend may provide an ordered list of irgs where code should be
	 * generated for */
Christian Würdig's avatar
Christian Würdig committed
564
	irg_list         = NEW_ARR_F(ir_graph *, 0);
565
	backend_irg_list = arch_env_get_backend_irg_list(arch_env, &irg_list);
566

Christian Würdig's avatar
Christian Würdig committed
567
	/* we might need 1 birg more for instrumentation constructor */
568
	num_birgs = backend_irg_list ? ARR_LEN(backend_irg_list) : get_irp_n_irgs();
569
	birgs     = ALLOCAN(be_irg_t, num_birgs + 1);
570

571
572
	be_info_init();

Christian Würdig's avatar
Christian Würdig committed
573
	/* First: initialize all birgs */
574
575
	for(i = 0; i < num_birgs; ++i) {
		ir_graph *irg = backend_irg_list ? backend_irg_list[i] : get_irp_irg(i);
576
577
		initialize_birg(&birgs[i], irg, &env);
	}
578
	arch_env_handle_intrinsics(arch_env);
Christian Würdig's avatar
Christian Würdig committed
579
	DEL_ARR_F(irg_list);
Michael Beck's avatar
Michael Beck committed
580

Christian Würdig's avatar
Christian Würdig committed
581
582
583
584
585
	/*
		Get the filename for the profiling data.
		Beware: '\0' is already included in sizeof(suffix)
	*/
	memset(prof_filename, 0, sizeof(prof_filename));
586
	strncpy(prof_filename, cup_name, sizeof(prof_filename) - sizeof(suffix));
Adam Szalkowski's avatar
Adam Szalkowski committed
587
	strcat(prof_filename, suffix);
588

Christian Würdig's avatar
Christian Würdig committed
589
590
591
592
593
	/*
		Next: Either instruments all irgs with profiling code
		or try to read in profile data for current translation unit.
	*/
	if (be_options.opt_profile) {
594
		ir_graph *prof_init_irg = ir_profile_instrument(prof_filename, profile_default);
595
596
		initialize_birg(&birgs[num_birgs], prof_init_irg, &env);
		num_birgs++;
597
	} else {
598
		ir_profile_read(prof_filename);
599
	}
Adam Szalkowski's avatar
Adam Szalkowski committed
600

601
602
603
604
#ifdef FIRM_STATISTICS
	stat_active = stat_is_active();
#endif /* FIRM_STATISTICS */

605
	/* For all graphs */
606
	for (i = 0; i < num_birgs; ++i) {
607
		be_irg_t *birg = &birgs[i];
Christian Würdig's avatar
Christian Würdig committed
608
		ir_graph *irg  = birg->irg;
609
		optimization_state_t state;
610
		const arch_code_generator_if_t *cg_if;
Sebastian Hack's avatar
Sebastian Hack committed
611

612
613
614
		/* set the current graph (this is important for several firm functions) */
		current_ir_graph = irg;

Matthias Braun's avatar
Matthias Braun committed
615
616
617
618
619
		stat_ev_if {
			stat_ev_ctx_push_fobj("bemain_irg", irg);
			be_stat_ev("bemain_insns_start", be_count_insns(irg));
			be_stat_ev("bemain_blocks_start", be_count_blocks(irg));
		}
620

621
		/* stop and reset timers */
Christian Würdig's avatar
Christian Würdig committed
622
		BE_TIMER_PUSH(t_other);   /* t_other */
623

624
625
626
627
628
629
630
631
632
633
634
		/* Verify the initial graph */
		BE_TIMER_PUSH(t_verify);
		if (be_options.vrfy_option == BE_VRFY_WARN) {
			irg_verify(irg, VRFY_ENFORCE_SSA);
			be_check_dominance(irg);
		} else if (be_options.vrfy_option == BE_VRFY_ASSERT) {
			assert(irg_verify(irg, VRFY_ENFORCE_SSA) && "irg verification failed");
			assert(be_check_dominance(irg) && "Dominance verification failed");
		}
		BE_TIMER_POP(t_verify);

635
		/* Get the code generator interface. */
Michael Beck's avatar
Michael Beck committed
636
		cg_if = arch_env_get_code_generator_if(arch_env);
637
638
639
640
641
642
643

		/* get a code generator for this graph. */
		birg->cg = cg_if->init(birg);

		/* some transformations need to be done before abi introduce */
		arch_code_generator_before_abi(birg->cg);

Sebastian Hack's avatar
Sebastian Hack committed
644
		/* implement the ABI conventions. */
Christian Würdig's avatar
Christian Würdig committed
645
		BE_TIMER_PUSH(t_abi);
646
		birg->abi = be_abi_introduce(birg);
Christian Würdig's avatar
Christian Würdig committed
647
		BE_TIMER_POP(t_abi);
Sebastian Hack's avatar
Sebastian Hack committed
648

Christian Würdig's avatar
Christian Würdig committed
649
		dump(DUMP_ABI, irg, "-abi", dump_ir_block_graph);
Christian Würdig's avatar
Christian Würdig committed
650

651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
		/* do local optimizations */
		optimize_graph_df(irg);

		/* we have to do cfopt+remove_critical_edges as we can't have Bad-blocks
		 * or critical edges in the backend */
		optimize_cf(irg);
		remove_critical_cf_edges(irg);

		/* TODO: we often have dead code reachable through out-edges here. So for
		 * now we rebuild edges (as we need correct user count for code selection)
		 */
		edges_deactivate(irg);
		edges_activate(irg);

		dump(DUMP_PREPARED, irg, "-pre_transform", dump_ir_block_graph_sched);

667
668
669
		if (be_options.vrfy_option == BE_VRFY_WARN) {
			be_check_dominance(irg);
			be_verify_out_edges(irg);
670
		} else if (be_options.vrfy_option == BE_VRFY_ASSERT) {
671
672
673
674
			assert(be_verify_out_edges(irg));
			assert(be_check_dominance(irg) && "Dominance verification failed");
		}

675
		/* generate code */
Christian Würdig's avatar
Christian Würdig committed
676
		BE_TIMER_PUSH(t_codegen);
677
		arch_code_generator_prepare_graph(birg->cg);
Christian Würdig's avatar
Christian Würdig committed
678
		BE_TIMER_POP(t_codegen);
Sebastian Hack's avatar
Sebastian Hack committed
679

Sebastian Hack's avatar
Sebastian Hack committed
680
		dump(DUMP_PREPARED, irg, "-prepared", dump_ir_block_graph);
681

682
683
684
		if (be_options.vrfy_option == BE_VRFY_WARN) {
			be_check_dominance(irg);
			be_verify_out_edges(irg);
685
		} else if (be_options.vrfy_option == BE_VRFY_ASSERT) {
686
687
688
689
			assert(be_verify_out_edges(irg));
			assert(be_check_dominance(irg) && "Dominance verification failed");
		}

Matthias Braun's avatar
Matthias Braun committed
690
		BE_TIMER_PUSH(t_execfreq);
691
692
693
		/**
		 * Create execution frequencies from profile data or estimate some
		 */
694
695
		if (ir_profile_has_data())
			birg->exec_freq = ir_create_execfreqs_from_profile(irg);
696
697
698
699
		else {
			/* TODO: edges are corrupt for EDGE_KIND_BLOCK after the local
			 * optimize graph phase merges blocks in the x86 backend */
			edges_deactivate(irg);
700
			birg->exec_freq = compute_execfreq(irg, 10);
701
		}
Matthias Braun's avatar
Matthias Braun committed
702
		BE_TIMER_POP(t_execfreq);
703

704
705
706

		/* disabled for now, fails for EmptyFor.c and XXEndless.c */
		/* be_live_chk_compare(birg); */
707

Christian Würdig's avatar
Christian Würdig committed
708
		/* schedule the irg */
Christian Würdig's avatar
Christian Würdig committed
709
		BE_TIMER_PUSH(t_sched);
710
711
712
713
714
715
716
717
		switch (be_options.scheduler) {
			default:
				fprintf(stderr, "Warning: invalid scheduler (%d) selected, falling back to list scheduler.\n", be_options.scheduler);
			case BE_SCHED_LIST:
				list_sched(birg, &be_options);
				break;
#ifdef WITH_ILP
			case BE_SCHED_ILP:
718
				be_ilp_sched(birg, &be_options);
719
720
721
				break;
#endif /* WITH_ILP */
		};
Christian Würdig's avatar
Christian Würdig committed
722
		BE_TIMER_POP(t_sched);
Sebastian Hack's avatar
Sebastian Hack committed
723

Christian Würdig's avatar
Christian Würdig committed
724
		dump(DUMP_SCHED, irg, "-sched", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
725

Christian Würdig's avatar
Christian Würdig committed
726
		/* check schedule */
Christian Würdig's avatar
Christian Würdig committed
727
		BE_TIMER_PUSH(t_verify);
728
		be_sched_vrfy(birg, be_options.vrfy_option);
Christian Würdig's avatar
Christian Würdig committed
729
		BE_TIMER_POP(t_verify);
730

Christian Würdig's avatar
Christian Würdig committed
731
		/* introduce patterns to assure constraints */
Michael Beck's avatar
Michael Beck committed
732
		BE_TIMER_PUSH(t_constr);
733
		/* we switch off optimizations here, because they might cause trouble */
734
		save_optimization_state(&state);
735
736
		set_optimize(0);
		set_opt_normalize(0);
737
738
		set_opt_cse(0);

739
740
		/* add Keeps for should_be_different constrained nodes  */
		/* beware: needs schedule due to usage of be_ssa_constr */
741
		assure_constraints(birg);
Christian Würdig's avatar
Christian Würdig committed
742
		BE_TIMER_POP(t_constr);
743

Christian Würdig's avatar
Christian Würdig committed
744
		dump(DUMP_SCHED, irg, "-assured", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
745

746
		/* stuff needs to be done after scheduling but before register allocation */
747
		BE_TIMER_PUSH(t_ra_preparation);
748
		arch_code_generator_before_ra(birg->cg);
749
		BE_TIMER_POP(t_ra_preparation);
750

Sebastian Hack's avatar
Sebastian Hack committed
751
		/* connect all stack modifying nodes together (see beabi.c) */
Christian Würdig's avatar
Christian Würdig committed
752
		BE_TIMER_PUSH(t_abi);
753
		be_abi_fix_stack_nodes(birg->abi);
Christian Würdig's avatar
Christian Würdig committed
754
		BE_TIMER_POP(t_abi);
Christian Würdig's avatar
Christian Würdig committed
755

Sebastian Hack's avatar
Sebastian Hack committed
756
		dump(DUMP_SCHED, irg, "-fix_stack", dump_ir_block_graph_sched);
Sebastian Hack's avatar
Sebastian Hack committed
757

Christian Würdig's avatar
Christian Würdig committed
758
		/* check schedule */
Christian Würdig's avatar
Christian Würdig committed
759
		BE_TIMER_PUSH(t_verify);
760
		be_sched_vrfy(birg, be_options.vrfy_option);
Christian Würdig's avatar
Christian Würdig committed
761
		BE_TIMER_POP(t_verify);
Sebastian Hack's avatar
Sebastian Hack committed
762

Matthias Braun's avatar
Matthias Braun committed
763
764
		stat_ev_if {
			stat_ev_dbl("bemain_costs_before_ra",
765
					be_estimate_irg_costs(irg, birg->exec_freq));
Matthias Braun's avatar
Matthias Braun committed
766
767
768
			be_stat_ev("bemain_insns_before_ra", be_count_insns(irg));
			be_stat_ev("bemain_blocks_before_ra", be_count_blocks(irg));
		}
769

770
		/* Do register allocation */
771
		be_allocate_registers(birg);
772

Matthias Braun's avatar
Matthias Braun committed
773
#ifdef FIRM_STATISTICS
774
		stat_ev_dbl("bemain_costs_before_ra", be_estimate_irg_costs(irg, birg->exec_freq));
Matthias Braun's avatar
Matthias Braun committed
775
#endif
776

Christian Würdig's avatar
Christian Würdig committed
777
		dump(DUMP_RA, irg, "-ra", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
778

Christian Würdig's avatar
Christian Würdig committed
779
		/* let the code generator prepare the graph for emitter */
Michael Beck's avatar
Michael Beck committed
780
		BE_TIMER_PUSH(t_finish);
781
		arch_code_generator_after_ra(birg->cg);
Christian Würdig's avatar
Christian Würdig committed
782
		BE_TIMER_POP(t_finish);
Sebastian Hack's avatar
Sebastian Hack committed
783

Christian Würdig's avatar
Christian Würdig committed
784
785
		/* fix stack offsets */
		BE_TIMER_PUSH(t_abi);
786
		be_abi_fix_stack_nodes(birg->abi);
787
		be_remove_dead_nodes_from_schedule(birg);
788
		be_abi_fix_stack_bias(birg->abi);
Christian Würdig's avatar
Christian Würdig committed
789
		BE_TIMER_POP(t_abi);
Christian Würdig's avatar
Christian Würdig committed
790

Christian Würdig's avatar
Christian Würdig committed
791
792
		dump(DUMP_SCHED, irg, "-fix_stack_after_ra", dump_ir_block_graph_sched);

793
		BE_TIMER_PUSH(t_finish);
794
		arch_code_generator_finish(birg->cg);
795
796
		BE_TIMER_POP(t_finish);

797
798
		dump(DUMP_FINAL, irg, "-finish", dump_ir_block_graph_sched);

Matthias Braun's avatar
Matthias Braun committed
799
800
801
802
803
		stat_ev_if {
			be_stat_ev("bemain_insns_finish", be_count_insns(irg));
			be_stat_ev("bemain_blocks_finish", be_count_blocks(irg));
		}

804
		/* check schedule and register allocation */
Christian Würdig's avatar
Christian Würdig committed
805
		BE_TIMER_PUSH(t_verify);
806
		if (be_options.vrfy_option == BE_VRFY_WARN) {
807
			irg_verify(irg, VRFY_ENFORCE_SSA);
808
809
			be_check_dominance(irg);
			be_verify_out_edges(irg);
810
			be_verify_schedule(birg);
Sebastian Hack's avatar
Sebastian Hack committed
811
			be_verify_register_allocation(birg);
812
813
814
		} else if (be_options.vrfy_option == BE_VRFY_ASSERT) {
			assert(irg_verify(irg, VRFY_ENFORCE_SSA) && "irg verification failed");
			assert(be_verify_out_edges(irg) && "out edge verification failed");
815
			assert(be_check_dominance(irg) && "Dominance verification failed");
816
			assert(be_verify_schedule(birg) && "Schedule verification failed");
Sebastian Hack's avatar
Sebastian Hack committed
817
			assert(be_verify_register_allocation(birg)
818
			       && "register allocation verification failed");
819

820
		}
Christian Würdig's avatar
Christian Würdig committed
821
		BE_TIMER_POP(t_verify);
822

Christian Würdig's avatar
Christian Würdig committed
823
		/* emit assembler code */
Michael Beck's avatar
Michael Beck committed
824
		BE_TIMER_PUSH(t_emit);
825
		arch_code_generator_done(birg->cg);
Christian Würdig's avatar
Christian Würdig committed
826
		BE_TIMER_POP(t_emit);
Christian Würdig's avatar
Christian Würdig committed
827

828
		dump(DUMP_FINAL, irg, "-end", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
829
830

		BE_TIMER_PUSH(t_abi);
831
		be_abi_free(birg->abi);
Christian Würdig's avatar
Christian Würdig committed
832
		BE_TIMER_POP(t_abi);
Christian Würdig's avatar
Christian Würdig committed
833

834
		restore_optimization_state(&state);
835

Christian Würdig's avatar
Christian Würdig committed
836
		BE_TIMER_POP(t_other);
Michael Beck's avatar
Michael Beck committed
837

Matthias Braun's avatar
Matthias Braun committed
838
839
#define STOP_AND_RESET_TIMER(timer) do { ir_timer_stop(timer); ir_timer_reset(timer); } while(0)

840
#define LC_EMIT(timer)  \
841
		stat_ev_if {    \
Matthias Braun's avatar
Matthias Braun committed
842
			stat_ev_dbl(ir_timer_get_name(timer), ir_timer_elapsed_msec(timer));  \
843
		} else { \
Matthias Braun's avatar
Matthias Braun committed
844
			printf("%-20s: %8.3lf msec\n", ir_timer_get_description(timer), (double)ir_timer_elapsed_usec(timer) / 1000.0); \
845
		} \
Matthias Braun's avatar
Matthias Braun committed
846
		STOP_AND_RESET_TIMER(timer);
Sebastian Hack's avatar
Sebastian Hack committed
847

848
		BE_TIMER_ONLY(
849
			stat_ev_if {
Matthias Braun's avatar
Matthias Braun committed
850
			} else {
851
852
				printf("==>> IRG %s <<==\n", get_entity_name(get_irg_entity(irg)));
			}
853
854
			LC_EMIT(t_abi);
			LC_EMIT(t_codegen);
855
			LC_EMIT(t_ra_preparation);
856
			LC_EMIT(t_sched);
Matthias Braun's avatar
Matthias Braun committed
857
858
859
			LC_EMIT(t_live);
			LC_EMIT(t_heights);
			LC_EMIT(t_ssa_constr);
860
			LC_EMIT(t_constr);
Matthias Braun's avatar
Matthias Braun committed
861
			LC_EMIT(t_execfreq);
Matthias Braun's avatar
Matthias Braun committed
862
863
864
865
866
867
868
869
870
871
			LC_EMIT(t_ra_prolog);
			LC_EMIT(t_ra_spill);
			LC_EMIT(t_ra_spill_apply);
			LC_EMIT(t_ra_constr);
			LC_EMIT(t_ra_color);
			LC_EMIT(t_ra_ifg);
			LC_EMIT(t_ra_copymin);
			LC_EMIT(t_ra_ssa);
			LC_EMIT(t_ra_epilog);
			LC_EMIT(t_ra_other);
872
873
			LC_EMIT(t_finish);
			LC_EMIT(t_emit);
Christian Würdig's avatar
Christian Würdig committed
874
			LC_EMIT(t_verify);
Michael Beck's avatar
Michael Beck committed
875
			LC_EMIT(t_other);
876
		);
877
#undef LC_EMIT
Michael Beck's avatar
BugFix:    
Michael Beck committed
878

879
		be_free_birg(birg);
880
881
882
883
884
885

        /* switched off due to statistics (statistic module needs all irgs) */
#ifdef FIRM_STATISTICS
		if (! stat_active)
#endif /* FIRM_STATISTICS */
			remove_irp_irg(irg);
Sebastian Hack's avatar
Sebastian Hack committed
886
		stat_ev_ctx_pop("bemain_irg");
887
	}
888
	ir_profile_free();
Sebastian Hack's avatar
Sebastian Hack committed
889
	be_done_env(&env);