bemain.c 18.4 KB
Newer Older
1
2
3
/**
 * Backend driver.
 * @author Sebastian Hack
Christian Würdig's avatar
Christian Würdig committed
4
5
 * @date   25.11.2004
 * @cvsid  $Id$
6
 */
Michael Beck's avatar
Michael Beck committed
7
8
9
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
10

Sebastian Hack's avatar
Sebastian Hack committed
11
12
#include <stdarg.h>

Sebastian Hack's avatar
Sebastian Hack committed
13
14
15
#ifdef WITH_LIBCORE
#include <libcore/lc_opts.h>
#include <libcore/lc_opts_enum.h>
16
#include <libcore/lc_timing.h>
17
#endif /* WITH_LIBCORE */
Sebastian Hack's avatar
Sebastian Hack committed
18

Sebastian Hack's avatar
Sebastian Hack committed
19
20
21
22
#include "obst.h"
#include "bitset.h"

#include "irprog.h"
Sebastian Hack's avatar
Sebastian Hack committed
23
#include "irgopt.h"
Sebastian Hack's avatar
Sebastian Hack committed
24
#include "irgraph.h"
Daniel Grund's avatar
Daniel Grund committed
25
#include "irdump.h"
26
#include "phiclass.h"
Sebastian Hack's avatar
Sebastian Hack committed
27
28
#include "irdom_t.h"
#include "iredges_t.h"
29
#include "irloop_t.h"
Sebastian Hack's avatar
Sebastian Hack committed
30
#include "irtools.h"
Sebastian Hack's avatar
Sebastian Hack committed
31
#include "return.h"
Christian Würdig's avatar
Christian Würdig committed
32
#include "firmstat.h"
Sebastian Hack's avatar
Sebastian Hack committed
33

34
35
36
#include "bearch.h"
#include "firm/bearch_firm.h"
#include "ia32/bearch_ia32.h"
37
38
39
#include "arm/bearch_arm.h"
#include "ppc32/bearch_ppc32.h"
#include "mips/bearch_mips.h"
40

Sebastian Hack's avatar
Sebastian Hack committed
41
42
#include "be_t.h"
#include "benumb_t.h"
43
44
45
#include "beutil.h"
#include "benode_t.h"
#include "beirgmod.h"
Sebastian Hack's avatar
Sebastian Hack committed
46
#include "besched_t.h"
47
48
#include "belistsched.h"
#include "belive_t.h"
49
50
51
52
53
54
#include "bespillbelady.h"
#include "bera.h"
#include "beraextern.h"
#include "bechordal_t.h"
#include "beifg.h"
#include "beifg_impl.h"
Daniel Grund's avatar
Daniel Grund committed
55
#include "becopyopt.h"
56
#include "becopystat.h"
57
#include "bessadestr.h"
Sebastian Hack's avatar
Sebastian Hack committed
58
#include "beabi.h"
Christian Würdig's avatar
Christian Würdig committed
59
#include "belower.h"
Sebastian Hack's avatar
Sebastian Hack committed
60
#include "beschedmris.h"
61
#include "bestat.h"
62
#include "beverify.h"
Sebastian Hack's avatar
Sebastian Hack committed
63
64

/* options visible for anyone */
Sebastian Hack's avatar
Sebastian Hack committed
65
static be_options_t be_options = {
66
67
68
69
	DUMP_NONE,                         /* dump options */
	BE_TIME_OFF,                       /* no timing */
	"i44pc52.info.uni-karlsruhe.de",   /* ilp server */
	"cplex"                            /* ilp solver */
Sebastian Hack's avatar
Sebastian Hack committed
70
71
72
};

/* dump flags */
73
static unsigned dump_flags = 0;
Sebastian Hack's avatar
Sebastian Hack committed
74

Christian Würdig's avatar
Christian Würdig committed
75
76
77
/* verify options */
static unsigned vrfy_option = BE_VRFY_WARN;

Sebastian Hack's avatar
Sebastian Hack committed
78
/* register allocator to use. */
Sebastian Hack's avatar
Sebastian Hack committed
79
static const be_ra_t *ra = &be_ra_chordal_allocator;
80

Sebastian Hack's avatar
Sebastian Hack committed
81
/* back end instruction set architecture to use */
Sebastian Hack's avatar
Sebastian Hack committed
82
static const arch_isa_if_t *isa_if = &ia32_isa_if;
Michael Beck's avatar
Michael Beck committed
83

Christian Würdig's avatar
Christian Würdig committed
84
85
/* mris option */
static int be_enable_mris = 0;
Michael Beck's avatar
Michael Beck committed
86

Sebastian Hack's avatar
Sebastian Hack committed
87
#ifdef WITH_LIBCORE
Daniel Grund's avatar
Daniel Grund committed
88

Sebastian Hack's avatar
Sebastian Hack committed
89
static lc_opt_entry_t *be_grp_root = NULL;
Sebastian Hack's avatar
Sebastian Hack committed
90

Sebastian Hack's avatar
Sebastian Hack committed
91
92
/* possible dumping options */
static const lc_opt_enum_mask_items_t dump_items[] = {
93
	{ "none",       DUMP_NONE },
Sebastian Hack's avatar
Sebastian Hack committed
94
	{ "initial",    DUMP_INITIAL },
95
	{ "abi",        DUMP_ABI    },
Sebastian Hack's avatar
Sebastian Hack committed
96
97
	{ "sched",      DUMP_SCHED  },
	{ "prepared",   DUMP_PREPARED },
98
	{ "regalloc",   DUMP_RA },
Sebastian Hack's avatar
Sebastian Hack committed
99
	{ "final",      DUMP_FINAL },
100
101
	{ "be",         DUMP_BE },
	{ "all",        2 * DUMP_BE - 1 },
Sebastian Hack's avatar
Sebastian Hack committed
102
103
104
105
106
	{ NULL,         0 }
};

/* register allocators */
static const lc_opt_enum_const_ptr_items_t ra_items[] = {
107
	{ "chordal",  &be_ra_chordal_allocator },
Daniel Grund's avatar
:wq    
Daniel Grund committed
108
	{ "external", &be_ra_external_allocator },
Sebastian Hack's avatar
Sebastian Hack committed
109
110
111
112
113
	{ NULL,      NULL }
};

/* instruction set architectures. */
static const lc_opt_enum_const_ptr_items_t isa_items[] = {
114
	{ "ia32",    &ia32_isa_if },
115
#if 0
116
	{ "arm",     &arm_isa_if },
117
	{ "ppc32",   &ppc32_isa_if },
118
	{ "mips",    &mips_isa_if },
119
#endif
Sebastian Hack's avatar
Sebastian Hack committed
120
121
	{ NULL,      NULL }
};
122

Christian Würdig's avatar
Christian Würdig committed
123
124
125
126
127
/* 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
128
	{ NULL,     0 }
Christian Würdig's avatar
Christian Würdig committed
129
};
130

Sebastian Hack's avatar
Sebastian Hack committed
131
132
static lc_opt_enum_mask_var_t dump_var = {
	&dump_flags, dump_items
133
134
};

Sebastian Hack's avatar
Sebastian Hack committed
135
136
137
static lc_opt_enum_const_ptr_var_t ra_var = {
	(const void **) &ra, ra_items
};
138

Sebastian Hack's avatar
Sebastian Hack committed
139
140
141
static lc_opt_enum_const_ptr_var_t isa_var = {
	(const void **) &isa_if, isa_items
};
142

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

Sebastian Hack's avatar
Sebastian Hack committed
147
static const lc_opt_table_entry_t be_main_options[] = {
Sebastian Hack's avatar
Sebastian Hack committed
148
149
150
151
	LC_OPT_ENT_ENUM_MASK("dump",     "dump irg on several occasions",     &dump_var),
	LC_OPT_ENT_ENUM_PTR ("ra",       "register allocator",                &ra_var),
	LC_OPT_ENT_ENUM_PTR ("isa",      "the instruction set architecture",  &isa_var),
	LC_OPT_ENT_NEGBOOL  ("noomitfp", "do not omit frame pointer",         &be_omit_fp),
Christian Würdig's avatar
Christian Würdig committed
152
153
	LC_OPT_ENT_BOOL     ("mris",     "enable mris schedule preparation",  &be_enable_mris),
	LC_OPT_ENT_ENUM_PTR ("vrfy",     "verify the backend irg (off, warn, assert)",  &vrfy_var),
154
	LC_OPT_ENT_BOOL     ("time",     "get backend timing statistics",     &be_options.timing),
155

Christian Würdig's avatar
Christian Würdig committed
156
#ifdef WITH_ILP
157
158
	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
159
#endif /* WITH_ILP */
Sebastian Hack's avatar
Sebastian Hack committed
160
161
162
	{ NULL }
};

163
#endif /* WITH_LIBCORE */
Sebastian Hack's avatar
Sebastian Hack committed
164
165
166
167
168

void be_opt_register(void)
{
#ifdef WITH_LIBCORE
	int i;
Daniel Grund's avatar
:wq    
Daniel Grund committed
169
	lc_opt_entry_t *be_grp_ra;
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
	static int run_once = 0;

	if (! run_once) {
		run_once    = 1;
		be_grp_root = lc_opt_get_grp(firm_opt_get_root(), "be");
		be_grp_ra   = lc_opt_get_grp(be_grp_root, "ra");

		lc_opt_add_table(be_grp_root, be_main_options);

		/* register allocator options */
		for(i = 0; ra_items[i].name != NULL; ++i) {
			const be_ra_t *ra = ra_items[i].value;
			ra->register_options(be_grp_ra);
		}

		/* register isa options */
		for(i = 0; isa_items[i].name != NULL; ++i) {
			const arch_isa_if_t *isa = isa_items[i].value;
			isa->register_options(be_grp_root);
		}
	}
#endif /* WITH_LIBCORE */
}
Sebastian Hack's avatar
Sebastian Hack committed
193

194
195
196
/* Parse one argument. */
int be_parse_arg(const char *arg) {
#ifdef WITH_LIBCORE
Michael Beck's avatar
Michael Beck committed
197
198
199
200
	if (strcmp(arg, "help") == 0 || (arg[0] == '?' && arg[1] == '\0')) {
		lc_opt_print_help(be_grp_root, stdout);
		return -1;
	}
201
	return lc_opt_from_single_arg(be_grp_root, NULL, arg, NULL);
202
203
#else
	return 0;
204
#endif /* WITH_LIBCORE */
205
206
}

207
208
209
210
211
212
213
/** The be parameters returned by default, all off. */
const static backend_params be_params = {
	NULL,
	NULL,
	0,
	NULL,
};
Sebastian Hack's avatar
Sebastian Hack committed
214

Christian Würdig's avatar
Christian Würdig committed
215
216
217
218
219
220
221
222
223
224
/* Perform schedule verification if requested. */
static void be_sched_vrfy(ir_graph *irg, int vrfy_opt) {
	if (vrfy_opt == BE_VRFY_WARN) {
		be_verify_schedule(irg);
	}
	else if (vrfy_opt == BE_VRFY_ASSERT) {
		assert(be_verify_schedule(irg) && "Schedule verification failed.");
	}
}

225
226
/* Initialize the Firm backend. Must be run BEFORE init_firm()! */
const backend_params *be_init(void)
227
{
Sebastian Hack's avatar
Sebastian Hack committed
228
229
230
231
232
233
234
	be_opt_register();

	be_sched_init();
	be_numbering_init();
	be_copy_opt_init();
	copystat_init();
	phi_class_init();
235
236
237
238

	if (isa_if->get_params)
		return isa_if->get_params();
	return &be_params;
239
240
}

241
242
243
244
245
246
/**
 * 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
 */
247
static be_main_env_t *be_init_env(be_main_env_t *env, FILE *file_handle)
Sebastian Hack's avatar
Sebastian Hack committed
248
{
Sebastian Hack's avatar
Sebastian Hack committed
249
	memset(env, 0, sizeof(*env));
Sebastian Hack's avatar
Sebastian Hack committed
250
251
	obstack_init(&env->obst);
	env->arch_env = obstack_alloc(&env->obst, sizeof(env->arch_env[0]));
Sebastian Hack's avatar
Sebastian Hack committed
252
	env->options  = &be_options;
253
	env->options->dump_flags = dump_flags;
254
	FIRM_DBG_REGISTER(env->dbg, "be.main");
Sebastian Hack's avatar
Sebastian Hack committed
255

256
	arch_env_init(env->arch_env, isa_if, file_handle);
Sebastian Hack's avatar
Sebastian Hack committed
257
258
259

	/* Register the irn handler of the architecture */
	if (arch_isa_get_irn_handler(env->arch_env->isa))
Sebastian Hack's avatar
Sebastian Hack committed
260
		arch_env_push_irn_handler(env->arch_env, arch_isa_get_irn_handler(env->arch_env->isa));
261

Michael Beck's avatar
Michael Beck committed
262
263
264
265
266
	/*
	 * Register the node handler of the back end infrastructure.
	 * This irn handler takes care of the platform independent
	 * spill, reload and perm nodes.
	 */
Sebastian Hack's avatar
Sebastian Hack committed
267
	arch_env_push_irn_handler(env->arch_env, &be_node_irn_handler);
Sebastian Hack's avatar
Sebastian Hack committed
268
269
	env->phi_handler = be_phi_handler_new(env->arch_env);
	arch_env_push_irn_handler(env->arch_env, env->phi_handler);
Sebastian Hack's avatar
Sebastian Hack committed
270
271

	return env;
272
273
}

Sebastian Hack's avatar
Sebastian Hack committed
274
static void be_done_env(be_main_env_t *env)
275
{
Sebastian Hack's avatar
Sebastian Hack committed
276
	env->arch_env->isa->impl->done(env->arch_env->isa);
Sebastian Hack's avatar
Sebastian Hack committed
277
	be_phi_handler_free(env->phi_handler);
Sebastian Hack's avatar
Sebastian Hack committed
278
	obstack_free(&env->obst, NULL);
Sebastian Hack's avatar
Sebastian Hack committed
279
}
Sebastian Hack's avatar
Sebastian Hack committed
280

281
282
283
284
285
286
287
288
289
/**
 * 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
290
static void dump(int mask, ir_graph *irg, const char *suffix,
291
                 void (*dumper)(ir_graph *, const char *))
Sebastian Hack's avatar
Sebastian Hack committed
292
{
Sebastian Hack's avatar
Sebastian Hack committed
293
	if(dump_flags & mask)
Christian Würdig's avatar
Christian Würdig committed
294
		be_dump(irg, suffix, dumper);
Sebastian Hack's avatar
Sebastian Hack committed
295
}
296

Michael Beck's avatar
Michael Beck committed
297
298
299
/**
 * Prepare a backend graph for code generation.
 */
Sebastian Hack's avatar
Sebastian Hack committed
300
static void prepare_graph(be_irg_t *birg)
Sebastian Hack's avatar
Sebastian Hack committed
301
{
Sebastian Hack's avatar
Sebastian Hack committed
302
303
	ir_graph *irg = birg->irg;

Sebastian Hack's avatar
Sebastian Hack committed
304
305
	/* Normalize proj nodes. */
	normalize_proj_nodes(irg);
Sebastian Hack's avatar
Sebastian Hack committed
306

Sebastian Hack's avatar
Sebastian Hack committed
307
	/* Make just one return node. */
Sebastian Hack's avatar
Sebastian Hack committed
308
	normalize_one_return(irg);
Sebastian Hack's avatar
Sebastian Hack committed
309

Sebastian Hack's avatar
Sebastian Hack committed
310
311
	/* Remove critical edges */
	remove_critical_cf_edges(irg);
Sebastian Hack's avatar
Sebastian Hack committed
312

Sebastian Hack's avatar
Sebastian Hack committed
313
	/* Compute the dominance information. */
314
	free_dom(irg);
Sebastian Hack's avatar
Sebastian Hack committed
315
	compute_doms(irg);
Sebastian Hack's avatar
Sebastian Hack committed
316

Sebastian Hack's avatar
Sebastian Hack committed
317
318
	/* Ensure, that the ir_edges are computed. */
	edges_activate(irg);
Sebastian Hack's avatar
Sebastian Hack committed
319

Sebastian Hack's avatar
Sebastian Hack committed
320
	/* check, if the dominance property is fulfilled. */
Sebastian Hack's avatar
Sebastian Hack committed
321
	be_check_dominance(irg);
Sebastian Hack's avatar
Sebastian Hack committed
322
323
324

	/* reset the phi handler. */
	be_phi_handler_reset(birg->main_env->phi_handler);
Sebastian Hack's avatar
Sebastian Hack committed
325
326
}

Michael Beck's avatar
Michael Beck committed
327
328
329
330
/**
 * The Firm backend main loop.
 * Do architecture specific lowering for all graphs
 * and call the architecture specific code generator.
331
332
 *
 * @param file_handle   the file handle the output will be written to
Michael Beck's avatar
Michael Beck committed
333
 */
334
static void be_main_loop(FILE *file_handle)
335
{
Sebastian Hack's avatar
Sebastian Hack committed
336
337
	int i, n;
	arch_isa_t *isa;
338
	be_main_env_t env;
339
340
341
	unsigned num_nodes_b = 0;
	unsigned num_nodes_a = 0;
	unsigned num_nodes_r = 0;
Christian Würdig's avatar
Christian Würdig committed
342
	lc_timer_t *t_prolog, *t_abi, *t_codegen, *t_sched, *t_constr, *t_regalloc, *t_finish, *t_emit, *t_other, *t_verify;
343
344
345
346
347
348
349
350
351
352
353
	be_ra_timer_t *ra_timer;

	if (be_options.timing == BE_TIME_ON) {
		t_prolog   = lc_timer_register("prolog",   "prolog");
		t_abi      = lc_timer_register("beabi",    "be abi introduction");
		t_codegen  = lc_timer_register("codegen",  "codegeneration");
		t_sched    = lc_timer_register("sched",    "scheduling");
		t_constr   = lc_timer_register("constr",   "assure constraints");
		t_regalloc = lc_timer_register("regalloc", "register allocation");
		t_finish   = lc_timer_register("finish",   "graph finish");
		t_emit     = lc_timer_register("emiter",   "code emiter");
Christian Würdig's avatar
Christian Würdig committed
354
		t_verify   = lc_timer_register("verify",   "graph verification");
Michael Beck's avatar
Michael Beck committed
355
		t_other    = lc_timer_register("other",    "other");
356
	}
357

358
	be_init_env(&env, file_handle);
Sebastian Hack's avatar
Sebastian Hack committed
359
360

	isa = arch_env_get_isa(env.arch_env);
361

362
	/* for debugging, anchors helps */
Michael Beck's avatar
Michael Beck committed
363
364
	// dump_all_anchors(1);

Christian Würdig's avatar
Christian Würdig committed
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
#define BE_TIMER_PUSH(timer)                                                        \
	if (be_options.timing == BE_TIME_ON) {                                          \
		int res = lc_timer_push(timer);                                             \
		if (vrfy_option == BE_VRFY_ASSERT)                                          \
			assert(res && "Timer already on stack, cannot be pushed twice.");       \
		else if (vrfy_option == BE_VRFY_WARN && ! res)                              \
			fprintf(stderr, "Timer %s already on stack, cannot be pushed twice.\n", \
				lc_timer_get_name(timer));                                          \
	}
#define BE_TIMER_POP(timer)                                                                    \
	if (be_options.timing == BE_TIME_ON) {                                                     \
		lc_timer_t *tmp = lc_timer_pop();                                                      \
		if (vrfy_option == BE_VRFY_ASSERT)                                                     \
			assert(tmp == timer && "Attempt to pop wrong timer.");                             \
		else if (vrfy_option == BE_VRFY_WARN && tmp != timer)                                  \
			fprintf(stderr, "Attempt to pop wrong timer. %s is on stack, trying to pop %s.\n", \
				lc_timer_get_name(tmp), lc_timer_get_name(timer));                             \
		timer = tmp;                                                                           \
	}

Michael Beck's avatar
Michael Beck committed
385
#define BE_TIMER_ONLY(code)   if (be_options.timing == BE_TIME_ON) do { code; } while(0)
386

387
	/* For all graphs */
388
	for (i = 0, n = get_irp_n_irgs(); i < n; ++i) {
389
		ir_graph *irg = get_irp_irg(i);
Sebastian Hack's avatar
Sebastian Hack committed
390
		const arch_code_generator_if_t *cg_if;
Sebastian Hack's avatar
Sebastian Hack committed
391
		be_irg_t birg;
392
		optimization_state_t state;
Sebastian Hack's avatar
Sebastian Hack committed
393

394
395
396
397
398
399
400
401
402
403
		/* stop and reset timers */
		if (be_options.timing == BE_TIME_ON) {
			LC_STOP_AND_RESET_TIMER(t_prolog);
			LC_STOP_AND_RESET_TIMER(t_abi);
			LC_STOP_AND_RESET_TIMER(t_codegen);
			LC_STOP_AND_RESET_TIMER(t_sched);
			LC_STOP_AND_RESET_TIMER(t_constr);
			LC_STOP_AND_RESET_TIMER(t_regalloc);
			LC_STOP_AND_RESET_TIMER(t_finish);
			LC_STOP_AND_RESET_TIMER(t_emit);
Christian Würdig's avatar
Christian Würdig committed
404
			LC_STOP_AND_RESET_TIMER(t_verify);
Michael Beck's avatar
Michael Beck committed
405
			LC_STOP_AND_RESET_TIMER(t_other);
406
		}
Christian Würdig's avatar
Christian Würdig committed
407
		BE_TIMER_PUSH(t_other);   /* t_other */
408

Michael Beck's avatar
Michael Beck committed
409
		BE_TIMER_ONLY(num_nodes_b = get_num_reachable_nodes(irg));
410

Sebastian Hack's avatar
Sebastian Hack committed
411
412
		birg.irg      = irg;
		birg.main_env = &env;
413

414
		DBG((env.dbg, LEVEL_2, "====> IRG: %F\n", irg));
Sebastian Hack's avatar
Sebastian Hack committed
415
		dump(DUMP_INITIAL, irg, "-begin", dump_ir_block_graph);
416

Michael Beck's avatar
Michael Beck committed
417
418
		BE_TIMER_PUSH(t_prolog);

Christian Würdig's avatar
Christian Würdig committed
419
420
421
		be_stat_init_irg(env.arch_env, irg);
		be_do_stat_nodes(irg, "01 Begin");

Sebastian Hack's avatar
Sebastian Hack committed
422
		/* set the current graph (this is important for several firm functions) */
Sebastian Hack's avatar
Sebastian Hack committed
423
		current_ir_graph = birg.irg;
424

Sebastian Hack's avatar
Sebastian Hack committed
425
		/* Get the code generator interface. */
426
		cg_if = isa->impl->get_code_generator_if(isa);
Sebastian Hack's avatar
Sebastian Hack committed
427

Sebastian Hack's avatar
Sebastian Hack committed
428
		/* get a code generator for this graph. */
429
		birg.cg = cg_if->init(&birg);
Christian Würdig's avatar
Christian Würdig committed
430

Sebastian Hack's avatar
Sebastian Hack committed
431
		/* create the code generator and generate code. */
Sebastian Hack's avatar
Sebastian Hack committed
432
433
		prepare_graph(&birg);

Christian Würdig's avatar
Christian Würdig committed
434
435
		BE_TIMER_POP(t_prolog);

Christian Würdig's avatar
Christian Würdig committed
436
		/* some transformations need to be done before abi introduce */
Christian Würdig's avatar
Christian Würdig committed
437
		BE_TIMER_PUSH(t_codegen);
Christian Würdig's avatar
Christian Würdig committed
438
		arch_code_generator_before_abi(birg.cg);
Christian Würdig's avatar
Christian Würdig committed
439
		BE_TIMER_POP(t_codegen);
440

Sebastian Hack's avatar
Sebastian Hack committed
441
		/* implement the ABI conventions. */
Christian Würdig's avatar
Christian Würdig committed
442
		BE_TIMER_PUSH(t_abi);
443
		birg.abi = be_abi_introduce(&birg);
Christian Würdig's avatar
Christian Würdig committed
444
		BE_TIMER_POP(t_abi);
Sebastian Hack's avatar
Sebastian Hack committed
445

Christian Würdig's avatar
Christian Würdig committed
446
		dump(DUMP_ABI, irg, "-abi", dump_ir_block_graph);
Christian Würdig's avatar
Christian Würdig committed
447
448
		be_do_stat_nodes(irg, "02 Abi");

449
		/* generate code */
Christian Würdig's avatar
Christian Würdig committed
450
		BE_TIMER_PUSH(t_codegen);
Sebastian Hack's avatar
Sebastian Hack committed
451
		arch_code_generator_prepare_graph(birg.cg);
Christian Würdig's avatar
Christian Würdig committed
452
		BE_TIMER_POP(t_codegen);
Sebastian Hack's avatar
Sebastian Hack committed
453

Christian Würdig's avatar
Christian Würdig committed
454
455
		be_do_stat_nodes(irg, "03 Prepare");

Sebastian Hack's avatar
Sebastian Hack committed
456
457
		/*
		 * Since the code generator made a lot of new nodes and skipped
Michael Beck's avatar
Michael Beck committed
458
		 * a lot of old ones, we should do dead node elimination here.
Sebastian Hack's avatar
Sebastian Hack committed
459
460
		 * Note that this requires disabling the edges here.
		 */
Sebastian Hack's avatar
Sebastian Hack committed
461
		edges_deactivate(irg);
462
		//dead_node_elimination(irg);
Sebastian Hack's avatar
Sebastian Hack committed
463
		edges_activate(irg);
464

465
466
		/* Compute loop nesting information (for weighting copies) */
		construct_cf_backedges(irg);
Sebastian Hack's avatar
Sebastian Hack committed
467
		dump(DUMP_PREPARED, irg, "-prepared", dump_ir_block_graph);
Michael Beck's avatar
Michael Beck committed
468
		BE_TIMER_ONLY(num_nodes_r = get_num_reachable_nodes(irg));
469

Christian Würdig's avatar
Christian Würdig committed
470
471
		/* let backend prepare scheduling */
		BE_TIMER_PUSH(t_codegen);
Sebastian Hack's avatar
Sebastian Hack committed
472
		arch_code_generator_before_sched(birg.cg);
Christian Würdig's avatar
Christian Würdig committed
473
		BE_TIMER_POP(t_codegen);
Christian Würdig's avatar
Christian Würdig committed
474

Christian Würdig's avatar
Christian Würdig committed
475
		/* schedule the irg */
Christian Würdig's avatar
Christian Würdig committed
476
		BE_TIMER_PUSH(t_sched);
Christian Würdig's avatar
Christian Würdig committed
477
		list_sched(&birg, be_enable_mris);
Christian Würdig's avatar
Christian Würdig committed
478
		BE_TIMER_POP(t_sched);
Sebastian Hack's avatar
Sebastian Hack committed
479

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

Christian Würdig's avatar
Christian Würdig committed
482
		/* check schedule */
Christian Würdig's avatar
Christian Würdig committed
483
		BE_TIMER_PUSH(t_verify);
Christian Würdig's avatar
Christian Würdig committed
484
		be_sched_vrfy(birg.irg, vrfy_option);
Christian Würdig's avatar
Christian Würdig committed
485
		BE_TIMER_POP(t_verify);
486

Christian Würdig's avatar
Christian Würdig committed
487
488
		be_do_stat_nodes(irg, "04 Schedule");

Christian Würdig's avatar
Christian Würdig committed
489
		/* introduce patterns to assure constraints */
Michael Beck's avatar
Michael Beck committed
490
		BE_TIMER_PUSH(t_constr);
491
		/* we switch off optimizations here, because they might cause trouble */
492
		save_optimization_state(&state);
493
494
495
		set_optimize(0);
		set_opt_normalize(0);

496
497
498
		/* add Keeps for should_be_different constrained nodes  */
		/* beware: needs schedule due to usage of be_ssa_constr */
		assure_constraints(&birg);
Christian Würdig's avatar
Christian Würdig committed
499
		BE_TIMER_POP(t_constr);
500

Christian Würdig's avatar
Christian Würdig committed
501
		dump(DUMP_SCHED, irg, "-assured", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
502
503
		be_do_stat_nodes(irg, "05 Constraints");

Sebastian Hack's avatar
Sebastian Hack committed
504
		/* connect all stack modifying nodes together (see beabi.c) */
Christian Würdig's avatar
Christian Würdig committed
505
		BE_TIMER_PUSH(t_abi);
Sebastian Hack's avatar
Sebastian Hack committed
506
		be_abi_fix_stack_nodes(birg.abi, NULL);
Christian Würdig's avatar
Christian Würdig committed
507
		BE_TIMER_POP(t_abi);
Christian Würdig's avatar
Christian Würdig committed
508

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

Christian Würdig's avatar
Christian Würdig committed
511
		/* check schedule */
Christian Würdig's avatar
Christian Würdig committed
512
		BE_TIMER_PUSH(t_verify);
Christian Würdig's avatar
Christian Würdig committed
513
		be_sched_vrfy(birg.irg, vrfy_option);
Christian Würdig's avatar
Christian Würdig committed
514
		BE_TIMER_POP(t_verify);
Sebastian Hack's avatar
Sebastian Hack committed
515

516
517
518
		/* do some statistics */
		be_do_stat_reg_pressure(&birg);

Michael Beck's avatar
Michael Beck committed
519
		/* stuff needs to be done after scheduling but before register allocation */
Christian Würdig's avatar
Christian Würdig committed
520
		BE_TIMER_PUSH(t_codegen);
Sebastian Hack's avatar
Sebastian Hack committed
521
		arch_code_generator_before_ra(birg.cg);
Christian Würdig's avatar
Christian Würdig committed
522
		BE_TIMER_POP(t_codegen);
523
524

		/* Do register allocation */
Christian Würdig's avatar
Christian Würdig committed
525
		BE_TIMER_ONLY(lc_timer_start(t_regalloc));
526
		ra_timer = ra->allocate(&birg);
527
		BE_TIMER_ONLY(lc_timer_stop(t_regalloc));
528

Christian Würdig's avatar
Christian Würdig committed
529
		dump(DUMP_RA, irg, "-ra", dump_ir_block_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
530
531
		be_do_stat_nodes(irg, "06 Register Allocation");

Christian Würdig's avatar
Christian Würdig committed
532
		/* let the codegenerator prepare the graph for emitter */
Michael Beck's avatar
Michael Beck committed
533
		BE_TIMER_PUSH(t_finish);
Christian Würdig's avatar
Christian Würdig committed
534
		arch_code_generator_after_ra(birg.cg);
Christian Würdig's avatar
Christian Würdig committed
535
		BE_TIMER_POP(t_finish);
Sebastian Hack's avatar
Sebastian Hack committed
536

Christian Würdig's avatar
Christian Würdig committed
537
538
539
540
		/* fix stack offsets */
		BE_TIMER_PUSH(t_abi);
		be_abi_fix_stack_bias(birg.abi);
		BE_TIMER_POP(t_abi);
Christian Würdig's avatar
Christian Würdig committed
541

Christian Würdig's avatar
Christian Würdig committed
542
		/* check schedule */
Christian Würdig's avatar
Christian Würdig committed
543
		BE_TIMER_PUSH(t_verify);
Christian Würdig's avatar
Christian Würdig committed
544
		be_sched_vrfy(birg.irg, vrfy_option);
Christian Würdig's avatar
Christian Würdig committed
545
		BE_TIMER_POP(t_verify);
546

Christian Würdig's avatar
Christian Würdig committed
547
		/* emit assembler code */
Michael Beck's avatar
Michael Beck committed
548
		BE_TIMER_PUSH(t_emit);
Sebastian Hack's avatar
Sebastian Hack committed
549
		arch_code_generator_done(birg.cg);
Christian Würdig's avatar
Christian Würdig committed
550
		BE_TIMER_POP(t_emit);
Christian Würdig's avatar
Christian Würdig committed
551

552
		dump(DUMP_FINAL, irg, "-end", dump_ir_extblock_graph_sched);
Christian Würdig's avatar
Christian Würdig committed
553
554

		BE_TIMER_PUSH(t_abi);
Sebastian Hack's avatar
Sebastian Hack committed
555
		be_abi_free(birg.abi);
Christian Würdig's avatar
Christian Würdig committed
556
		BE_TIMER_POP(t_abi);
Christian Würdig's avatar
Christian Würdig committed
557

Christian Würdig's avatar
Christian Würdig committed
558
		be_do_stat_nodes(irg, "07 Final");
559
		restore_optimization_state(&state);
560

Michael Beck's avatar
Michael Beck committed
561
		BE_TIMER_ONLY(num_nodes_a = get_num_reachable_nodes(irg));
562

Christian Würdig's avatar
Christian Würdig committed
563
		/* switched off due to statistics (statistic module needs all irgs) */
564
565
		if (! stat_is_active())
			free_ir_graph(irg);
Christian Würdig's avatar
Christian Würdig committed
566
567

		BE_TIMER_POP(t_other);
Michael Beck's avatar
Michael Beck committed
568

Christian Würdig's avatar
Christian Würdig committed
569
570
#define LC_EMIT(timer)    printf("%-20s: %.3lf msec\n", lc_timer_get_description(timer), (double)lc_timer_elapsed_usec(timer) / 1000.0)
#define LC_EMIT_RA(timer) printf("\t%-20s: %.3lf msec\n", lc_timer_get_description(timer), (double)lc_timer_elapsed_usec(timer) / 1000.0)
571
572
573
574
575
576
577
578
579
580
581
		if (be_options.timing == BE_TIME_ON) {
			printf("==>> IRG %s <<==\n", get_entity_name(get_irg_entity(irg)));
			printf("# nodes at begin:  %u\n", num_nodes_b);
			printf("# nodes before ra: %u\n", num_nodes_r);
			printf("# nodes at end:    %u\n\n", num_nodes_a);
			LC_EMIT(t_prolog);
			LC_EMIT(t_abi);
			LC_EMIT(t_codegen);
			LC_EMIT(t_sched);
			LC_EMIT(t_constr);
			LC_EMIT(t_regalloc);
Christian Würdig's avatar
Christian Würdig committed
582
583
584
			LC_EMIT_RA(ra_timer->t_prolog);
			LC_EMIT_RA(ra_timer->t_live);
			LC_EMIT_RA(ra_timer->t_spill);
Matthias Braun's avatar
Matthias Braun committed
585
                        LC_EMIT_RA(ra_timer->t_spillslots);
Christian Würdig's avatar
Christian Würdig committed
586
587
588
589
590
591
592
			LC_EMIT_RA(ra_timer->t_color);
			LC_EMIT_RA(ra_timer->t_ifg);
			LC_EMIT_RA(ra_timer->t_copymin);
			LC_EMIT_RA(ra_timer->t_ssa);
			LC_EMIT_RA(ra_timer->t_epilog);
			LC_EMIT_RA(ra_timer->t_verify);
			LC_EMIT_RA(ra_timer->t_other);
593
594
			LC_EMIT(t_finish);
			LC_EMIT(t_emit);
Christian Würdig's avatar
Christian Würdig committed
595
			LC_EMIT(t_verify);
Michael Beck's avatar
Michael Beck committed
596
			LC_EMIT(t_other);
597
598
		}
#undef LC_EMIT
599
	}
Sebastian Hack's avatar
Sebastian Hack committed
600
	be_done_env(&env);
601

Christian Würdig's avatar
Christian Würdig committed
602
603
604
#undef BE_TIMER_POP
#undef BE_TIMER_PUSH
#undef BE_TIMER_ONLY
605
606
}

Michael Beck's avatar
Michael Beck committed
607
/* Main interface to the frontend. */
608
void be_main(FILE *file_handle)
609
{
610
611
612
613
614
615
616
617
618
619
620
621
622
623
#ifdef WITH_LIBCORE
	lc_timer_t *t;

	if (be_options.timing == BE_TIME_ON) {
		t = lc_timer_register("bemain", "measure complete bemain loop");

		if (lc_timer_enter_high_priority()) {
			fprintf(stderr, "Warning: Could not enter high priority mode.\n");
		}

		lc_timer_reset_and_start(t);
	}
#endif /* WITH_LIBCORE */

624
	/* never build code for pseudo irgs */
Michael Beck's avatar
Michael Beck committed
625
	set_visit_pseudo_irgs(0);
626

Sebastian Hack's avatar
Sebastian Hack committed
627
628
	be_node_init();
	be_main_loop(file_handle);
629
630
631
632
633

#ifdef WITH_LIBCORE
	if (be_options.timing == BE_TIME_ON) {
		lc_timer_stop(t);
		lc_timer_leave_high_priority();
Michael Beck's avatar
Michael Beck committed
634
		printf("%-20s: %lu msec\n", "BEMAINLOOP", lc_timer_elapsed_msec(t));
635
636
	}
#endif /* WITH_LIBCORE */
637
}
Michael Beck's avatar
Michael Beck committed
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653

/** The debug info retriever function. */
static retrieve_dbg_func retrieve_dbg = NULL;

/* Sets a debug info retriever. */
void be_set_debug_retrieve(retrieve_dbg_func func) {
	retrieve_dbg = func;
}

/* Retrieve the debug info. */
const char *be_retrieve_dbg_info(const dbg_info *dbg, unsigned *line) {
	if (retrieve_dbg)
		return retrieve_dbg(dbg, line);
	*line = 0;
	return NULL;
}