bemain.c 18.2 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
 */

6
/**
Christian Würdig's avatar
Christian Würdig committed
7
8
9
10
 * @file
 * @brief       Main Backend driver.
 * @author      Sebastian Hack
 * @date        25.11.2004
11
 */
12

13
#include <stdio.h>
14

Matthias Braun's avatar
Matthias Braun committed
15
16
#include "lc_opts.h"
#include "lc_opts_enum.h"
17

18
#include "ident_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
19
#include "obst.h"
20
#include "statev.h"
Sebastian Hack's avatar
Sebastian Hack committed
21
#include "irprog.h"
Sebastian Hack's avatar
Sebastian Hack committed
22
#include "irgopt.h"
Daniel Grund's avatar
Daniel Grund committed
23
#include "irdump.h"
Sebastian Hack's avatar
Sebastian Hack committed
24
25
#include "irdom_t.h"
#include "iredges_t.h"
26
#include "irloop_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
27
#include "irtools.h"
28
#include "irverify.h"
Matthias Braun's avatar
Matthias Braun committed
29
#include "iroptimize.h"
Christian Würdig's avatar
Christian Würdig committed
30
#include "firmstat.h"
31
#include "execfreq_t.h"
32
#include "irprofile.h"
33
#include "ircons.h"
34
#include "util.h"
Sebastian Hack's avatar
Sebastian Hack committed
35

36
#include "bearch.h"
Sebastian Hack's avatar
Sebastian Hack committed
37
#include "be_t.h"
38
#include "bediagnostic.h"
39
#include "begnuas.h"
40
#include "bemodule.h"
41
#include "beutil.h"
42
#include "benode.h"
43
#include "besched.h"
44
#include "belistsched.h"
Matthias Braun's avatar
Matthias Braun committed
45
#include "belive.h"
46
47
48
#include "bera.h"
#include "bechordal_t.h"
#include "beifg.h"
49
#include "becopystat.h"
50
#include "bessadestr.h"
Christian Würdig's avatar
Christian Würdig committed
51
#include "belower.h"
52
#include "bespillutil.h"
53
#include "bestat.h"
54
#include "beverify.h"
55
#include "beirg.h"
56
#include "bestack.h"
57
#include "beemitter.h"
Sebastian Hack's avatar
Sebastian Hack committed
58
59

/* options visible for anyone */
60
be_options_t be_options = {
61
62
63
64
65
66
67
68
69
70
	.dump_flags           = DUMP_NONE,
	.timing               = false,
	.opt_profile_generate = false,
	.opt_profile_use      = false,
	.omit_fp              = false,
	.pic                  = false,
	.do_verify            = true,
	.ilp_server           = "",
	.ilp_solver           = "",
	.verbose_asm          = true,
Sebastian Hack's avatar
Sebastian Hack committed
71
72
73
};

/* back end instruction set architecture to use */
74
arch_isa_if_t const *isa_if = NULL;
Michael Beck's avatar
Michael Beck committed
75

Sebastian Hack's avatar
Sebastian Hack committed
76
77
/* possible dumping options */
static const lc_opt_enum_mask_items_t dump_items[] = {
78
	{ "none",       DUMP_NONE },
Sebastian Hack's avatar
Sebastian Hack committed
79
80
81
	{ "initial",    DUMP_INITIAL },
	{ "sched",      DUMP_SCHED  },
	{ "prepared",   DUMP_PREPARED },
82
	{ "regalloc",   DUMP_RA },
Sebastian Hack's avatar
Sebastian Hack committed
83
	{ "final",      DUMP_FINAL },
84
85
	{ "be",         DUMP_BE },
	{ "all",        2 * DUMP_BE - 1 },
Sebastian Hack's avatar
Sebastian Hack committed
86
87
88
89
	{ NULL,         0 }
};

static lc_opt_enum_mask_var_t dump_var = {
90
	&be_options.dump_flags, dump_items
91
92
};

Sebastian Hack's avatar
Sebastian Hack committed
93
static const lc_opt_table_entry_t be_main_options[] = {
94
95
96
	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     ("pic",        "create PIC code",                                     &be_options.pic),
Matthias Braun's avatar
Matthias Braun committed
97
	LC_OPT_ENT_BOOL     ("verify",     "verify the backend irg",                              &be_options.do_verify),
98
	LC_OPT_ENT_BOOL     ("time",       "get backend timing statistics",                       &be_options.timing),
99
100
101
	LC_OPT_ENT_BOOL     ("profilegenerate", "instrument the code for execution count profiling", &be_options.opt_profile_generate),
	LC_OPT_ENT_BOOL     ("profileuse",      "use existing profile data",                         &be_options.opt_profile_use),
	LC_OPT_ENT_BOOL     ("verboseasm", "enable verbose assembler output",                        &be_options.verbose_asm),
102

103
104
	LC_OPT_ENT_STR("ilp.server", "the ilp server name", &be_options.ilp_server),
	LC_OPT_ENT_STR("ilp.solver", "the ilp solver name", &be_options.ilp_solver),
105
	LC_OPT_LAST
Sebastian Hack's avatar
Sebastian Hack committed
106
107
};

108
109
static be_module_list_entry_t *isa_ifs         = NULL;
static bool                    isa_initialized = false;
110

111
asm_constraint_flags_t be_asm_constraint_flags[256];
112
113
114
115

void be_set_constraint_support(asm_constraint_flags_t const flags, char const *const constraints)
{
	for (char const *i = constraints; *i != '\0'; ++i) {
116
		be_asm_constraint_flags[(unsigned char)*i] = flags;
117
118
	}
}
119

120
121
static void be_init_default_asm_constraint_flags(void)
{
122
123
	for (size_t i = 0; i != ARRAY_SIZE(be_asm_constraint_flags); ++i) {
		be_asm_constraint_flags[i] = ASM_CONSTRAINT_FLAG_INVALID;
124
	}
125
126
127

	be_set_constraint_support(ASM_CONSTRAINT_FLAG_MODIFIER_EARLYCLOBBER, "&");

128
	/* List of constraints supported by gcc for any machine (or at least
129
130
	 * recognized). Mark them as NO_SUPPORT so we can differentiate them
	 * from INVALID. Backends should change the flags they support. */
131
	char const *const gcc_common_flags = "%,0123456789<>EFGHIJKLMNOPVXgimoprs";
132
	be_set_constraint_support(ASM_CONSTRAINT_FLAG_NO_SUPPORT, gcc_common_flags);
133
134
	/* Skip whitespace.
	 * TODO '*' actually penalizes the selection of the next constraint letter.
135
136
137
138
	 * We do not support this, yet.
	 * TODO '!' and '?' actually penalize an alternative of a multi alternative
	 * constraint.  We do not support this, yet. */
	be_set_constraint_support(ASM_CONSTRAINT_FLAG_NONE, "\t\n\r !*?");
139
140
}

141
142
143
144
static void initialize_isa(void)
{
	if (isa_initialized)
		return;
145
	be_init_default_asm_constraint_flags();
146
	isa_if->init();
Matthias Braun's avatar
Matthias Braun committed
147
148
149
150
151
152
153
154
155
	isa_initialized = true;
}

static void finish_isa(void)
{
	if (isa_initialized) {
		isa_if->finish();
		isa_initialized = false;
	}
156
157
}

158
asm_constraint_flags_t be_parse_asm_constraints(const char *constraint)
159
{
160
161
	initialize_isa();

162
163
164
165
166
167
168
169
170
	asm_constraint_flags_t flags;
	char            const *c = constraint;
	switch (*c) {
	case '=': ++c; flags = ASM_CONSTRAINT_FLAG_MODIFIER_WRITE; break;
	case '+': ++c; flags = ASM_CONSTRAINT_FLAG_MODIFIER_READ | ASM_CONSTRAINT_FLAG_MODIFIER_WRITE; break;
	default:       flags = ASM_CONSTRAINT_FLAG_MODIFIER_READ; break;
	}

	for (; *c != '\0'; ++c) {
171
172
		switch (*c) {
		case '#':
173
			/* text until comma is a comment */
174
			while (*c != 0 && *c != ',')
175
176
				++c;
			break;
177
178

		default:
179
			flags |= be_asm_constraint_flags[(unsigned char)*c];
180
181
182
183
184
185
186
			break;
		}
	}

	return flags;
}

187
int be_is_valid_clobber(const char *clobber)
188
{
189
190
	initialize_isa();

191
192
193
	/* 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)
194
		return 1;
195
196
	/* cc (condition code) is always valid */
	if (strcmp(clobber, "cc") == 0)
197
		return 1;
198

199
	return isa_if->is_valid_clobber(clobber);
200
201
}

202
203
void be_register_isa_if(const char *name, const arch_isa_if_t *isa)
{
204
	if (isa_if == NULL)
205
206
207
208
209
		isa_if = isa;

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

210
static void be_opt_register(void)
Sebastian Hack's avatar
Sebastian Hack committed
211
{
Matthias Braun's avatar
Matthias Braun committed
212
	static bool run_once = false;
213
	if (run_once)
214
		return;
Matthias Braun's avatar
Matthias Braun committed
215
	run_once = true;
216

Matthias Braun's avatar
Matthias Braun committed
217
	lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
218
	lc_opt_add_table(be_grp, be_main_options);
219
220
221

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

	be_init_modules();
224
}
Sebastian Hack's avatar
Sebastian Hack committed
225

226
/* Parse one argument. */
227
228
int be_parse_arg(const char *arg)
{
229
	lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
Michael Beck's avatar
Michael Beck committed
230
	if (strcmp(arg, "help") == 0 || (arg[0] == '?' && arg[1] == '\0')) {
231
		lc_opt_print_help_for_entry(be_grp, '-', stdout);
Michael Beck's avatar
Michael Beck committed
232
233
		return -1;
	}
234
	return lc_opt_from_single_arg(be_grp, arg);
235
236
}

237
238
239
void be_check_verify_result(bool fine, ir_graph *irg)
{
	if (!fine) {
240
		be_errorf(NULL, "verifier failed; trying to write assert graph and abort");
241
242
243
244
245
		dump_ir_graph(irg, "assert");
		abort();
	}
}

Christian Würdig's avatar
Christian Würdig committed
246
/* Perform schedule verification if requested. */
Matthias Braun's avatar
Matthias Braun committed
247
static void be_sched_verify(ir_graph *irg)
248
{
Matthias Braun's avatar
Matthias Braun committed
249
250
	if (be_options.do_verify) {
		be_timer_push(T_VERIFY);
251
252
		bool fine = be_verify_schedule(irg);
		be_check_verify_result(fine, irg);
Matthias Braun's avatar
Matthias Braun committed
253
		be_timer_pop(T_VERIFY);
Christian Würdig's avatar
Christian Würdig committed
254
255
256
	}
}

257
258
259
260
261
262
263
264
265
266
static void be_regalloc_verify(ir_graph *const irg, bool const ignore_sp_problems)
{
	if (be_options.do_verify) {
		be_timer_push(T_VERIFY);
		bool const fine = be_verify_register_allocation(irg, ignore_sp_problems);
		be_check_verify_result(fine, irg);
		be_timer_pop(T_VERIFY);
	}
}

267
268
/* Initialize the Firm backend. Must be run first in init_firm()! */
void firm_be_init(void)
269
{
Sebastian Hack's avatar
Sebastian Hack committed
270
	be_opt_register();
271
	be_init_modules();
272
}
273

yb9976's avatar
yb9976 committed
274
275
276
/* Finalize the Firm backend. */
void firm_be_finish(void)
{
Matthias Braun's avatar
Matthias Braun committed
277
	finish_isa();
yb9976's avatar
yb9976 committed
278
279
280
	be_quit_modules();
}

281
282
283
/* Returns the backend parameter */
const backend_params *be_get_backend_param(void)
{
284
	initialize_isa();
285
	return isa_if->get_params();
286
287
}

Manuel Mohr's avatar
Manuel Mohr committed
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
int be_is_big_endian(void)
{
	return be_get_backend_param()->byte_order_big_endian;
}

unsigned be_get_machine_size(void)
{
	return be_get_backend_param()->machine_size;
}

ir_mode *be_get_mode_float_arithmetic(void)
{
	return be_get_backend_param()->mode_float_arithmetic;
}

ir_type *be_get_type_long_long(void)
{
	return be_get_backend_param()->type_long_long;
}

ir_type *be_get_type_unsigned_long_long(void)
{
	return be_get_backend_param()->type_unsigned_long_long;
}

ir_type *be_get_type_long_double(void)
{
	return be_get_backend_param()->type_long_double;
}

318
319
320
321
322
float_int_conversion_overflow_style_t be_get_float_int_overflow(void)
{
	return be_get_backend_param()->float_int_overflow;
}

323
324
325
326
327
328
/**
 * 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
 */
Matthias Braun's avatar
Matthias Braun committed
329
330
static be_main_env_t *be_init_env(be_main_env_t *const env,
                                  char const *const compilation_unit_name)
Sebastian Hack's avatar
Sebastian Hack committed
331
{
Sebastian Hack's avatar
Sebastian Hack committed
332
	memset(env, 0, sizeof(*env));
333
	env->ent_trampoline_map   = pmap_create();
334
	env->pic_trampolines_type = new_type_segment(NEW_IDENT("$PIC_TRAMPOLINE_TYPE"), tf_none);
335
	env->ent_pic_symbol_map   = pmap_create();
336
	env->pic_symbols_type     = new_type_segment(NEW_IDENT("$PIC_SYMBOLS_TYPE"), tf_none);
337
	env->cup_name             = compilation_unit_name;
338
339

	isa_if->begin_codegeneration();
340

341
	memset(be_asm_constraint_flags, 0, sizeof(be_asm_constraint_flags));
Sebastian Hack's avatar
Sebastian Hack committed
342
343

	return env;
344
345
}

346
347
348
/**
 * Called when the be_main_env_t can be destroyed.
 */
Sebastian Hack's avatar
Sebastian Hack committed
349
static void be_done_env(be_main_env_t *env)
350
{
351
	isa_if->end_codegeneration();
352
353
	pmap_destroy(env->ent_trampoline_map);
	pmap_destroy(env->ent_pic_symbol_map);
354
355
	free_type(env->pic_trampolines_type);
	free_type(env->pic_symbols_type);
Sebastian Hack's avatar
Sebastian Hack committed
356
}
Sebastian Hack's avatar
Sebastian Hack committed
357

Michael Beck's avatar
Michael Beck committed
358
/**
359
 * Prepare a backend graph for code generation and initialize its irg
Michael Beck's avatar
Michael Beck committed
360
 */
361
static void initialize_birg(be_irg_t *birg, ir_graph *irg, be_main_env_t *env)
Sebastian Hack's avatar
Sebastian Hack committed
362
{
363
364
365
	/* don't duplicate locals in backend when dumping... */
	ir_remove_dump_flags(ir_dump_flag_consts_local);

366
	be_dump(DUMP_INITIAL, irg, "begin");
367

368
369
370
371
372
	assure_irg_properties(irg,
		IR_GRAPH_PROPERTY_NO_BADS
		| IR_GRAPH_PROPERTY_NO_UNREACHABLE_CODE
		| IR_GRAPH_PROPERTY_NO_CRITICAL_EDGES
		| IR_GRAPH_PROPERTY_MANY_RETURNS);
yb9976's avatar
yb9976 committed
373

374
375
	memset(birg, 0, sizeof(*birg));
	birg->main_env = env;
376
	obstack_init(&birg->obst);
377
	irg->be_data = birg;
Sebastian Hack's avatar
Sebastian Hack committed
378

379
	be_info_init_irg(irg);
380
	birg->lv = be_liveness_new(irg);
Sebastian Hack's avatar
Sebastian Hack committed
381
382
}

Matthias Braun's avatar
Matthias Braun committed
383
int be_timing;
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413

static const char *get_timer_name(be_timer_id_t id)
{
	switch (id) {
	case T_ABI:            return "abi";
	case T_CODEGEN:        return "codegen";
	case T_RA_PREPARATION: return "ra_preparation";
	case T_SCHED:          return "sched";
	case T_CONSTR:         return "constr";
	case T_FINISH:         return "finish";
	case T_EMIT:           return "emit";
	case T_VERIFY:         return "verify";
	case T_OTHER:          return "other";
	case T_HEIGHTS:        return "heights";
	case T_LIVE:           return "live";
	case T_EXECFREQ:       return "execfreq";
	case T_SSA_CONSTR:     return "ssa_constr";
	case T_RA_EPILOG:      return "ra_epilog";
	case T_RA_CONSTR:      return "ra_constr";
	case T_RA_SPILL:       return "ra_spill";
	case T_RA_SPILL_APPLY: return "ra_spill_apply";
	case T_RA_COLOR:       return "ra_color";
	case T_RA_IFG:         return "ra_ifg";
	case T_RA_COPYMIN:     return "ra_copymin";
	case T_RA_SSA:         return "ra_ssa";
	case T_RA_OTHER:       return "ra_other";
	}
	return "unknown";
}
ir_timer_t *be_timers[T_LAST+1];
414

415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
static void dummy_after_transform(ir_graph *irg, const char *name)
{
	(void)irg;
	(void)name;
}

after_transform_func be_after_transform = dummy_after_transform;

void be_set_after_transform_func(after_transform_func after_transform)
{
	be_after_transform = after_transform;
}

void be_after_irp_transform(const char *name)
{
	if (be_after_transform == NULL)
		return;

433
	foreach_irp_irg_r(i, irg) {
434
435
436
437
		be_after_transform(irg, name);
	}
}

438
439
void be_lower_for_target(void)
{
440
441
	initialize_isa();

442
443
	isa_if->lower_for_target();
	/* set the phase to low */
444
	foreach_irp_irg_r(i, irg) {
445
446
		assert(!irg_is_constrained(irg, IR_GRAPH_CONSTRAINT_TARGET_LOWERED));
		add_irg_constraints(irg, IR_GRAPH_CONSTRAINT_TARGET_LOWERED);
447
448
449
	}
}

Michael Beck's avatar
Michael Beck committed
450
451
452
453
/**
 * The Firm backend main loop.
 * Do architecture specific lowering for all graphs
 * and call the architecture specific code generator.
454
455
 *
 * @param file_handle   the file handle the output will be written to
456
 * @param cup_name      name of the compilation unit
Michael Beck's avatar
Michael Beck committed
457
 */
458
static void be_main_loop(FILE *file_handle, const char *cup_name)
459
{
460
	be_timing = be_options.timing;
Matthias Braun's avatar
Matthias Braun committed
461

462
	/* perform target lowering if it didn't happen yet */
463
	if (get_irp_n_irgs() > 0 && !irg_is_constrained(get_irp_irg(0), IR_GRAPH_CONSTRAINT_TARGET_LOWERED))
464
465
		be_lower_for_target();

Matthias Braun's avatar
Matthias Braun committed
466
	if (be_timing) {
467
468
469
		for (be_timer_id_t t = T_FIRST; t < T_LAST+1; ++t) {
			be_timers[t] = ir_timer_new();
			ir_timer_init_parent(be_timers[t]);
470
		}
471
	}
472

473
474
	be_emit_init(file_handle);

Matthias Braun's avatar
Matthias Braun committed
475
	be_main_env_t env;
476
	be_init_env(&env, cup_name);
Matthias Braun's avatar
Matthias Braun committed
477
	be_info_init();
478
479

	be_gas_begin_compilation_unit(&env);
480

Christian Würdig's avatar
Christian Würdig committed
481
	/* First: initialize all birgs */
482
	size_t          num_birgs = 0;
Matthias Braun's avatar
Matthias Braun committed
483
	/* we might need 1 birg more for instrumentation constructor */
484
485
	be_irg_t *const birgs     = ALLOCAN(be_irg_t, get_irp_n_irgs() + 1);
	foreach_irp_irg(i, irg) {
486
487
488
489
		ir_entity *entity = get_irg_entity(irg);
		if (get_entity_linkage(entity) & IR_LINKAGE_NO_CODEGEN)
			continue;
		initialize_birg(&birgs[num_birgs++], irg, &env);
490
491
		if (isa_if->handle_intrinsics)
			isa_if->handle_intrinsics(irg);
492
		be_dump(DUMP_INITIAL, irg, "prepared");
493
	}
Michael Beck's avatar
Michael Beck committed
494

Christian Würdig's avatar
Christian Würdig committed
495
496
497
498
	/*
		Get the filename for the profiling data.
		Beware: '\0' is already included in sizeof(suffix)
	*/
Matthias Braun's avatar
Matthias Braun committed
499
500
	static const char suffix[] = ".prof";
	char prof_filename[256];
501
502
503
	sprintf(prof_filename, "%.*s%s",
	        (int)(sizeof(prof_filename) - sizeof(suffix)), cup_name, suffix);

504
	bool have_profile = false;
505
506
507
	if (be_options.opt_profile_use) {
		bool res = ir_profile_read(prof_filename);
		if (!res) {
508
			be_warningf(NULL, "could not read profile data '%s'", prof_filename);
509
510
511
512
		} else {
			ir_create_execfreqs_from_profile();
			ir_profile_free();
			have_profile = true;
513
514
		}
	}
515

516
	if (num_birgs > 0 && be_options.opt_profile_generate) {
517
		ir_graph *const prof_init_irg = ir_profile_instrument(prof_filename);
518
		assert(prof_init_irg->be_data == NULL);
519
		initialize_birg(&birgs[num_birgs++], prof_init_irg, &env);
520
521
522
523
	}

	if (!have_profile) {
		be_timer_push(T_EXECFREQ);
524
		foreach_irp_irg(i, irg) {
525
526
527
			ir_estimate_execfreq(irg);
		}
		be_timer_pop(T_EXECFREQ);
528
	}
Adam Szalkowski's avatar
Adam Szalkowski committed
529

530
	/* For all graphs */
531
	foreach_irp_irg(i, irg) {
532
533
534
		ir_entity *const entity = get_irg_entity(irg);
		if (get_entity_linkage(entity) & IR_LINKAGE_NO_CODEGEN)
			continue;
Sebastian Hack's avatar
Sebastian Hack committed
535

536
		be_timer_push(T_OTHER);
537
		if (stat_ev_enabled) {
Matthias Braun's avatar
Matthias Braun committed
538
539
540
			stat_ev_ctx_push_fmt("bemain_irg", "%+F", irg);
			stat_ev_ull("bemain_insns_start", be_count_insns(irg));
			stat_ev_ull("bemain_blocks_start", be_count_blocks(irg));
Matthias Braun's avatar
Matthias Braun committed
541
		}
542

543
		/* Verify the initial graph */
Matthias Braun's avatar
Matthias Braun committed
544
545
		if (be_options.do_verify) {
			be_timer_push(T_VERIFY);
546
547
			bool fine = irg_verify(irg);
			be_check_verify_result(fine, irg);
Matthias Braun's avatar
Matthias Braun committed
548
			be_timer_pop(T_VERIFY);
549
550
		}

551
		/* prepare and perform codeselection */
552
		isa_if->prepare_graph(irg);
553

Christian Würdig's avatar
Christian Würdig committed
554
		/* schedule the irg */
555
		be_timer_push(T_SCHED);
556
		be_schedule_graph(irg);
557
		be_timer_pop(T_SCHED);
Sebastian Hack's avatar
Sebastian Hack committed
558

559
		be_dump(DUMP_SCHED, irg, "sched");
Christian Würdig's avatar
Christian Würdig committed
560

Christian Würdig's avatar
Christian Würdig committed
561
		/* check schedule */
Matthias Braun's avatar
Matthias Braun committed
562
		be_sched_verify(irg);
563

564
		/* we switch off optimizations here, because they might cause trouble */
565
		optimization_state_t state;
566
		save_optimization_state(&state);
567
		set_optimize(0);
568
569
		set_opt_cse(0);

570
		/* stuff needs to be done after scheduling but before register allocation */
571
		be_timer_push(T_RA_PREPARATION);
572
		isa_if->before_ra(irg);
573
		be_timer_pop(T_RA_PREPARATION);
574

575
		if (stat_ev_enabled) {
576
			stat_ev_dbl("bemain_costs_before_ra", be_estimate_irg_costs(irg));
Matthias Braun's avatar
Matthias Braun committed
577
578
			stat_ev_ull("bemain_insns_before_ra", be_count_insns(irg));
			stat_ev_ull("bemain_blocks_before_ra", be_count_blocks(irg));
Matthias Braun's avatar
Matthias Braun committed
579
		}
580

581
582
583
		be_timer_push(T_RA_CONSTR);
		/* add CopyKeeps for should_be_different constrained nodes  */
		/* beware: needs schedule due to usage of be_ssa_constr */
584
		be_spill_prepare_for_constraints(irg);
585
586
587
		be_timer_pop(T_RA_CONSTR);
		be_dump(DUMP_RA, irg, "spillprepare");

Matthias Braun's avatar
Matthias Braun committed
588
589
590
591
		if (stat_ev_enabled) {
			be_stat_values(irg);
		}

592
		/* Do register allocation */
593
		be_allocate_registers(irg);
594
		be_regalloc_verify(irg, true);
Matthias Braun's avatar
Matthias Braun committed
595

596
597
598
599
600
		if (stat_ev_enabled) {
			stat_ev_dbl("bemain_costs_after_ra", be_estimate_irg_costs(irg));
			stat_ev_ull("bemain_insns_after_ra", be_count_insns(irg));
			stat_ev_ull("bemain_blocks_after_ra", be_count_blocks(irg));
		}
601

602
		be_dump(DUMP_RA, irg, "ra");
Christian Würdig's avatar
Christian Würdig committed
603

Christian Würdig's avatar
Christian Würdig committed
604
		/* emit assembler code */
605
		be_timer_push(T_EMIT);
606
		isa_if->emit(irg);
607
		be_timer_pop(T_EMIT);
Christian Würdig's avatar
Christian Würdig committed
608

609
610
611
612
613
614
		if (stat_ev_enabled) {
			stat_ev_ull("bemain_insns_finish", be_count_insns(irg));
			stat_ev_ull("bemain_blocks_finish", be_count_blocks(irg));
		}

		be_dump(DUMP_FINAL, irg, "final");
615
		be_regalloc_verify(irg, false);
Christian Würdig's avatar
Christian Würdig committed
616

617
		restore_optimization_state(&state);
618

619
620
621
622
		be_timer_pop(T_OTHER);

		if (be_timing) {
			if (stat_ev_enabled) {
Matthias Braun's avatar
Matthias Braun committed
623
				for (be_timer_id_t t = T_FIRST; t < T_LAST+1; ++t) {
624
625
626
					char buf[128];
					snprintf(buf, sizeof(buf), "bemain_time_%s",
					         get_timer_name(t));
Manuel Mohr's avatar
Manuel Mohr committed
627
					stat_ev_dbl(buf, ir_timer_elapsed_usec(be_timers[t]));
628
				}
Matthias Braun's avatar
Matthias Braun committed
629
			} else {
630
631
				printf("==>> IRG %s <<==\n",
				       get_entity_name(get_irg_entity(irg)));
Matthias Braun's avatar
Matthias Braun committed
632
				for (be_timer_id_t t = T_FIRST; t < T_LAST+1; ++t) {
633
					double val = ir_timer_elapsed_usec(be_timers[t]) / 1000.0;
634
					printf("%-20s: %10.3f msec\n", get_timer_name(t), val);
635
				}
636
			}
Matthias Braun's avatar
Matthias Braun committed
637
			for (be_timer_id_t t = T_FIRST; t < T_LAST+1; ++t) {
638
639
640
				ir_timer_reset(be_timers[t]);
			}
		}
Michael Beck's avatar
BugFix:    
Michael Beck committed
641

642
		be_free_birg(irg);
Sebastian Hack's avatar
Sebastian Hack committed
643
		stat_ev_ctx_pop("bemain_irg");
644
	}
645

646
647
648
	be_gas_end_compilation_unit(&env);
	be_emit_exit();

Sebastian Hack's avatar
Sebastian Hack committed
649
	be_done_env(&env);
650
651

	be_info_free();
652
653
}

Michael Beck's avatar
Michael Beck committed
654
/* Main interface to the frontend. */
655
void be_main(FILE *file_handle, const char *cup_name)
656
{
Matthias Braun's avatar
Matthias Braun committed
657
	ir_timer_t *t = NULL;
658

659
	if (be_options.timing) {
660
		t = ir_timer_new();
661

662
663
		if (ir_timer_enter_high_priority())
			be_warningf(NULL, "could not enter high priority mode");
664

Matthias Braun's avatar
Matthias Braun committed
665
		ir_timer_reset_and_start(t);
666
	}
667

668
	if (stat_ev_enabled) {
669
		const char *dot = strrchr(cup_name, '.');
Sebastian Hack's avatar
Sebastian Hack committed
670
		const char *pos = dot ? dot : cup_name + strlen(cup_name);
671
		char       *buf = ALLOCAN(char, pos - cup_name + 1);
Sebastian Hack's avatar
Sebastian Hack committed
672
		strncpy(buf, cup_name, pos - cup_name);
Sebastian Hack's avatar
Sebastian Hack committed
673
		buf[pos - cup_name] = '\0';
Sebastian Hack's avatar
Sebastian Hack committed
674

675
		stat_ev_ctx_push_str("bemain_compilation_unit", cup_name);
Sebastian Hack's avatar
Sebastian Hack committed
676
	}
677

678
	be_main_loop(file_handle, cup_name);
679

680
	if (be_options.timing) {
Matthias Braun's avatar
Matthias Braun committed
681
682
		ir_timer_stop(t);
		ir_timer_leave_high_priority();
683
		if (stat_ev_enabled) {
684
			stat_ev_dbl("bemain_backend_time", ir_timer_elapsed_msec(t));
685
		} else {
686
			double val = ir_timer_elapsed_usec(t) / 1000.0;
687
			printf("%-20s: %10.3f msec\n", "BEMAINLOOP", val);
688
		}
689
	}
690

691
	if (stat_ev_enabled) {
692
693
		stat_ev_ctx_pop("bemain_compilation_unit");
	}
694
}