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

Christian Würdig's avatar
Christian Würdig committed
6
/**
Christian Würdig's avatar
Christian Würdig committed
7
8
9
 * @file
 * @brief       This is the main ia32 firm backend driver.
 * @author      Christian Wuerdig
Christian Würdig's avatar
Christian Würdig committed
10
 */
11
#include "config.h"
12

Matthias Braun's avatar
Matthias Braun committed
13
14
#include "lc_opts.h"
#include "lc_opts_enum.h"
Christoph Mallon's avatar
Christoph Mallon committed
15
#include "irarch.h"
Christian Würdig's avatar
Christian Würdig committed
16
#include "irgwalk.h"
Christian Würdig's avatar
Christian Würdig committed
17
#include "irprog.h"
18
#include "iredges_t.h"
19
#include "ircons.h"
20
#include "irflag.h"
Christian Würdig's avatar
Christian Würdig committed
21
#include "irgmod.h"
Christian Würdig's avatar
Christian Würdig committed
22
#include "irgopt.h"
23
#include "irgopt.h"
24
#include "irdump.h"
Christian Würdig's avatar
Christian Würdig committed
25
#include "debug.h"
26
#include "error.h"
27
#include "xmalloc.h"
Michael Beck's avatar
Michael Beck committed
28
#include "irtools.h"
Matthias Braun's avatar
Matthias Braun committed
29
#include "iroptimize.h"
Michael Beck's avatar
Michael Beck committed
30
#include "instrument.h"
31
#include "iropt_t.h"
32
#include "lower_dw.h"
33
#include "lower_calls.h"
34
#include "lower_mode_b.h"
35
#include "lower_softfloat.h"
36
#include "firmstat_t.h"
Christian Würdig's avatar
Christian Würdig committed
37

38
39
40
41
#include "beabi.h"
#include "benode.h"
#include "belower.h"
#include "besched.h"
42
#include "be.h"
43
44
45
46
47
48
49
50
51
52
53
54
55
#include "be_t.h"
#include "beirgmod.h"
#include "beblocksched.h"
#include "bespillutil.h"
#include "bespillslots.h"
#include "bemodule.h"
#include "begnuas.h"
#include "bestate.h"
#include "beflags.h"
#include "betranshlp.h"
#include "belistsched.h"
#include "beabihelper.h"
#include "bestack.h"
56

57
#include "bearch_ia32_t.h"
Christian Würdig's avatar
Christian Würdig committed
58

59
60
#include "ia32_new_nodes.h"
#include "gen_ia32_regalloc_if.h"
61
#include "ia32_common_transform.h"
Christian Würdig's avatar
Christian Würdig committed
62
#include "ia32_transform.h"
Christian Würdig's avatar
Christian Würdig committed
63
#include "ia32_emitter.h"
Christian Würdig's avatar
Christian Würdig committed
64
#include "ia32_optimize.h"
65
#include "ia32_x87.h"
66
#include "ia32_dbg_stat.h"
Christian Würdig's avatar
Christian Würdig committed
67
#include "ia32_finish.h"
68
#include "ia32_fpu.h"
69
#include "ia32_architecture.h"
70

71
72
#ifdef FIRM_GRGEN_BE
#include "ia32_pbqp_transform.h"
73
74

transformer_t be_transformer = TRANSFORMER_DEFAULT;
75
76
#endif

77
78
79
ir_mode *ia32_mode_fpcw;
ir_mode *ia32_mode_E;
ir_type *ia32_type_E;
80

81
82
83
84
85
86
/** The current omit-fp state */
static ir_type *omit_fp_between_type   = NULL;
static ir_type *between_type           = NULL;
static ir_entity *old_bp_ent           = NULL;
static ir_entity *ret_addr_ent         = NULL;
static ir_entity *omit_fp_ret_addr_ent = NULL;
87
static int        precise_x87_spills;
88

89
90
91
92
93
94
95
96
97
98
99
/**
 * The environment for the intrinsic mapping.
 */
static ia32_intrinsic_env_t intrinsic_env = {
	NULL,    /* entity for __divdi3 library call */
	NULL,    /* entity for __moddi3 library call */
	NULL,    /* entity for __udivdi3 library call */
	NULL,    /* entity for __umoddi3 library call */
};


100
typedef ir_node *(*create_const_node_func) (dbg_info *dbgi, ir_node *block);
101

102
/**
103
 * Used to create per-graph unique pseudo nodes.
104
 */
105
static inline ir_node *create_const(ir_graph *irg, ir_node **place,
106
                                    create_const_node_func func,
107
                                    const arch_register_t* reg)
108
109
110
{
	ir_node *block, *res;

111
	if (*place != NULL)
112
113
		return *place;

114
	block = get_irg_start_block(irg);
115
	res = func(NULL, block);
116
	arch_set_irn_register(res, reg);
117
118
119
120
121
	*place = res;

	return res;
}

122
/* Creates the unique per irg GP NoReg node. */
123
ir_node *ia32_new_NoReg_gp(ir_graph *irg)
124
{
125
126
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
	return create_const(irg, &irg_data->noreg_gp, new_bd_ia32_NoReg_GP,
127
	                    &ia32_registers[REG_GP_NOREG]);
128
129
}

130
ir_node *ia32_new_NoReg_fp(ir_graph *irg)
131
{
132
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
133
134
	return create_const(irg, &irg_data->noreg_fp, new_bd_ia32_NoReg_FP,
	                    &ia32_registers[REG_FP_NOREG]);
135
136
}

137
ir_node *ia32_new_NoReg_xmm(ir_graph *irg)
138
{
139
140
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
	return create_const(irg, &irg_data->noreg_xmm, new_bd_ia32_NoReg_XMM,
141
	                    &ia32_registers[REG_XMM_NOREG]);
142
143
}

144
ir_node *ia32_new_Fpu_truncate(ir_graph *irg)
145
{
146
147
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
	return create_const(irg, &irg_data->fpu_trunc_mode, new_bd_ia32_ChangeCW,
148
                        &ia32_registers[REG_FPCW]);
149
150
}

151

152
/**
153
 * Returns the admissible noreg register node for input register pos of node irn.
154
 */
155
static ir_node *ia32_get_admissible_noreg(ir_node *irn, int pos)
156
{
157
	ir_graph                  *irg = get_irn_irg(irn);
158
	const arch_register_req_t *req = arch_get_irn_register_req_in(irn, pos);
159

Matthias Braun's avatar
Matthias Braun committed
160
161
	assert(req != NULL && "Missing register requirements");
	if (req->cls == &ia32_reg_classes[CLASS_ia32_gp])
162
		return ia32_new_NoReg_gp(irg);
Matthias Braun's avatar
Matthias Braun committed
163

164
	if (ia32_cg_config.use_sse2) {
165
		return ia32_new_NoReg_xmm(irg);
166
	} else {
167
		return ia32_new_NoReg_fp(irg);
168
	}
169
170
}

171
172
static ir_entity *ia32_get_frame_entity(const ir_node *irn)
{
Christian Würdig's avatar
Christian Würdig committed
173
	return is_ia32_irn(irn) ? get_ia32_frame_ent(irn) : NULL;
174
175
}

176
static void ia32_set_frame_entity(ir_node *node, ir_entity *entity)
177
{
178
179
180
181
	if (is_be_node(node))
		be_node_set_frame_entity(node, entity);
	else
		set_ia32_frame_ent(node, entity);
182
183
}

184
static void ia32_set_frame_offset(ir_node *irn, int bias)
185
186
187
{
	if (get_ia32_frame_ent(irn) == NULL)
		return;
188

189
	if (is_ia32_Pop(irn) || is_ia32_PopMem(irn)) {
190
191
192
		ir_graph          *irg     = get_irn_irg(irn);
		be_stack_layout_t *layout  = be_get_irg_stack_layout(irg);
		if (layout->sp_relative) {
193
194
195
196
197
			/* Pop nodes modify the stack pointer before calculating the
			 * destination address, so fix this here
			 */
			bias -= 4;
		}
198
	}
199
	add_ia32_am_offs_int(irn, bias);
200
201
}

202
static int ia32_get_sp_bias(const ir_node *node)
203
{
204
205
206
	if (is_ia32_Call(node))
		return -(int)get_ia32_call_attr_const(node)->pop;

207
208
209
	if (is_ia32_Push(node))
		return 4;

210
	if (is_ia32_Pop(node) || is_ia32_PopMem(node))
211
		return -4;
212

213
	if (is_ia32_Leave(node) || is_ia32_CopyEbpEsp(node)) {
214
215
216
		return SP_BIAS_RESET;
	}

217
218
219
	return 0;
}

Sebastian Hack's avatar
Sebastian Hack committed
220
/**
221
 * Build the between type and entities if not already build.
Sebastian Hack's avatar
Sebastian Hack committed
222
 */
223
224
static void ia32_build_between_type(void)
{
225
#define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
226
	if (between_type == NULL) {
227
228
		ir_type *old_bp_type   = new_type_primitive(mode_Iu);
		ir_type *ret_addr_type = new_type_primitive(mode_Iu);
Sebastian Hack's avatar
Sebastian Hack committed
229

230
231
232
		between_type           = new_type_struct(IDENT("ia32_between_type"));
		old_bp_ent             = new_entity(between_type, IDENT("old_bp"), old_bp_type);
		ret_addr_ent           = new_entity(between_type, IDENT("ret_addr"), ret_addr_type);
Sebastian Hack's avatar
Sebastian Hack committed
233

234
235
236
		set_entity_offset(old_bp_ent, 0);
		set_entity_offset(ret_addr_ent, get_type_size_bytes(old_bp_type));
		set_type_size_bytes(between_type, get_type_size_bytes(old_bp_type) + get_type_size_bytes(ret_addr_type));
237
		set_type_state(between_type, layout_fixed);
238
239
240
241
242
243
244

		omit_fp_between_type = new_type_struct(IDENT("ia32_between_type_omit_fp"));
		omit_fp_ret_addr_ent = new_entity(omit_fp_between_type, IDENT("ret_addr"), ret_addr_type);

		set_entity_offset(omit_fp_ret_addr_ent, 0);
		set_type_size_bytes(omit_fp_between_type, get_type_size_bytes(ret_addr_type));
		set_type_state(omit_fp_between_type, layout_fixed);
Sebastian Hack's avatar
Sebastian Hack committed
245
	}
246
247
248
249
250
251
252
253
#undef IDENT
}

/**
 * Produces the type which sits between the stack args and the locals on the stack.
 * it will contain the return address and space to store the old base pointer.
 * @return The Firm type modeling the ABI between type.
 */
254
static ir_type *ia32_abi_get_between_type(ir_graph *irg)
255
{
256
	const be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
257
	ia32_build_between_type();
258
	return layout->sp_relative ? omit_fp_between_type : between_type;
259
260
261
262
263
}

/**
 * Return the stack entity that contains the return address.
 */
264
ir_entity *ia32_get_return_address_entity(ir_graph *irg)
265
{
266
	const be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
267
	ia32_build_between_type();
268
	return layout->sp_relative ? omit_fp_ret_addr_ent : ret_addr_ent;
269
270
271
272
273
}

/**
 * Return the stack entity that contains the frame address.
 */
274
ir_entity *ia32_get_frame_address_entity(ir_graph *irg)
275
{
276
	const be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
277
	ia32_build_between_type();
278
	return layout->sp_relative ? NULL : old_bp_ent;
Sebastian Hack's avatar
Sebastian Hack committed
279
280
}

281
282
283
284
285
286
287
/**
 * Get the estimated cycle count for @p irn.
 *
 * @param irn  The node.
 *
 * @return     The estimated cycle count for this operation
 */
288
static int ia32_get_op_estimated_cost(ir_node const *const irn)
289
{
290
	if (is_ia32_CopyB_i(irn)) {
291
292
		unsigned const size = get_ia32_copyb_size(irn);
		return 20 + size * 4 / 3;
Christian Würdig's avatar
Christian Würdig committed
293
	}
294
295
296

	unsigned cost = get_ia32_latency(irn);

Christian Würdig's avatar
Christian Würdig committed
297
	/* in case of address mode operations add additional cycles */
298
	if (get_ia32_op_type(irn) != ia32_Normal) {
299
		if (is_ia32_use_frame(irn) || (
300
301
		      is_ia32_NoReg_GP(get_irn_n(irn, n_ia32_base)) &&
		      is_ia32_NoReg_GP(get_irn_n(irn, n_ia32_index))
302
		    )) {
303
			/* Stack access, assume it is cached. */
304
305
			cost += 5;
		} else {
306
			/* Access probably elsewhere. */
307
308
			cost += 20;
		}
Christian Würdig's avatar
Christian Würdig committed
309
310
311
	}

	return cost;
312
313
}

314
315
static ir_mode *get_spill_mode_mode(const ir_mode *mode)
{
316
	if (mode_is_float(mode))
317
		return precise_x87_spills ? ia32_mode_E : mode_D;
318
319
320
321

	return mode_Iu;
}

322
323
324
/**
 * Get the mode that should be used for spilling value node
 */
325
static ir_mode *get_spill_mode(const ir_node *node)
326
327
{
	ir_mode *mode = get_irn_mode(node);
328
	return get_spill_mode_mode(mode);
329
330
}

331
/**
Christoph Mallon's avatar
Christoph Mallon committed
332
 * Check if irn can load its operand at position i from memory (source addressmode).
333
334
335
336
 * @param irn    The irn to be checked
 * @param i      The operands position
 * @return Non-Zero if operand can be loaded
 */
337
338
339
340
static int ia32_possible_memory_operand(const ir_node *irn, unsigned int i)
{
	ir_node       *op        = get_irn_n(irn, i);
	const ir_mode *mode      = get_irn_mode(op);
341

342
343
344
	if (!is_ia32_irn(irn)                              ||  /* must be an ia32 irn */
	    get_ia32_op_type(irn) != ia32_Normal           ||  /* must not already be a addressmode irn */
	    is_ia32_use_frame(irn))                            /* must not already use frame */
345
		return 0;
346
347
348
349
350
	if (mode_is_float(mode)) {
		ir_mode *spillmode = get_spill_mode_mode(mode);
		if (spillmode != mode_D && spillmode != mode_F)
			return 0;
	}
351

352
353
354
355
	switch (get_ia32_am_support(irn)) {
		case ia32_am_none:
			return 0;

356
		case ia32_am_unary:
357
358
359
			if (i != n_ia32_unary_op)
				return 0;
			break;
360
361
362
363
364
365
366
367

		case ia32_am_binary:
			switch (i) {
				case n_ia32_binary_left: {
					if (!is_ia32_commutative(irn))
						return 0;

					/* we can't swap left/right for limited registers
368
369
370
					 * (As this (currently) breaks constraint handling copies) */
					arch_register_req_t const *const req = arch_get_irn_register_req_in(irn, n_ia32_binary_left);
					if (arch_register_req_is(req, limited))
371
						return 0;
372
					break;
373
374
375
				}

				case n_ia32_binary_right:
376
					break;
377

378
379
380
				default:
					return 0;
			}
381
			break;
382
383

		default:
384
			panic("Unknown AM type");
385
	}
386
387
388
389
390
391
392

	/* HACK: must not already use "real" memory.
	 * This can happen for Call and Div */
	if (!is_NoMem(get_irn_n(irn, n_ia32_mem)))
		return 0;

	return 1;
393
394
}

395
396
static void ia32_perform_memory_operand(ir_node *irn, ir_node *spill,
                                        unsigned int i)
397
{
398
	assert(ia32_possible_memory_operand(irn, i) && "Cannot perform memory operand change");
399
400

	set_ia32_op_type(irn, ia32_AddrModeS);
401

402
403
404
	ir_mode *op_mode      = get_irn_mode(get_irn_n(irn, i));
	ir_mode *load_mode    = get_spill_mode_mode(op_mode);
	ir_mode *dest_op_mode = get_ia32_ls_mode(irn);
405
406
407
	if (get_mode_size_bits(load_mode) <= get_mode_size_bits(dest_op_mode)) {
		set_ia32_ls_mode(irn, load_mode);
	}
408
	set_ia32_use_frame(irn);
409
	set_ia32_need_stackent(irn);
410

411
412
	if (i == n_ia32_binary_left                    &&
	    get_ia32_am_support(irn) == ia32_am_binary &&
413
414
	    /* immediates are only allowed on the right side */
	    !is_ia32_Immediate(get_irn_n(irn, n_ia32_binary_right))) {
415
		ia32_swap_left_right(irn);
416
		i = n_ia32_binary_right;
417
	}
418

419
420
	assert(is_NoMem(get_irn_n(irn, n_ia32_mem)));

421
422
	set_irn_n(irn, n_ia32_base, get_irg_frame(get_irn_irg(irn)));
	set_irn_n(irn, n_ia32_mem,  spill);
423
	set_irn_n(irn, i,           ia32_get_admissible_noreg(irn, i));
424
	set_ia32_is_reload(irn);
425
426
}

Sebastian Hack's avatar
Sebastian Hack committed
427
428
429
430
static const be_abi_callbacks_t ia32_abi_callbacks = {
	ia32_abi_get_between_type,
};

431
/* register allocator interface */
Matthias Braun's avatar
Matthias Braun committed
432
static const arch_irn_ops_t ia32_irn_ops = {
433
434
435
436
437
438
439
440
	ia32_get_frame_entity,
	ia32_set_frame_offset,
	ia32_get_sp_bias,
	ia32_get_op_estimated_cost,
	ia32_possible_memory_operand,
	ia32_perform_memory_operand,
};

441
static int gprof = 0;
Michael Beck's avatar
Michael Beck committed
442

443
static void ia32_before_abi(ir_graph *irg)
444
{
445
	if (gprof) {
446
		static ir_entity *mcount = NULL;
Michael Beck's avatar
Michael Beck committed
447
		if (mcount == NULL) {
448
			ir_type *tp = new_type_method(0, 0);
449
450
			ident   *id = new_id_from_str("mcount");
			mcount = new_entity(get_glob_type(), id, tp);
Michael Beck's avatar
Michael Beck committed
451
452
			/* FIXME: enter the right ld_ident here */
			set_entity_ld_ident(mcount, get_entity_ident(mcount));
453
			set_entity_visibility(mcount, ir_visibility_external);
Michael Beck's avatar
Michael Beck committed
454
		}
455
		instrument_initcall(irg, mcount);
Michael Beck's avatar
Michael Beck committed
456
	}
457
458
459
460
461
462
}

/**
 * Transforms the standard firm graph into
 * an ia32 firm graph
 */
463
static void ia32_prepare_graph(ir_graph *irg)
464
{
465
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
466

467
#ifdef FIRM_GRGEN_BE
468
	switch (be_transformer) {
469
470
	case TRANSFORMER_DEFAULT:
		/* transform remaining nodes into assembler instructions */
471
		ia32_transform_graph(irg);
472
		break;
473

474
475
476
	case TRANSFORMER_PBQP:
	case TRANSFORMER_RAND:
		/* transform nodes into assembler instructions by PBQP magic */
477
		ia32_transform_graph_by_pbqp(irg);
478
		break;
479

480
481
	default:
		panic("invalid transformer");
482
	}
483
#else
484
	ia32_transform_graph(irg);
485
#endif
486

yb9976's avatar
typo    
yb9976 committed
487
	/* do local optimizations (mainly CSE) */
488
	optimize_graph_df(irg);
489
	/* backend code expects that outedges are always enabled */
490
	assure_edges(irg);
491

492
493
	if (irg_data->dump)
		dump_ir_graph(irg, "transformed");
Christian Würdig's avatar
Christian Würdig committed
494

495
	/* optimize address mode */
496
	ia32_optimize_graph(irg);
497

498
	/* do code placement, to optimize the position of constants */
499
	place_code(irg);
500
	/* backend code expects that outedges are always enabled */
501
	assure_edges(irg);
502

503
504
	if (irg_data->dump)
		dump_ir_graph(irg, "place");
Christian Würdig's avatar
Christian Würdig committed
505
506
}

507
ir_node *ia32_turn_back_am(ir_node *node)
508
509
{
	dbg_info *dbgi  = get_irn_dbg_info(node);
510
	ir_graph *irg   = get_irn_irg(node);
511
	ir_node  *block = get_nodes_block(node);
512
	ir_node  *base  = get_irn_n(node, n_ia32_base);
513
	ir_node  *idx   = get_irn_n(node, n_ia32_index);
514
	ir_node  *mem   = get_irn_n(node, n_ia32_mem);
515
	ir_node  *noreg;
516

517
	ir_node  *load     = new_bd_ia32_Load(dbgi, block, base, idx, mem);
518
	ir_node  *load_res = new_rd_Proj(dbgi, load, mode_Iu, pn_ia32_Load_res);
519
520

	ia32_copy_am_attrs(load, node);
521
522
	if (is_ia32_is_reload(node))
		set_ia32_is_reload(load);
523
	set_irn_n(node, n_ia32_mem, get_irg_no_mem(irg));
524

525
	switch (get_ia32_am_support(node)) {
526
527
528
529
530
		case ia32_am_unary:
			set_irn_n(node, n_ia32_unary_op, load_res);
			break;

		case ia32_am_binary:
531
			if (is_ia32_Immediate(get_irn_n(node, n_ia32_binary_right))) {
532
533
534
535
536
537
				set_irn_n(node, n_ia32_binary_left, load_res);
			} else {
				set_irn_n(node, n_ia32_binary_right, load_res);
			}
			break;

538
		default:
539
			panic("Unknown AM type");
540
	}
541
	noreg = ia32_new_NoReg_gp(irg);
542
	set_irn_n(node, n_ia32_base,  noreg);
543
544
545
546
547
	set_irn_n(node, n_ia32_index, noreg);
	set_ia32_am_offs_int(node, 0);
	set_ia32_am_sc(node, NULL);
	set_ia32_am_scale(node, 0);
	clear_ia32_am_sc_sign(node);
548
549

	/* rewire mem-proj */
Michael Beck's avatar
Michael Beck committed
550
	if (get_irn_mode(node) == mode_T) {
551
552
		foreach_out_edge(node, edge) {
			ir_node *out = get_edge_src_irn(edge);
553
554
555
556
			if (get_irn_mode(out) == mode_M) {
				set_Proj_pred(out, load);
				set_Proj_proj(out, pn_ia32_Load_M);
				break;
557
558
559
560
561
			}
		}
	}

	set_ia32_op_type(node, ia32_Normal);
Michael Beck's avatar
Michael Beck committed
562
	if (sched_is_scheduled(node))
563
		sched_add_before(node, load);
564
565

	return load_res;
566
567
568
569
570
}

static ir_node *flags_remat(ir_node *node, ir_node *after)
{
	/* we should turn back source address mode when rematerializing nodes */
571
	ia32_op_type_t type;
572
	ir_node        *block;
573
574
	ir_node        *copy;

Michael Beck's avatar
Michael Beck committed
575
	if (is_Block(after)) {
576
577
578
579
580
		block = after;
	} else {
		block = get_nodes_block(after);
	}

581
	type = get_ia32_op_type(node);
582
	switch (type) {
583
		case ia32_AddrModeS:
584
			ia32_turn_back_am(node);
585
			break;
586
587
588
589
590
591

		case ia32_AddrModeD:
			/* TODO implement this later... */
			panic("found DestAM with flag user %+F this should not happen", node);

		default: assert(type == ia32_Normal); break;
592
593
	}

594
	copy = exact_copy(node);
595
	set_nodes_block(copy, block);
596
597
598
599
600
	sched_add_after(after, copy);

	return copy;
}

601
602
603
/**
 * Called before the register allocator.
 */
604
static void ia32_before_ra(ir_graph *irg)
605
{
606
	/* setup fpu rounding modes */
607
	ia32_setup_fpu_mode(irg);
608
609

	/* fixup flags */
610
	be_sched_fix_flags(irg, &ia32_reg_classes[CLASS_ia32_flags],
611
	                   &flags_remat, NULL);
612

613
	be_add_missing_keeps(irg);
614
}
615

Christian Würdig's avatar
Christian Würdig committed
616

Christian Würdig's avatar
Christian Würdig committed
617
/**
618
 * Transforms a be_Reload into a ia32 Load.
Christian Würdig's avatar
Christian Würdig committed
619
 */
620
static void transform_to_Load(ir_node *node)
621
{
622
	ir_graph *irg        = get_irn_irg(node);
623
	dbg_info *dbgi       = get_irn_dbg_info(node);
624
625
626
	ir_node *block       = get_nodes_block(node);
	ir_entity *ent       = be_get_frame_entity(node);
	ir_mode *mode        = get_irn_mode(node);
627
	ir_mode *spillmode   = get_spill_mode(node);
628
	ir_node *noreg       = ia32_new_NoReg_gp(irg);
629
	ir_node *ptr         = get_irg_frame(irg);
630
	ir_node *mem         = get_irn_n(node, n_be_Reload_mem);
Christian Würdig's avatar
Christian Würdig committed
631
	ir_node *new_op, *proj;
632
	const arch_register_t *reg;
Christian Würdig's avatar
Christian Würdig committed
633

634
	if (mode_is_float(spillmode)) {
635
		if (ia32_cg_config.use_sse2)
636
			new_op = new_bd_ia32_xLoad(dbgi, block, ptr, noreg, mem, spillmode);
637
		else
638
			new_op = new_bd_ia32_fld(dbgi, block, ptr, noreg, mem, spillmode);
Christian Würdig's avatar
Christian Würdig committed
639
	}
640
	else if (get_mode_size_bits(spillmode) == 128) {
641
		/* Reload 128 bit SSE registers */
642
		new_op = new_bd_ia32_xxLoad(dbgi, block, ptr, noreg, mem);
643
	}
644
	else
645
		new_op = new_bd_ia32_Load(dbgi, block, ptr, noreg, mem);
Christian Würdig's avatar
Christian Würdig committed
646
647

	set_ia32_op_type(new_op, ia32_AddrModeS);
648
	set_ia32_ls_mode(new_op, spillmode);
Christian Würdig's avatar
Christian Würdig committed
649
650
	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);
651
	set_ia32_is_reload(new_op);
Christian Würdig's avatar
Christian Würdig committed
652

653
	DBG_OPT_RELOAD2LD(node, new_op);
654

655
	proj = new_rd_Proj(dbgi, new_op, mode, pn_ia32_Load_res);
Christian Würdig's avatar
Christian Würdig committed
656

657
	sched_replace(node, new_op);
Christian Würdig's avatar
Christian Würdig committed
658

659
	/* copy the register from the old node to the new Load */
660
	reg = arch_get_irn_register(node);
661
	arch_set_irn_register(proj, reg);
662

663
	SET_IA32_ORIG_NODE(new_op, node);
Christian Würdig's avatar
Christian Würdig committed
664

665
	exchange(node, proj);
Christian Würdig's avatar
Christian Würdig committed
666
667
668
}

/**
669
 * Transforms a be_Spill node into a ia32 Store.
Christian Würdig's avatar
Christian Würdig committed
670
 */
671
static void transform_to_Store(ir_node *node)
672
{
673
	ir_graph *irg  = get_irn_irg(node);
674
	dbg_info *dbgi = get_irn_dbg_info(node);
675
676
	ir_node *block = get_nodes_block(node);
	ir_entity *ent = be_get_frame_entity(node);
677
	const ir_node *spillval = get_irn_n(node, n_be_Spill_val);
678
	ir_mode *mode  = get_spill_mode(spillval);
679
	ir_node *noreg = ia32_new_NoReg_gp(irg);
680
	ir_node *nomem = get_irg_no_mem(irg);
681
	ir_node *ptr   = get_irg_frame(irg);
682
	ir_node *val   = get_irn_n(node, n_be_Spill_val);
683
	ir_node *res;
684
	ir_node *store;
Christian Würdig's avatar
Christian Würdig committed
685
686

	if (mode_is_float(mode)) {
687
		if (ia32_cg_config.use_sse2) {
688
			store = new_bd_ia32_xStore(dbgi, block, ptr, noreg, nomem, val);
689
690
			res   = new_r_Proj(store, mode_M, pn_ia32_xStore_M);
		} else {
691
692
			store = new_bd_ia32_fst(dbgi, block, ptr, noreg, nomem, val, mode);
			res   = new_r_Proj(store, mode_M, pn_ia32_fst_M);
693
		}
694
	} else if (get_mode_size_bits(mode) == 128) {
695
		/* Spill 128 bit SSE registers */
696
		store = new_bd_ia32_xxStore(dbgi, block, ptr, noreg, nomem, val);
697
		res   = new_r_Proj(store, mode_M, pn_ia32_xxStore_M);
698
	} else {
699
700
701
		store = get_mode_size_bits(mode) == 8
			? new_bd_ia32_Store_8bit(dbgi, block, ptr, noreg, nomem, val)
			: new_bd_ia32_Store     (dbgi, block, ptr, noreg, nomem, val);
702
		res   = new_r_Proj(store, mode_M, pn_ia32_Store_M);
Christian Würdig's avatar
Christian Würdig committed
703
704
	}

705
706
707
708
	set_ia32_op_type(store, ia32_AddrModeD);
	set_ia32_ls_mode(store, mode);
	set_ia32_frame_ent(store, ent);
	set_ia32_use_frame(store);
709
	set_ia32_is_spill(store);
710
	SET_IA32_ORIG_NODE(store, node);
711
	DBG_OPT_SPILL2ST(node, store);
Christian Würdig's avatar
Christian Würdig committed
712

713
	sched_replace(node, store);
714
	exchange(node, res);
Christian Würdig's avatar
Christian Würdig committed
715
716
}

717
static ir_node *create_push(ir_node *node, ir_node *schedpoint, ir_node *sp, ir_node *mem, ir_entity *ent)
718
{
719
720
721
722
723
	dbg_info *dbgi  = get_irn_dbg_info(node);
	ir_node  *block = get_nodes_block(node);
	ir_graph *irg   = get_irn_irg(node);
	ir_node  *noreg = ia32_new_NoReg_gp(irg);
	ir_node  *frame = get_irg_frame(irg);
724

725
	ir_node *push = new_bd_ia32_Push(dbgi, block, frame, noreg, mem, noreg, sp);
726
727
728
729
730

	set_ia32_frame_ent(push, ent);
	set_ia32_use_frame(push);
	set_ia32_op_type(push, ia32_AddrModeS);
	set_ia32_ls_mode(push, mode_Is);
731
	set_ia32_is_spill(push);
732
733
734
735
736

	sched_add_before(schedpoint, push);
	return push;
}

737
static ir_node *create_pop(ir_node *node, ir_node *schedpoint, ir_node *sp, ir_entity *ent)
738
{
739
	dbg_info *dbgi  = get_irn_dbg_info(node);
740
741
742
743
	ir_node  *block = get_nodes_block(node);
	ir_graph *irg   = get_irn_irg(node);
	ir_node  *noreg = ia32_new_NoReg_gp(irg);
	ir_node  *frame = get_irg_frame(irg);
744

745
	ir_node *pop = new_bd_ia32_PopMem(dbgi, block, frame, noreg,
746
	                                  get_irg_no_mem(irg), sp);
747
748
749
750
751

	set_ia32_frame_ent(pop, ent);
	set_ia32_use_frame(pop);
	set_ia32_op_type(pop, ia32_AddrModeD);
	set_ia32_ls_mode(pop, mode_Is);
752
	set_ia32_is_reload(pop);
753
754
755
756
757
758

	sched_add_before(schedpoint, pop);

	return pop;
}

759
760
static ir_node* create_spproj(ir_node *node, ir_node *pred, int pos)
{
761
762
	dbg_info *dbgi   = get_irn_dbg_info(node);
	ir_mode  *spmode = mode_Iu;
763
	const arch_register_t *spreg = &ia32_registers[REG_ESP];
764
765
	ir_node *sp;

766
	sp = new_rd_Proj(dbgi, pred, spmode, pos);
767
	arch_set_irn_register(sp, spreg);
768
769
770
771

	return sp;
}

772
/**
773
 * Transform MemPerm, currently we do this the ugly way and produce
774
775
776
 * push/pop into/from memory cascades. This is possible without using
 * any registers.
 */
777
static void transform_MemPerm(ir_node *node)
778
{