bearch_ia32.c 55.4 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.
 */

Christian Würdig's avatar
Christian Würdig committed
20
/**
Christian Würdig's avatar
Christian Würdig committed
21
22
23
 * @file
 * @brief       This is the main ia32 firm backend driver.
 * @author      Christian Wuerdig
Christian Würdig's avatar
Christian Würdig committed
24
 */
25
#include "config.h"
26

Matthias Braun's avatar
Matthias Braun committed
27
28
#include "lc_opts.h"
#include "lc_opts_enum.h"
29

Christian Würdig's avatar
Christian Würdig committed
30
31
#include <math.h>

Christoph Mallon's avatar
Christoph Mallon committed
32
#include "irarch.h"
Christian Würdig's avatar
Christian Würdig committed
33
#include "irgwalk.h"
Christian Würdig's avatar
Christian Würdig committed
34
35
#include "irprog.h"
#include "irprintf.h"
36
#include "iredges_t.h"
37
#include "ircons.h"
38
#include "irflag.h"
Christian Würdig's avatar
Christian Würdig committed
39
#include "irgmod.h"
Christian Würdig's avatar
Christian Würdig committed
40
#include "irgopt.h"
41
#include "irgopt.h"
42
#include "irdump.h"
43
#include "pdeq.h"
44
#include "pset.h"
Christian Würdig's avatar
Christian Würdig committed
45
#include "debug.h"
46
#include "error.h"
47
#include "xmalloc.h"
Michael Beck's avatar
Michael Beck committed
48
#include "irtools.h"
Matthias Braun's avatar
Matthias Braun committed
49
#include "iroptimize.h"
Michael Beck's avatar
Michael Beck committed
50
#include "instrument.h"
51
#include "iropt_t.h"
52
#include "lower_dw.h"
53
#include "lower_calls.h"
54
#include "lower_mode_b.h"
55
#include "lower_softfloat.h"
56
#include "firmstat_t.h"
Christian Würdig's avatar
Christian Würdig committed
57

58
59
60
61
#include "beabi.h"
#include "benode.h"
#include "belower.h"
#include "besched.h"
62
#include "be.h"
63
64
65
66
67
68
69
70
71
72
73
74
75
#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"
76

77
#include "bearch_ia32_t.h"
Christian Würdig's avatar
Christian Würdig committed
78

79
80
#include "ia32_new_nodes.h"
#include "gen_ia32_regalloc_if.h"
81
#include "ia32_common_transform.h"
Christian Würdig's avatar
Christian Würdig committed
82
#include "ia32_transform.h"
Christian Würdig's avatar
Christian Würdig committed
83
#include "ia32_emitter.h"
Christian Würdig's avatar
Christian Würdig committed
84
#include "ia32_optimize.h"
85
#include "ia32_x87.h"
86
#include "ia32_dbg_stat.h"
Christian Würdig's avatar
Christian Würdig committed
87
#include "ia32_finish.h"
88
#include "ia32_fpu.h"
89
#include "ia32_architecture.h"
90

91
92
#ifdef FIRM_GRGEN_BE
#include "ia32_pbqp_transform.h"
93
94

transformer_t be_transformer = TRANSFORMER_DEFAULT;
95
96
#endif

97
98
99
ir_mode *ia32_mode_fpcw;
ir_mode *ia32_mode_E;
ir_type *ia32_type_E;
100

101
102
103
104
105
106
107
/** 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;

108
109
110
111
112
113
114
115
116
117
118
/**
 * 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 */
};


119
typedef ir_node *(*create_const_node_func) (dbg_info *dbgi, ir_node *block);
120

121
/**
122
 * Used to create per-graph unique pseudo nodes.
123
 */
124
static inline ir_node *create_const(ir_graph *irg, ir_node **place,
125
                                    create_const_node_func func,
126
                                    const arch_register_t* reg)
127
128
129
{
	ir_node *block, *res;

130
	if (*place != NULL)
131
132
		return *place;

133
	block = get_irg_start_block(irg);
134
	res = func(NULL, block);
135
	arch_set_irn_register(res, reg);
136
137
138
139
140
	*place = res;

	return res;
}

141
/* Creates the unique per irg GP NoReg node. */
142
ir_node *ia32_new_NoReg_gp(ir_graph *irg)
143
{
144
145
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
	return create_const(irg, &irg_data->noreg_gp, new_bd_ia32_NoReg_GP,
146
	                    &ia32_registers[REG_GP_NOREG]);
147
148
}

149
ir_node *ia32_new_NoReg_fp(ir_graph *irg)
150
{
151
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
152
153
	return create_const(irg, &irg_data->noreg_fp, new_bd_ia32_NoReg_FP,
	                    &ia32_registers[REG_FP_NOREG]);
154
155
}

156
ir_node *ia32_new_NoReg_xmm(ir_graph *irg)
157
{
158
159
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
	return create_const(irg, &irg_data->noreg_xmm, new_bd_ia32_NoReg_XMM,
160
	                    &ia32_registers[REG_XMM_NOREG]);
161
162
}

163
ir_node *ia32_new_Fpu_truncate(ir_graph *irg)
164
{
165
166
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
	return create_const(irg, &irg_data->fpu_trunc_mode, new_bd_ia32_ChangeCW,
167
                        &ia32_registers[REG_FPCW]);
168
169
}

170

171
/**
172
 * Returns the admissible noreg register node for input register pos of node irn.
173
 */
174
static ir_node *ia32_get_admissible_noreg(ir_node *irn, int pos)
175
{
176
	ir_graph                  *irg = get_irn_irg(irn);
177
	const arch_register_req_t *req = arch_get_irn_register_req_in(irn, pos);
178

Matthias Braun's avatar
Matthias Braun committed
179
180
	assert(req != NULL && "Missing register requirements");
	if (req->cls == &ia32_reg_classes[CLASS_ia32_gp])
181
		return ia32_new_NoReg_gp(irg);
Matthias Braun's avatar
Matthias Braun committed
182

183
	if (ia32_cg_config.use_sse2) {
184
		return ia32_new_NoReg_xmm(irg);
185
	} else {
186
		return ia32_new_NoReg_fp(irg);
187
	}
188
189
}

190
191
static ir_entity *ia32_get_frame_entity(const ir_node *irn)
{
Christian Würdig's avatar
Christian Würdig committed
192
	return is_ia32_irn(irn) ? get_ia32_frame_ent(irn) : NULL;
193
194
}

195
static void ia32_set_frame_entity(ir_node *node, ir_entity *entity)
196
{
197
198
199
200
	if (is_be_node(node))
		be_node_set_frame_entity(node, entity);
	else
		set_ia32_frame_ent(node, entity);
201
202
}

203
static void ia32_set_frame_offset(ir_node *irn, int bias)
204
205
206
{
	if (get_ia32_frame_ent(irn) == NULL)
		return;
207

208
	if (is_ia32_Pop(irn) || is_ia32_PopMem(irn)) {
209
210
211
		ir_graph          *irg     = get_irn_irg(irn);
		be_stack_layout_t *layout  = be_get_irg_stack_layout(irg);
		if (layout->sp_relative) {
212
213
214
215
216
			/* Pop nodes modify the stack pointer before calculating the
			 * destination address, so fix this here
			 */
			bias -= 4;
		}
217
	}
218
	add_ia32_am_offs_int(irn, bias);
219
220
}

221
static int ia32_get_sp_bias(const ir_node *node)
222
{
223
224
225
	if (is_ia32_Call(node))
		return -(int)get_ia32_call_attr_const(node)->pop;

226
227
228
	if (is_ia32_Push(node))
		return 4;

229
	if (is_ia32_Pop(node) || is_ia32_PopMem(node))
230
		return -4;
231

232
	if (is_ia32_Leave(node) || is_ia32_CopyEbpEsp(node)) {
233
234
235
		return SP_BIAS_RESET;
	}

236
237
238
	return 0;
}

Sebastian Hack's avatar
Sebastian Hack committed
239
/**
240
 * Build the between type and entities if not already build.
Sebastian Hack's avatar
Sebastian Hack committed
241
 */
242
243
static void ia32_build_between_type(void)
{
244
#define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
245
	if (between_type == NULL) {
246
247
		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
248

249
250
251
		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
252

253
254
255
		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));
256
		set_type_state(between_type, layout_fixed);
257
258
259
260
261
262
263

		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
264
	}
265
266
267
268
269
270
271
272
#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.
 */
273
static ir_type *ia32_abi_get_between_type(ir_graph *irg)
274
{
275
	const be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
276
	ia32_build_between_type();
277
	return layout->sp_relative ? omit_fp_between_type : between_type;
278
279
280
281
282
}

/**
 * Return the stack entity that contains the return address.
 */
283
ir_entity *ia32_get_return_address_entity(ir_graph *irg)
284
{
285
	const be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
286
	ia32_build_between_type();
287
	return layout->sp_relative ? omit_fp_ret_addr_ent : ret_addr_ent;
288
289
290
291
292
}

/**
 * Return the stack entity that contains the frame address.
 */
293
ir_entity *ia32_get_frame_address_entity(ir_graph *irg)
294
{
295
	const be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
296
	ia32_build_between_type();
297
	return layout->sp_relative ? NULL : old_bp_ent;
Sebastian Hack's avatar
Sebastian Hack committed
298
299
}

300
301
302
303
304
305
306
307
/**
 * Get the estimated cycle count for @p irn.
 *
 * @param self The this pointer.
 * @param irn  The node.
 *
 * @return     The estimated cycle count for this operation
 */
308
static int ia32_get_op_estimated_cost(const ir_node *irn)
309
{
310
	int            cost;
Christian Würdig's avatar
Christian Würdig committed
311
	ia32_op_type_t op_tp;
Adam Szalkowski's avatar
Adam Szalkowski committed
312

Christian Würdig's avatar
Christian Würdig committed
313
	if (is_Proj(irn))
314
315
316
		return 0;
	if (!is_ia32_irn(irn))
		return 0;
Adam Szalkowski's avatar
Adam Szalkowski committed
317

Christian Würdig's avatar
Christian Würdig committed
318
319
320
321
322
323
324
325
326
	assert(is_ia32_irn(irn));

	cost  = get_ia32_latency(irn);
	op_tp = get_ia32_op_type(irn);

	if (is_ia32_CopyB(irn)) {
		cost = 250;
	}
	else if (is_ia32_CopyB_i(irn)) {
Michael Beck's avatar
Michael Beck committed
327
		int size = get_ia32_copyb_size(irn);
Christian Würdig's avatar
Christian Würdig committed
328
329
330
331
332
		cost     = 20 + (int)ceil((4/3) * size);
	}
	/* in case of address mode operations add additional cycles */
	else if (op_tp == ia32_AddrModeD || op_tp == ia32_AddrModeS) {
		/*
333
334
335
			In case of stack access and access to fixed addresses add 5 cycles
			(we assume they are in cache), other memory operations cost 20
			cycles.
Christian Würdig's avatar
Christian Würdig committed
336
		*/
337
		if (is_ia32_use_frame(irn) || (
338
339
		    is_ia32_NoReg_GP(get_irn_n(irn, n_ia32_base)) &&
		    is_ia32_NoReg_GP(get_irn_n(irn, n_ia32_index))
340
		    )) {
341
342
343
344
			cost += 5;
		} else {
			cost += 20;
		}
Christian Würdig's avatar
Christian Würdig committed
345
346
347
	}

	return cost;
348
349
}

350
351
static ir_mode *get_spill_mode_mode(const ir_mode *mode)
{
352
	if (mode_is_float(mode))
353
354
355
356
357
		return mode_D;

	return mode_Iu;
}

358
359
360
/**
 * Get the mode that should be used for spilling value node
 */
361
static ir_mode *get_spill_mode(const ir_node *node)
362
363
{
	ir_mode *mode = get_irn_mode(node);
364
	return get_spill_mode_mode(mode);
365
366
367
}

/**
Michael Beck's avatar
Michael Beck committed
368
 * Checks whether an addressmode reload for a node with mode mode is compatible
369
370
371
372
 * with a spillslot of mode spill_mode
 */
static int ia32_is_spillmode_compatible(const ir_mode *mode, const ir_mode *spillmode)
{
373
	return !mode_is_float(mode) || mode == spillmode;
374
375
}

376
/**
Christoph Mallon's avatar
Christoph Mallon committed
377
 * Check if irn can load its operand at position i from memory (source addressmode).
378
379
380
381
 * @param irn    The irn to be checked
 * @param i      The operands position
 * @return Non-Zero if operand can be loaded
 */
382
383
384
385
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);
386
	const ir_mode *spillmode = get_spill_mode(op);
387

388
389
390
391
	if (!is_ia32_irn(irn)                              ||  /* must be an ia32 irn */
	    get_ia32_op_type(irn) != ia32_Normal           ||  /* must not already be a addressmode irn */
	    !ia32_is_spillmode_compatible(mode, spillmode) ||
	    is_ia32_use_frame(irn))                            /* must not already use frame */
392
393
		return 0;

394
395
396
397
	switch (get_ia32_am_support(irn)) {
		case ia32_am_none:
			return 0;

398
		case ia32_am_unary:
399
400
401
			if (i != n_ia32_unary_op)
				return 0;
			break;
402
403
404
405
406
407
408
409

		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
410
411
412
					 * (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))
413
						return 0;
414
					break;
415
416
417
				}

				case n_ia32_binary_right:
418
					break;
419

420
421
422
				default:
					return 0;
			}
423
			break;
424
425

		default:
426
			panic("Unknown AM type");
427
	}
428
429
430
431
432
433
434

	/* 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;
435
436
}

437
438
static void ia32_perform_memory_operand(ir_node *irn, ir_node *spill,
                                        unsigned int i)
439
{
440
441
442
	ir_mode *load_mode;
	ir_mode *dest_op_mode;

443
	assert(ia32_possible_memory_operand(irn, i) && "Cannot perform memory operand change");
444
445

	set_ia32_op_type(irn, ia32_AddrModeS);
446
447
448
449
450
451

	load_mode    = get_irn_mode(get_irn_n(irn, i));
	dest_op_mode = get_ia32_ls_mode(irn);
	if (get_mode_size_bits(load_mode) <= get_mode_size_bits(dest_op_mode)) {
		set_ia32_ls_mode(irn, load_mode);
	}
452
	set_ia32_use_frame(irn);
453
	set_ia32_need_stackent(irn);
454

455
456
	if (i == n_ia32_binary_left                    &&
	    get_ia32_am_support(irn) == ia32_am_binary &&
457
458
	    /* immediates are only allowed on the right side */
	    !is_ia32_Immediate(get_irn_n(irn, n_ia32_binary_right))) {
459
		ia32_swap_left_right(irn);
460
		i = n_ia32_binary_right;
461
	}
462

463
464
	assert(is_NoMem(get_irn_n(irn, n_ia32_mem)));

465
466
	set_irn_n(irn, n_ia32_base, get_irg_frame(get_irn_irg(irn)));
	set_irn_n(irn, n_ia32_mem,  spill);
467
	set_irn_n(irn, i,           ia32_get_admissible_noreg(irn, i));
468
	set_ia32_is_reload(irn);
469
470
}

Sebastian Hack's avatar
Sebastian Hack committed
471
472
473
474
static const be_abi_callbacks_t ia32_abi_callbacks = {
	ia32_abi_get_between_type,
};

475
/* register allocator interface */
Matthias Braun's avatar
Matthias Braun committed
476
static const arch_irn_ops_t ia32_irn_ops = {
477
478
479
480
481
482
483
484
	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,
};

485
static int gprof = 0;
Michael Beck's avatar
Michael Beck committed
486

487
static void ia32_before_abi(ir_graph *irg)
488
{
489
	if (gprof) {
490
		static ir_entity *mcount = NULL;
Michael Beck's avatar
Michael Beck committed
491
		if (mcount == NULL) {
492
			ir_type *tp = new_type_method(0, 0);
493
494
			ident   *id = new_id_from_str("mcount");
			mcount = new_entity(get_glob_type(), id, tp);
Michael Beck's avatar
Michael Beck committed
495
496
			/* FIXME: enter the right ld_ident here */
			set_entity_ld_ident(mcount, get_entity_ident(mcount));
497
			set_entity_visibility(mcount, ir_visibility_external);
Michael Beck's avatar
Michael Beck committed
498
		}
499
		instrument_initcall(irg, mcount);
Michael Beck's avatar
Michael Beck committed
500
	}
501
502
503
504
505
506
}

/**
 * Transforms the standard firm graph into
 * an ia32 firm graph
 */
507
static void ia32_prepare_graph(ir_graph *irg)
508
{
509
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
510

511
#ifdef FIRM_GRGEN_BE
512
	switch (be_transformer) {
513
514
	case TRANSFORMER_DEFAULT:
		/* transform remaining nodes into assembler instructions */
515
		ia32_transform_graph(irg);
516
		break;
517

518
519
520
	case TRANSFORMER_PBQP:
	case TRANSFORMER_RAND:
		/* transform nodes into assembler instructions by PBQP magic */
521
		ia32_transform_graph_by_pbqp(irg);
522
		break;
523

524
525
	default:
		panic("invalid transformer");
526
	}
527
#else
528
	ia32_transform_graph(irg);
529
#endif
530

yb9976's avatar
typo    
yb9976 committed
531
	/* do local optimizations (mainly CSE) */
532
	optimize_graph_df(irg);
533
	/* backend code expects that outedges are always enabled */
534
	assure_edges(irg);
535

536
537
	if (irg_data->dump)
		dump_ir_graph(irg, "transformed");
Christian Würdig's avatar
Christian Würdig committed
538

539
	/* optimize address mode */
540
	ia32_optimize_graph(irg);
541

542
	/* do code placement, to optimize the position of constants */
543
	place_code(irg);
544
	/* backend code expects that outedges are always enabled */
545
	assure_edges(irg);
546

547
548
	if (irg_data->dump)
		dump_ir_graph(irg, "place");
Christian Würdig's avatar
Christian Würdig committed
549
550
}

551
ir_node *ia32_turn_back_am(ir_node *node)
552
553
{
	dbg_info *dbgi  = get_irn_dbg_info(node);
554
	ir_graph *irg   = get_irn_irg(node);
555
	ir_node  *block = get_nodes_block(node);
556
	ir_node  *base  = get_irn_n(node, n_ia32_base);
557
	ir_node  *idx   = get_irn_n(node, n_ia32_index);
558
	ir_node  *mem   = get_irn_n(node, n_ia32_mem);
559
	ir_node  *noreg;
560

561
	ir_node  *load     = new_bd_ia32_Load(dbgi, block, base, idx, mem);
562
	ir_node  *load_res = new_rd_Proj(dbgi, load, mode_Iu, pn_ia32_Load_res);
563
564

	ia32_copy_am_attrs(load, node);
565
566
	if (is_ia32_is_reload(node))
		set_ia32_is_reload(load);
567
	set_irn_n(node, n_ia32_mem, get_irg_no_mem(irg));
568

569
	switch (get_ia32_am_support(node)) {
570
571
572
573
574
		case ia32_am_unary:
			set_irn_n(node, n_ia32_unary_op, load_res);
			break;

		case ia32_am_binary:
575
			if (is_ia32_Immediate(get_irn_n(node, n_ia32_binary_right))) {
576
577
578
579
580
581
				set_irn_n(node, n_ia32_binary_left, load_res);
			} else {
				set_irn_n(node, n_ia32_binary_right, load_res);
			}
			break;

582
		default:
583
			panic("Unknown AM type");
584
	}
585
	noreg = ia32_new_NoReg_gp(irg);
586
	set_irn_n(node, n_ia32_base,  noreg);
587
588
589
590
591
	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);
592
593

	/* rewire mem-proj */
Michael Beck's avatar
Michael Beck committed
594
	if (get_irn_mode(node) == mode_T) {
595
596
		foreach_out_edge(node, edge) {
			ir_node *out = get_edge_src_irn(edge);
597
598
599
600
			if (get_irn_mode(out) == mode_M) {
				set_Proj_pred(out, load);
				set_Proj_proj(out, pn_ia32_Load_M);
				break;
601
602
603
604
605
			}
		}
	}

	set_ia32_op_type(node, ia32_Normal);
Michael Beck's avatar
Michael Beck committed
606
	if (sched_is_scheduled(node))
607
		sched_add_before(node, load);
608
609

	return load_res;
610
611
612
613
614
}

static ir_node *flags_remat(ir_node *node, ir_node *after)
{
	/* we should turn back source address mode when rematerializing nodes */
615
	ia32_op_type_t type;
616
	ir_node        *block;
617
618
	ir_node        *copy;

Michael Beck's avatar
Michael Beck committed
619
	if (is_Block(after)) {
620
621
622
623
624
		block = after;
	} else {
		block = get_nodes_block(after);
	}

625
	type = get_ia32_op_type(node);
626
	switch (type) {
627
		case ia32_AddrModeS:
628
			ia32_turn_back_am(node);
629
			break;
630
631
632
633
634
635

		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;
636
637
	}

638
	copy = exact_copy(node);
639
	set_nodes_block(copy, block);
640
641
642
643
644
	sched_add_after(after, copy);

	return copy;
}

645
646
647
/**
 * Called before the register allocator.
 */
648
static void ia32_before_ra(ir_graph *irg)
649
{
650
	/* setup fpu rounding modes */
651
	ia32_setup_fpu_mode(irg);
652
653

	/* fixup flags */
654
	be_sched_fix_flags(irg, &ia32_reg_classes[CLASS_ia32_flags],
655
	                   &flags_remat, NULL);
656

657
	be_add_missing_keeps(irg);
658
}
659

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

Christian Würdig's avatar
Christian Würdig committed
661
/**
662
 * Transforms a be_Reload into a ia32 Load.
Christian Würdig's avatar
Christian Würdig committed
663
 */
664
static void transform_to_Load(ir_node *node)
665
{
666
	ir_graph *irg        = get_irn_irg(node);
667
	dbg_info *dbgi       = get_irn_dbg_info(node);
668
669
670
	ir_node *block       = get_nodes_block(node);
	ir_entity *ent       = be_get_frame_entity(node);
	ir_mode *mode        = get_irn_mode(node);
671
	ir_mode *spillmode   = get_spill_mode(node);
672
	ir_node *noreg       = ia32_new_NoReg_gp(irg);
673
	ir_node *ptr         = get_irg_frame(irg);
674
	ir_node *mem         = get_irn_n(node, n_be_Reload_mem);
Christian Würdig's avatar
Christian Würdig committed
675
	ir_node *new_op, *proj;
676
	const arch_register_t *reg;
Christian Würdig's avatar
Christian Würdig committed
677

678
	if (mode_is_float(spillmode)) {
679
		if (ia32_cg_config.use_sse2)
680
			new_op = new_bd_ia32_xLoad(dbgi, block, ptr, noreg, mem, spillmode);
681
		else
682
			new_op = new_bd_ia32_fld(dbgi, block, ptr, noreg, mem, spillmode);
Christian Würdig's avatar
Christian Würdig committed
683
	}
684
	else if (get_mode_size_bits(spillmode) == 128) {
685
		/* Reload 128 bit SSE registers */
686
		new_op = new_bd_ia32_xxLoad(dbgi, block, ptr, noreg, mem);
687
	}
688
	else
689
		new_op = new_bd_ia32_Load(dbgi, block, ptr, noreg, mem);
Christian Würdig's avatar
Christian Würdig committed
690
691

	set_ia32_op_type(new_op, ia32_AddrModeS);
692
	set_ia32_ls_mode(new_op, spillmode);
Christian Würdig's avatar
Christian Würdig committed
693
694
	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);
695
	set_ia32_is_reload(new_op);
Christian Würdig's avatar
Christian Würdig committed
696

697
	DBG_OPT_RELOAD2LD(node, new_op);
698

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

701
	sched_replace(node, new_op);
Christian Würdig's avatar
Christian Würdig committed
702

703
	/* copy the register from the old node to the new Load */
704
	reg = arch_get_irn_register(node);
705
	arch_set_irn_register(proj, reg);
706

707
	SET_IA32_ORIG_NODE(new_op, node);
Christian Würdig's avatar
Christian Würdig committed
708

709
	exchange(node, proj);
Christian Würdig's avatar
Christian Würdig committed
710
711
712
}

/**
713
 * Transforms a be_Spill node into a ia32 Store.
Christian Würdig's avatar
Christian Würdig committed
714
 */
715
static void transform_to_Store(ir_node *node)
716
{
717
	ir_graph *irg  = get_irn_irg(node);
718
	dbg_info *dbgi = get_irn_dbg_info(node);
719
720
	ir_node *block = get_nodes_block(node);
	ir_entity *ent = be_get_frame_entity(node);
721
	const ir_node *spillval = get_irn_n(node, n_be_Spill_val);
722
	ir_mode *mode  = get_spill_mode(spillval);
723
	ir_node *noreg = ia32_new_NoReg_gp(irg);
724
	ir_node *nomem = get_irg_no_mem(irg);
725
	ir_node *ptr   = get_irg_frame(irg);
726
	ir_node *val   = get_irn_n(node, n_be_Spill_val);
727
	ir_node *res;
728
	ir_node *store;
Christian Würdig's avatar
Christian Würdig committed
729
730

	if (mode_is_float(mode)) {
731
		if (ia32_cg_config.use_sse2) {
732
			store = new_bd_ia32_xStore(dbgi, block, ptr, noreg, nomem, val);
733
734
			res   = new_r_Proj(store, mode_M, pn_ia32_xStore_M);
		} else {
735
736
			store = new_bd_ia32_fst(dbgi, block, ptr, noreg, nomem, val, mode);
			res   = new_r_Proj(store, mode_M, pn_ia32_fst_M);
737
		}
738
	} else if (get_mode_size_bits(mode) == 128) {
739
		/* Spill 128 bit SSE registers */
740
		store = new_bd_ia32_xxStore(dbgi, block, ptr, noreg, nomem, val);
741
		res   = new_r_Proj(store, mode_M, pn_ia32_xxStore_M);
742
	} else {
743
744
745
		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);
746
		res   = new_r_Proj(store, mode_M, pn_ia32_Store_M);
Christian Würdig's avatar
Christian Würdig committed
747
748
	}

749
750
751
752
	set_ia32_op_type(store, ia32_AddrModeD);
	set_ia32_ls_mode(store, mode);
	set_ia32_frame_ent(store, ent);
	set_ia32_use_frame(store);
753
	set_ia32_is_spill(store);
754
	SET_IA32_ORIG_NODE(store, node);
755
	DBG_OPT_SPILL2ST(node, store);
Christian Würdig's avatar
Christian Würdig committed
756

757
	sched_replace(node, store);
758
	exchange(node, res);
Christian Würdig's avatar
Christian Würdig committed
759
760
}

761
static ir_node *create_push(ir_node *node, ir_node *schedpoint, ir_node *sp, ir_node *mem, ir_entity *ent)
762
{
763
764
765
766
767
	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);
768

769
	ir_node *push = new_bd_ia32_Push(dbgi, block, frame, noreg, mem, noreg, sp);
770
771
772
773
774

	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);
775
	set_ia32_is_spill(push);
776
777
778
779
780

	sched_add_before(schedpoint, push);
	return push;
}

781
static ir_node *create_pop(ir_node *node, ir_node *schedpoint, ir_node *sp, ir_entity *ent)
782
{
783
	dbg_info *dbgi  = get_irn_dbg_info(node);
784
785
786
787
	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);
788

789
	ir_node *pop = new_bd_ia32_PopMem(dbgi, block, frame, noreg,
790
	                                  get_irg_no_mem(irg), sp);
791
792
793
794
795

	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);
796
	set_ia32_is_reload(pop);
797
798
799
800
801
802

	sched_add_before(schedpoint, pop);

	return pop;
}

803
804
static ir_node* create_spproj(ir_node *node, ir_node *pred, int pos)
{
805
806
	dbg_info *dbgi   = get_irn_dbg_info(node);
	ir_mode  *spmode = mode_Iu;
807
	const arch_register_t *spreg = &ia32_registers[REG_ESP];
808
809
	ir_node *sp;