bearch_ia32.c 61.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"
Christian Würdig's avatar
Christian Würdig committed
56

57
58
59
60
61
#include "beabi.h"
#include "beirg.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
76
#include "be_t.h"
#include "beirgmod.h"
#include "be_dbgout.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"
77

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

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

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

transformer_t be_transformer = TRANSFORMER_DEFAULT;
96
97
#endif

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

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

109
110
111
112
113
114
115
116
117
118
119
120
121
/**
 * The environment for the intrinsic mapping.
 */
static ia32_intrinsic_env_t intrinsic_env = {
	NULL,    /* the isa */
	NULL,    /* the irg, these entities belong to */
	NULL,    /* entity for __divdi3 library call */
	NULL,    /* entity for __moddi3 library call */
	NULL,    /* entity for __udivdi3 library call */
	NULL,    /* entity for __umoddi3 library call */
};


122
typedef ir_node *(*create_const_node_func) (dbg_info *dbgi, ir_node *block);
123

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

133
	if (*place != NULL)
134
135
		return *place;

136
	block = get_irg_start_block(irg);
137
	res = func(NULL, block);
138
	arch_set_irn_register(res, reg);
139
140
141
142
143
	*place = res;

	return res;
}

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

152
ir_node *ia32_new_NoReg_vfp(ir_graph *irg)
153
{
154
155
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
	return create_const(irg, &irg_data->noreg_vfp, new_bd_ia32_NoReg_VFP,
156
	                    &ia32_registers[REG_VFP_NOREG]);
157
158
}

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

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

173

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

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

186
	if (ia32_cg_config.use_sse2) {
187
		return ia32_new_NoReg_xmm(irg);
188
	} else {
189
		return ia32_new_NoReg_vfp(irg);
190
	}
191
192
}

193
194
195
/**
 * The IA32 ABI callback object.
 */
196
typedef struct {
197
198
	be_abi_call_flags_bits_t flags;  /**< The call flags. */
	ir_graph *irg;                   /**< The associated graph. */
199
200
} ia32_abi_env_t;

201
202
static ir_entity *ia32_get_frame_entity(const ir_node *irn)
{
Christian Würdig's avatar
Christian Würdig committed
203
	return is_ia32_irn(irn) ? get_ia32_frame_ent(irn) : NULL;
204
205
}

206
static void ia32_set_frame_entity(ir_node *node, ir_entity *entity)
207
{
208
209
210
211
	if (is_be_node(node))
		be_node_set_frame_entity(node, entity);
	else
		set_ia32_frame_ent(node, entity);
212
213
}

214
static void ia32_set_frame_offset(ir_node *irn, int bias)
215
216
217
{
	if (get_ia32_frame_ent(irn) == NULL)
		return;
218

219
	if (is_ia32_Pop(irn) || is_ia32_PopMem(irn)) {
220
221
222
		ir_graph          *irg     = get_irn_irg(irn);
		be_stack_layout_t *layout  = be_get_irg_stack_layout(irg);
		if (layout->sp_relative) {
223
224
225
226
227
			/* Pop nodes modify the stack pointer before calculating the
			 * destination address, so fix this here
			 */
			bias -= 4;
		}
228
	}
229
	add_ia32_am_offs_int(irn, bias);
230
231
}

232
static int ia32_get_sp_bias(const ir_node *node)
233
{
234
235
236
	if (is_ia32_Call(node))
		return -(int)get_ia32_call_attr_const(node)->pop;

237
238
239
	if (is_ia32_Push(node))
		return 4;

240
	if (is_ia32_Pop(node) || is_ia32_PopMem(node))
241
		return -4;
242

243
	if (is_ia32_Leave(node) || is_ia32_CopyEbpEsp(node)) {
244
245
246
		return SP_BIAS_RESET;
	}

247
248
249
	return 0;
}

Sebastian Hack's avatar
Sebastian Hack committed
250
/**
251
 * Build the between type and entities if not already build.
Sebastian Hack's avatar
Sebastian Hack committed
252
 */
253
254
static void ia32_build_between_type(void)
{
255
#define IDENT(s) new_id_from_chars(s, sizeof(s)-1)
256
	if (between_type == NULL) {
257
258
		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
259

260
261
262
		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
263

264
265
266
		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));
267
		set_type_state(between_type, layout_fixed);
268
269
270
271
272
273
274

		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
275
	}
276
277
278
279
280
281
282
283
#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.
 */
284
static ir_type *ia32_abi_get_between_type(ir_graph *irg)
285
{
286
	const be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
287
	ia32_build_between_type();
288
	return layout->sp_relative ? omit_fp_between_type : between_type;
289
290
291
292
293
}

/**
 * Return the stack entity that contains the return address.
 */
294
ir_entity *ia32_get_return_address_entity(ir_graph *irg)
295
{
296
	const be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
297
	ia32_build_between_type();
298
	return layout->sp_relative ? omit_fp_ret_addr_ent : ret_addr_ent;
299
300
301
302
303
}

/**
 * Return the stack entity that contains the frame address.
 */
304
ir_entity *ia32_get_frame_address_entity(ir_graph *irg)
305
{
306
	const be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
307
	ia32_build_between_type();
308
	return layout->sp_relative ? NULL : old_bp_ent;
Sebastian Hack's avatar
Sebastian Hack committed
309
310
}

311
312
313
314
315
316
317
318
/**
 * 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
 */
319
static int ia32_get_op_estimated_cost(const ir_node *irn)
320
{
321
	int            cost;
Christian Würdig's avatar
Christian Würdig committed
322
	ia32_op_type_t op_tp;
Adam Szalkowski's avatar
Adam Szalkowski committed
323

Christian Würdig's avatar
Christian Würdig committed
324
	if (is_Proj(irn))
325
326
327
		return 0;
	if (!is_ia32_irn(irn))
		return 0;
Adam Szalkowski's avatar
Adam Szalkowski committed
328

Christian Würdig's avatar
Christian Würdig committed
329
330
331
332
333
334
335
336
337
	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
338
		int size = get_ia32_copyb_size(irn);
Christian Würdig's avatar
Christian Würdig committed
339
340
341
342
343
		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) {
		/*
344
345
346
			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
347
		*/
348
		if (is_ia32_use_frame(irn) || (
349
350
		    is_ia32_NoReg_GP(get_irn_n(irn, n_ia32_base)) &&
		    is_ia32_NoReg_GP(get_irn_n(irn, n_ia32_index))
351
		    )) {
352
353
354
355
			cost += 5;
		} else {
			cost += 20;
		}
Christian Würdig's avatar
Christian Würdig committed
356
357
358
	}

	return cost;
359
360
}

Christian Würdig's avatar
Christian Würdig committed
361
362
363
364
365
366
367
368
369
/**
 * Returns the inverse operation if @p irn, recalculating the argument at position @p i.
 *
 * @param irn       The original operation
 * @param i         Index of the argument we want the inverse operation to yield
 * @param inverse   struct to be filled with the resulting inverse op
 * @param obstack   The obstack to use for allocation of the returned nodes array
 * @return          The inverse operation or NULL if operation invertible
 */
370
371
static arch_inverse_t *ia32_get_inverse(const ir_node *irn, int i, arch_inverse_t *inverse, struct obstack *obst)
{
372
373
374
375
376
377
378
	(void) irn;
	(void) i;
	(void) inverse;
	(void) obst;
	return NULL;

#if 0
379
	ir_mode  *mode;
380
	ir_mode  *irn_mode;
381
	ir_node  *block, *noreg, *nomem;
382
	dbg_info *dbgi;
383
384
385
386
387
388

	/* we cannot invert non-ia32 irns */
	if (! is_ia32_irn(irn))
		return NULL;

	/* operand must always be a real operand (not base, index or mem) */
389
	if (i != n_ia32_binary_left && i != n_ia32_binary_right)
390
391
392
393
394
395
		return NULL;

	/* we don't invert address mode operations */
	if (get_ia32_op_type(irn) != ia32_Normal)
		return NULL;

396
397
398
399
400
	/* TODO: adjust for new immediates... */
	ir_fprintf(stderr, "TODO: fix get_inverse for new immediates (%+F)\n",
	           irn);
	return NULL;

401
	block    = get_nodes_block(irn);
402
	mode     = get_irn_mode(irn);
403
404
	irn_mode = get_irn_mode(irn);
	noreg    = get_irn_n(irn, 0);
405
	nomem    = get_irg_no_mem(irg);
406
	dbgi     = get_irn_dbg_info(irn);
407
408

	/* initialize structure */
409
	inverse->nodes = obstack_alloc(obst, 2 * sizeof(inverse->nodes[0]));
410
	inverse->costs = 0;
411
	inverse->n     = 1;
412

413
	switch (get_ia32_irn_opcode(irn)) {
414
415
416
417
		case iro_ia32_Add:
			if (get_ia32_immop_type(irn) == ia32_ImmConst) {
				/* we have an add with a const here */
				/* invers == add with negated const */
418
				inverse->nodes[0] = new_bd_ia32_Add(dbgi, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
419
420
421
422
423
424
425
426
				inverse->costs   += 1;
				copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
				set_ia32_Immop_tarval(inverse->nodes[0], tarval_neg(get_ia32_Immop_tarval(irn)));
				set_ia32_commutative(inverse->nodes[0]);
			}
			else if (get_ia32_immop_type(irn) == ia32_ImmSymConst) {
				/* we have an add with a symconst here */
				/* invers == sub with const */
427
				inverse->nodes[0] = new_bd_ia32_Sub(dbgi, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
428
				inverse->costs   += 2;
429
430
431
432
				copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
			}
			else {
				/* normal add: inverse == sub */
433
				inverse->nodes[0] = new_bd_ia32_Sub(dbgi, block, noreg, noreg, nomem, (ir_node*) irn, get_irn_n(irn, i ^ 1));
434
				inverse->costs   += 2;
435
436
437
438
439
440
			}
			break;
		case iro_ia32_Sub:
			if (get_ia32_immop_type(irn) != ia32_ImmNone) {
				/* we have a sub with a const/symconst here */
				/* invers == add with this const */
441
				inverse->nodes[0] = new_bd_ia32_Add(dbgi, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
442
443
444
445
446
				inverse->costs   += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1;
				copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
			}
			else {
				/* normal sub */
447
				if (i == n_ia32_binary_left) {
448
					inverse->nodes[0] = new_bd_ia32_Add(dbgi, block, noreg, noreg, nomem, (ir_node*) irn, get_irn_n(irn, 3));
449
450
				}
				else {
451
					inverse->nodes[0] = new_bd_ia32_Sub(dbgi, block, noreg, noreg, nomem, get_irn_n(irn, n_ia32_binary_left), (ir_node*) irn);
452
453
454
455
				}
				inverse->costs += 1;
			}
			break;
456
		case iro_ia32_Xor:
457
458
			if (get_ia32_immop_type(irn) != ia32_ImmNone) {
				/* xor with const: inverse = xor */
459
				inverse->nodes[0] = new_bd_ia32_Xor(dbgi, block, noreg, noreg, nomem, get_irn_n(irn, i), noreg);
460
461
462
463
464
				inverse->costs   += (get_ia32_immop_type(irn) == ia32_ImmSymConst) ? 5 : 1;
				copy_ia32_Immop_attr(inverse->nodes[0], (ir_node *)irn);
			}
			else {
				/* normal xor */
465
				inverse->nodes[0] = new_bd_ia32_Xor(dbgi, block, noreg, noreg, nomem, (ir_node *) irn, get_irn_n(irn, i));
466
467
468
				inverse->costs   += 1;
			}
			break;
469
		case iro_ia32_Not: {
470
			inverse->nodes[0] = new_bd_ia32_Not(dbgi, block, (ir_node*) irn);
471
472
			inverse->costs   += 1;
			break;
473
		}
474
		case iro_ia32_Neg: {
475
			inverse->nodes[0] = new_bd_ia32_Neg(dbgi, block, (ir_node*) irn);
476
477
			inverse->costs   += 1;
			break;
478
		}
479
480
481
482
483
484
		default:
			/* inverse operation not supported */
			return NULL;
	}

	return inverse;
485
#endif
Christian Würdig's avatar
Christian Würdig committed
486
487
}

488
489
static ir_mode *get_spill_mode_mode(const ir_mode *mode)
{
490
	if (mode_is_float(mode))
491
492
493
494
495
		return mode_D;

	return mode_Iu;
}

496
497
498
/**
 * Get the mode that should be used for spilling value node
 */
499
static ir_mode *get_spill_mode(const ir_node *node)
500
501
{
	ir_mode *mode = get_irn_mode(node);
502
	return get_spill_mode_mode(mode);
503
504
505
}

/**
Michael Beck's avatar
Michael Beck committed
506
 * Checks whether an addressmode reload for a node with mode mode is compatible
507
508
509
510
 * with a spillslot of mode spill_mode
 */
static int ia32_is_spillmode_compatible(const ir_mode *mode, const ir_mode *spillmode)
{
511
	return !mode_is_float(mode) || mode == spillmode;
512
513
}

514
/**
Christoph Mallon's avatar
Christoph Mallon committed
515
 * Check if irn can load its operand at position i from memory (source addressmode).
516
517
518
519
 * @param irn    The irn to be checked
 * @param i      The operands position
 * @return Non-Zero if operand can be loaded
 */
520
521
522
523
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);
524
	const ir_mode *spillmode = get_spill_mode(op);
525

526
527
528
529
	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 */
530
531
		return 0;

532
533
534
535
	switch (get_ia32_am_support(irn)) {
		case ia32_am_none:
			return 0;

536
		case ia32_am_unary:
537
538
539
			if (i != n_ia32_unary_op)
				return 0;
			break;
540
541
542
543
544
545
546
547
548
549
550

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

					/* we can't swap left/right for limited registers
					 * (As this (currently) breaks constraint handling copies)
					 */
551
					req = arch_get_irn_register_req_in(irn, n_ia32_binary_left);
552
553
					if (req->type & arch_register_req_type_limited)
						return 0;
554
					break;
555
556
557
				}

				case n_ia32_binary_right:
558
					break;
559

560
561
562
				default:
					return 0;
			}
563
			break;
564
565

		default:
566
			panic("Unknown AM type");
567
	}
568
569
570
571
572
573
574

	/* 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;
575
576
}

577
578
static void ia32_perform_memory_operand(ir_node *irn, ir_node *spill,
                                        unsigned int i)
579
{
580
581
582
	ir_mode *load_mode;
	ir_mode *dest_op_mode;

583
	assert(ia32_possible_memory_operand(irn, i) && "Cannot perform memory operand change");
584
585

	set_ia32_op_type(irn, ia32_AddrModeS);
586
587
588
589
590
591

	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);
	}
592
	set_ia32_use_frame(irn);
593
	set_ia32_need_stackent(irn);
594

595
596
	if (i == n_ia32_binary_left                    &&
	    get_ia32_am_support(irn) == ia32_am_binary &&
597
598
	    /* immediates are only allowed on the right side */
	    !is_ia32_Immediate(get_irn_n(irn, n_ia32_binary_right))) {
599
		ia32_swap_left_right(irn);
600
		i = n_ia32_binary_right;
601
	}
602

603
604
	assert(is_NoMem(get_irn_n(irn, n_ia32_mem)));

605
606
	set_irn_n(irn, n_ia32_base, get_irg_frame(get_irn_irg(irn)));
	set_irn_n(irn, n_ia32_mem,  spill);
607
	set_irn_n(irn, i,           ia32_get_admissible_noreg(irn, i));
608
	set_ia32_is_reload(irn);
609
610
}

Sebastian Hack's avatar
Sebastian Hack committed
611
612
613
614
static const be_abi_callbacks_t ia32_abi_callbacks = {
	ia32_abi_get_between_type,
};

615
/* register allocator interface */
Matthias Braun's avatar
Matthias Braun committed
616
static const arch_irn_ops_t ia32_irn_ops = {
617
618
619
620
621
622
623
624
625
	ia32_get_frame_entity,
	ia32_set_frame_offset,
	ia32_get_sp_bias,
	ia32_get_inverse,
	ia32_get_op_estimated_cost,
	ia32_possible_memory_operand,
	ia32_perform_memory_operand,
};

Michael Beck's avatar
Michael Beck committed
626
static ir_entity *mcount = NULL;
627
static int gprof = 0;
Michael Beck's avatar
Michael Beck committed
628

629
static void ia32_before_abi(ir_graph *irg)
630
{
631
	if (gprof) {
Michael Beck's avatar
Michael Beck committed
632
		if (mcount == NULL) {
633
			ir_type *tp = new_type_method(0, 0);
634
635
			ident   *id = new_id_from_str("mcount");
			mcount = new_entity(get_glob_type(), id, tp);
Michael Beck's avatar
Michael Beck committed
636
637
			/* FIXME: enter the right ld_ident here */
			set_entity_ld_ident(mcount, get_entity_ident(mcount));
638
			set_entity_visibility(mcount, ir_visibility_external);
Michael Beck's avatar
Michael Beck committed
639
		}
640
		instrument_initcall(irg, mcount);
Michael Beck's avatar
Michael Beck committed
641
	}
642
643
644
645
646
647
}

/**
 * Transforms the standard firm graph into
 * an ia32 firm graph
 */
648
static void ia32_prepare_graph(ir_graph *irg)
649
{
650
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
651

652
#ifdef FIRM_GRGEN_BE
653
	switch (be_transformer) {
654
655
	case TRANSFORMER_DEFAULT:
		/* transform remaining nodes into assembler instructions */
656
		ia32_transform_graph(irg);
657
		break;
658

659
660
661
	case TRANSFORMER_PBQP:
	case TRANSFORMER_RAND:
		/* transform nodes into assembler instructions by PBQP magic */
662
		ia32_transform_graph_by_pbqp(irg);
663
		break;
664

665
666
	default:
		panic("invalid transformer");
667
	}
668
#else
669
	ia32_transform_graph(irg);
670
#endif
671

yb9976's avatar
typo    
yb9976 committed
672
	/* do local optimizations (mainly CSE) */
673
	optimize_graph_df(irg);
674
675
	/* backend code expects that outedges are always enabled */
	edges_assure(irg);
676

677
678
	if (irg_data->dump)
		dump_ir_graph(irg, "transformed");
Christian Würdig's avatar
Christian Würdig committed
679

680
	/* optimize address mode */
681
	ia32_optimize_graph(irg);
682

683
	/* do code placement, to optimize the position of constants */
684
	place_code(irg);
685
686
	/* backend code expects that outedges are always enabled */
	edges_assure(irg);
687

688
689
	if (irg_data->dump)
		dump_ir_graph(irg, "place");
Christian Würdig's avatar
Christian Würdig committed
690
691
}

692
ir_node *ia32_turn_back_am(ir_node *node)
693
694
{
	dbg_info *dbgi  = get_irn_dbg_info(node);
695
	ir_graph *irg   = get_irn_irg(node);
696
	ir_node  *block = get_nodes_block(node);
697
	ir_node  *base  = get_irn_n(node, n_ia32_base);
698
	ir_node  *idx   = get_irn_n(node, n_ia32_index);
699
	ir_node  *mem   = get_irn_n(node, n_ia32_mem);
700
	ir_node  *noreg;
701

702
	ir_node  *load     = new_bd_ia32_Load(dbgi, block, base, idx, mem);
703
	ir_node  *load_res = new_rd_Proj(dbgi, load, mode_Iu, pn_ia32_Load_res);
704
705

	ia32_copy_am_attrs(load, node);
706
707
	if (is_ia32_is_reload(node))
		set_ia32_is_reload(load);
708
	set_irn_n(node, n_ia32_mem, get_irg_no_mem(irg));
709

710
	switch (get_ia32_am_support(node)) {
711
712
713
714
715
		case ia32_am_unary:
			set_irn_n(node, n_ia32_unary_op, load_res);
			break;

		case ia32_am_binary:
716
			if (is_ia32_Immediate(get_irn_n(node, n_ia32_binary_right))) {
717
718
719
720
721
722
				set_irn_n(node, n_ia32_binary_left, load_res);
			} else {
				set_irn_n(node, n_ia32_binary_right, load_res);
			}
			break;

723
		default:
724
			panic("Unknown AM type");
725
	}
726
	noreg = ia32_new_NoReg_gp(current_ir_graph);
727
	set_irn_n(node, n_ia32_base,  noreg);
728
729
730
731
732
	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);
733
734

	/* rewire mem-proj */
Michael Beck's avatar
Michael Beck committed
735
	if (get_irn_mode(node) == mode_T) {
736
		const ir_edge_t *edge;
737
738
		foreach_out_edge(node, edge) {
			ir_node *out = get_edge_src_irn(edge);
739
740
741
742
			if (get_irn_mode(out) == mode_M) {
				set_Proj_pred(out, load);
				set_Proj_proj(out, pn_ia32_Load_M);
				break;
743
744
745
746
747
			}
		}
	}

	set_ia32_op_type(node, ia32_Normal);
Michael Beck's avatar
Michael Beck committed
748
	if (sched_is_scheduled(node))
749
		sched_add_before(node, load);
750
751

	return load_res;
752
753
754
755
756
}

static ir_node *flags_remat(ir_node *node, ir_node *after)
{
	/* we should turn back source address mode when rematerializing nodes */
757
	ia32_op_type_t type;
758
	ir_node        *block;
759
760
	ir_node        *copy;

Michael Beck's avatar
Michael Beck committed
761
	if (is_Block(after)) {
762
763
764
765
766
		block = after;
	} else {
		block = get_nodes_block(after);
	}

767
	type = get_ia32_op_type(node);
768
	switch (type) {
769
		case ia32_AddrModeS:
770
			ia32_turn_back_am(node);
771
			break;
772
773
774
775
776
777

		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;
778
779
	}

780
	copy = exact_copy(node);
781
	set_nodes_block(copy, block);
782
783
784
785
786
	sched_add_after(after, copy);

	return copy;
}

787
788
789
/**
 * Called before the register allocator.
 */
790
static void ia32_before_ra(ir_graph *irg)
791
{
792
	/* setup fpu rounding modes */
793
	ia32_setup_fpu_mode(irg);
794
795

	/* fixup flags */
796
	be_sched_fix_flags(irg, &ia32_reg_classes[CLASS_ia32_flags],
797
	                   &flags_remat, NULL);
798

799
	be_add_missing_keeps(irg);
800
}
801

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

Christian Würdig's avatar
Christian Würdig committed
803
/**
804
 * Transforms a be_Reload into a ia32 Load.
Christian Würdig's avatar
Christian Würdig committed
805
 */
806
static void transform_to_Load(ir_node *node)
807
{
808
	ir_graph *irg        = get_irn_irg(node);
809
	dbg_info *dbgi       = get_irn_dbg_info(node);
810
811
812
	ir_node *block       = get_nodes_block(node);
	ir_entity *ent       = be_get_frame_entity(node);
	ir_mode *mode        = get_irn_mode(node);
813
	ir_mode *spillmode   = get_spill_mode(node);
814
	ir_node *noreg       = ia32_new_NoReg_gp(irg);
Christian Würdig's avatar
Christian Würdig committed
815
	ir_node *sched_point = NULL;
816
	ir_node *ptr         = get_irg_frame(irg);
817
	ir_node *mem         = get_irn_n(node, n_be_Reload_mem);
Christian Würdig's avatar
Christian Würdig committed
818
	ir_node *new_op, *proj;
819
	const arch_register_t *reg;
Christian Würdig's avatar
Christian Würdig committed
820

821
822
	if (sched_is_scheduled(node)) {
		sched_point = sched_prev(node);
Christian Würdig's avatar
Christian Würdig committed
823
824
	}

825
	if (mode_is_float(spillmode)) {
826
		if (ia32_cg_config.use_sse2)
827
			new_op = new_bd_ia32_xLoad(dbgi, block, ptr, noreg, mem, spillmode);
828
		else
829
			new_op = new_bd_ia32_vfld(dbgi, block, ptr, noreg, mem, spillmode);
Christian Würdig's avatar
Christian Würdig committed
830
	}
831
	else if (get_mode_size_bits(spillmode) == 128) {
832
		/* Reload 128 bit SSE registers */
833
		new_op = new_bd_ia32_xxLoad(dbgi, block, ptr, noreg, mem);
834
	}
835
	else
836
		new_op = new_bd_ia32_Load(dbgi, block, ptr, noreg, mem);
Christian Würdig's avatar
Christian Würdig committed
837
838

	set_ia32_op_type(new_op, ia32_AddrModeS);
839
	set_ia32_ls_mode(new_op, spillmode);
Christian Würdig's avatar
Christian Würdig committed
840
841
	set_ia32_frame_ent(new_op, ent);
	set_ia32_use_frame(new_op);
842
	set_ia32_is_reload(new_op);
Christian Würdig's avatar
Christian Würdig committed
843

844
	DBG_OPT_RELOAD2LD(node, new_op);
845

846
	proj = new_rd_Proj(dbgi, new_op, mode, pn_ia32_Load_res);
Christian Würdig's avatar
Christian Würdig committed
847
848
849

	if (sched_point) {
		sched_add_after(sched_point, new_op);
850
		sched_remove(node);
Christian Würdig's avatar
Christian Würdig committed
851
852
	}

853
	/* copy the register from the old node to the new Load */
854
	reg = arch_get_irn_register(node);