ia32_bearch.c 51.4 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
12
#include "ia32_bearch_t.h"

13
#include "be_t.h"
Matthias Braun's avatar
Matthias Braun committed
14
15
16
#include "beflags.h"
#include "begnuas.h"
#include "bemodule.h"
17
#include "bera.h"
Matthias Braun's avatar
Matthias Braun committed
18
19
20
21
#include "besched.h"
#include "bespillslots.h"
#include "bestack.h"
#include "beutil.h"
22
#include "bevarargs.h"
23
24
25
#include "gen_ia32_regalloc_if.h"
#include "ia32_architecture.h"
#include "ia32_emitter.h"
26
#include "ia32_encode.h"
27
28
29
30
31
#include "ia32_finish.h"
#include "ia32_fpu.h"
#include "ia32_new_nodes.h"
#include "ia32_optimize.h"
#include "ia32_transform.h"
32
#include "ident_t.h"
Matthias Braun's avatar
Matthias Braun committed
33
#include "instrument.h"
34
#include "ircons.h"
35
#include "iredges_t.h"
Christian Würdig's avatar
Christian Würdig committed
36
#include "irgmod.h"
Christian Würdig's avatar
Christian Würdig committed
37
#include "irgopt.h"
Matthias Braun's avatar
Matthias Braun committed
38
#include "irgwalk.h"
39
#include "iropt_t.h"
Matthias Braun's avatar
Matthias Braun committed
40
41
#include "irtools.h"
#include "lc_opts_enum.h"
42
#include "lower_alloc.h"
Matthias Braun's avatar
Matthias Braun committed
43
#include "lower_builtins.h"
44
#include "lower_calls.h"
45
#include "lower_mode_b.h"
46
#include "lower_softfloat.h"
47
#include "lowering.h"
Matthias Braun's avatar
Matthias Braun committed
48
#include "panic.h"
49
#include "x86_x87.h"
50

51
52
pmap *ia32_tv_ent; /**< A map of entities that store const tarvals */

53
ir_mode *ia32_mode_fpcw;
54
ir_mode *ia32_mode_flags;
55
ir_mode *ia32_mode_8h;
56
57
58
ir_mode *ia32_mode_gp;
ir_mode *ia32_mode_float64;
ir_mode *ia32_mode_float32;
59

60
/** The current omit-fp state */
Matthias Braun's avatar
Matthias Braun committed
61
62
63
64
65
static ir_type   *omit_fp_between_type;
static ir_type   *between_type;
static ir_entity *old_bp_ent;
static ir_entity *ret_addr_ent;
static ir_entity *omit_fp_ret_addr_ent;
66
static bool       return_small_struct_in_regs;
67

68
typedef ir_node *(*create_const_node_func) (dbg_info *dbgi, ir_node *block);
69

70
/**
71
 * Used to create per-graph unique pseudo nodes.
72
 */
73
static inline ir_node *create_const(ir_graph *irg, ir_node **place,
74
                                    create_const_node_func func,
75
                                    const arch_register_t* reg)
76
{
77
	if (*place != NULL)
78
79
		return *place;

Matthias Braun's avatar
Matthias Braun committed
80
81
	ir_node *block = get_irg_start_block(irg);
	ir_node *res   = func(NULL, block);
82
	arch_set_irn_register(res, reg);
83
	*place = res;
84
85
86
	/* We need a keep edge on our cached nodes, so that following firm
	 * irgwalks will not miss them. */
	keep_alive(res);
87
88
89
	return res;
}

90
ir_node *ia32_new_NoReg_gp(ir_graph *irg)
91
{
92
93
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
	return create_const(irg, &irg_data->noreg_gp, new_bd_ia32_NoReg_GP,
94
	                    &ia32_registers[REG_GP_NOREG]);
95
96
}

97
ir_node *ia32_new_NoReg_fp(ir_graph *irg)
98
{
99
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
100
101
	return create_const(irg, &irg_data->noreg_fp, new_bd_ia32_NoReg_FP,
	                    &ia32_registers[REG_FP_NOREG]);
102
103
}

104
ir_node *ia32_new_NoReg_xmm(ir_graph *irg)
105
{
106
107
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
	return create_const(irg, &irg_data->noreg_xmm, new_bd_ia32_NoReg_XMM,
108
	                    &ia32_registers[REG_XMM_NOREG]);
109
110
}

111
ir_node *ia32_new_Fpu_truncate(ir_graph *irg)
112
{
113
114
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
	return create_const(irg, &irg_data->fpu_trunc_mode, new_bd_ia32_ChangeCW,
115
                        &ia32_registers[REG_FPCW]);
116
117
}

118
/**
119
 * Returns the admissible noreg register node for input register pos of node irn.
120
 */
121
static ir_node *ia32_get_admissible_noreg(ir_node *irn, int pos)
122
{
123
	ir_graph                  *irg = get_irn_irg(irn);
124
	const arch_register_req_t *req = arch_get_irn_register_req_in(irn, pos);
Matthias Braun's avatar
Matthias Braun committed
125
	if (req->cls == &ia32_reg_classes[CLASS_ia32_gp])
126
		return ia32_new_NoReg_gp(irg);
Matthias Braun's avatar
Matthias Braun committed
127

128
	if (ia32_cg_config.use_sse2) {
129
		return ia32_new_NoReg_xmm(irg);
130
	} else {
131
		return ia32_new_NoReg_fp(irg);
132
	}
133
134
}

135
static ir_entity *ia32_get_frame_entity(const ir_node *node)
136
{
137
138
139
	if (!is_ia32_irn(node))
		return NULL;
	ia32_attr_t const *const attr = get_ia32_attr_const(node);
140
	if (attr->am_imm.kind == X86_IMM_FRAMEENT) {
141
142
143
144
145
		assert(get_ia32_frame_use(node) != IA32_FRAME_USE_NONE);
		return attr->am_imm.entity;
	}
	assert(get_ia32_frame_use(node) == IA32_FRAME_USE_NONE);
	return NULL;
146
147
}

148
149
static void ia32_set_frame_entity(ir_node *node, ir_entity *entity,
                                  const ir_type *type)
150
{
151
152
	ia32_attr_t *const attr = get_ia32_attr(node);
	attr->am_imm = (x86_imm32_t) {
153
		.kind   = X86_IMM_FRAMEENT,
154
155
156
157
		.entity = entity,
		.offset = attr->am_imm.offset,
	};
	assert(get_ia32_frame_use(node) != IA32_FRAME_USE_NONE);
158

yb9976's avatar
yb9976 committed
159
	/* set ls_mode based on entity unless we explicitly requested
160
	 * a certain mode */
yb9976's avatar
yb9976 committed
161
162
	if (get_ia32_frame_use(node) != IA32_FRAME_USE_AUTO
	    || is_ia32_Cmp(node) || is_ia32_Conv_I2I(node))
163
164
165
166
167
168
169
170
		return;
	ir_mode *mode = get_type_mode(type);
	/** we 8bit stores have a special register requirement, so we can't simply
	 * change the ls_mode to 8bit here. The "hack" in
	 * ia32_collect_frame_entity_nodes() should take care that it never happens
	 */
	assert(!is_ia32_Store(node) || get_mode_size_bits(mode) > 8);
	set_ia32_ls_mode(node, mode);
171
172
}

173
static void ia32_set_frame_offset(ir_node *node, int bias)
174
{
175
	ia32_attr_t *const attr = get_ia32_attr(node);
176
	assert(attr->am_imm.kind == X86_IMM_FRAMEENT);
177

178
179
180
181
182
183
	/* Pop nodes modify the stack pointer before calculating the
	 * destination address, fix this here */
	if (is_ia32_PopMem(node)) {
		ir_node *base = get_irn_n(node, n_ia32_PopMem_base);
		if (arch_get_irn_register(base) == &ia32_registers[REG_ESP]) {
			ir_mode *mode = get_ia32_ls_mode(node);
Matthias Braun's avatar
Matthias Braun committed
184
			bias -= get_mode_size_bytes(mode);
185
		}
186
	}
187
188
189
190
191
192
193
194

#ifndef NDEBUG
	attr->old_frame_ent = attr->am_imm.entity;
#endif
	/* This is just a simple 32bit value now */
	attr->am_imm.offset += bias;
	attr->am_imm.entity = NULL;
	attr->am_imm.kind   = X86_IMM_VALUE;
195
196
}

197
int ia32_get_sp_bias(const ir_node *node)
198
{
199
200
201
	if (is_ia32_Call(node))
		return -(int)get_ia32_call_attr_const(node)->pop;

Matthias Braun's avatar
Matthias Braun committed
202
203
204
205
	if (is_ia32_Push(node)) {
		ir_mode *ls_mode = get_ia32_ls_mode(node);
		return get_mode_size_bytes(ls_mode);
	}
206

Matthias Braun's avatar
Matthias Braun committed
207
208
209
210
	if (is_ia32_Pop(node) || is_ia32_PopMem(node)) {
		ir_mode *ls_mode = get_ia32_ls_mode(node);
		return -get_mode_size_bytes(ls_mode);
	}
211

Matthias Braun's avatar
Matthias Braun committed
212
	if (is_ia32_Leave(node) || is_ia32_CopyEbpEsp(node))
213
214
		return SP_BIAS_RESET;

215
216
217
	return 0;
}

Sebastian Hack's avatar
Sebastian Hack committed
218
/**
219
 * Build the between type and entities if not already built.
Sebastian Hack's avatar
Sebastian Hack committed
220
 */
221
222
static void ia32_build_between_type(void)
{
223
	if (between_type == NULL) {
224
225
		ir_type *old_bp_type   = new_type_primitive(ia32_mode_gp);
		ir_type *ret_addr_type = new_type_primitive(ia32_mode_gp);
Sebastian Hack's avatar
Sebastian Hack committed
226

227
228
229
		between_type = new_type_struct(NEW_IDENT("ia32_between_type"));
		old_bp_ent   = new_entity(between_type, NEW_IDENT("old_bp"), old_bp_type);
		ret_addr_ent = new_entity(between_type, NEW_IDENT("ret_addr"), ret_addr_type);
Sebastian Hack's avatar
Sebastian Hack committed
230

231
		set_entity_offset(old_bp_ent, 0);
232
233
		set_entity_offset(ret_addr_ent, get_type_size(old_bp_type));
		set_type_size(between_type, get_type_size(old_bp_type) + get_type_size(ret_addr_type));
234
		set_type_state(between_type, layout_fixed);
235

236
237
		omit_fp_between_type = new_type_struct(NEW_IDENT("ia32_between_type_omit_fp"));
		omit_fp_ret_addr_ent = new_entity(omit_fp_between_type, NEW_IDENT("ret_addr"), ret_addr_type);
238
239

		set_entity_offset(omit_fp_ret_addr_ent, 0);
240
		set_type_size(omit_fp_between_type, get_type_size(ret_addr_type));
241
		set_type_state(omit_fp_between_type, layout_fixed);
Sebastian Hack's avatar
Sebastian Hack committed
242
	}
243
244
245
246
247
}

/**
 * Return the stack entity that contains the return address.
 */
248
ir_entity *ia32_get_return_address_entity(ir_graph *irg)
249
{
250
	ia32_build_between_type();
251
252
	return ia32_get_irg_data(irg)->omit_fp ? omit_fp_ret_addr_ent
	                                       : ret_addr_ent;
253
254
255
256
257
}

/**
 * Return the stack entity that contains the frame address.
 */
258
ir_entity *ia32_get_frame_address_entity(ir_graph *irg)
259
{
260
	ia32_build_between_type();
261
	return ia32_get_irg_data(irg)->omit_fp ? NULL : old_bp_ent;
Sebastian Hack's avatar
Sebastian Hack committed
262
263
}

264
265
266
267
268
269
270
/**
 * Get the estimated cycle count for @p irn.
 *
 * @param irn  The node.
 *
 * @return     The estimated cycle count for this operation
 */
271
static unsigned ia32_get_op_estimated_cost(ir_node const *const irn)
272
{
273
274
275
	if (!is_ia32_irn(irn))
		return 1;

276
	if (is_ia32_CopyB_i(irn)) {
277
278
		unsigned const size = get_ia32_copyb_size(irn);
		return 20 + size * 4 / 3;
Christian Würdig's avatar
Christian Würdig committed
279
	}
280
281
282

	unsigned cost = get_ia32_latency(irn);

Christian Würdig's avatar
Christian Würdig committed
283
	/* in case of address mode operations add additional cycles */
284
	if (get_ia32_op_type(irn) != ia32_Normal) {
285
		if (get_ia32_frame_use(irn) != IA32_FRAME_USE_NONE || (
286
287
		      is_ia32_NoReg_GP(get_irn_n(irn, n_ia32_base)) &&
		      is_ia32_NoReg_GP(get_irn_n(irn, n_ia32_index))
288
		    )) {
289
			/* Stack access, assume it is cached. */
290
291
			cost += 5;
		} else {
292
			/* Access probably elsewhere. */
293
294
			cost += 20;
		}
Christian Würdig's avatar
Christian Würdig committed
295
296
297
	}

	return cost;
298
299
}

300
static ir_mode *get_spill_mode(const ir_node *value)
301
{
302
303
304
305
306
	/* determine a sensible spill mode and try to make it small */
	const ir_node *skipped = skip_Proj_const(value);
	if (is_ia32_fld(skipped) || is_ia32_Load(skipped))
		return get_ia32_ls_mode(skipped);

307
	return get_irn_mode(value);
308
309
}

310
/**
Christoph Mallon's avatar
Christoph Mallon committed
311
 * Check if irn can load its operand at position i from memory (source addressmode).
312
313
 * @param irn    The irn to be checked
 * @param i      The operands position
314
 * @return whether operand can be loaded
315
 */
316
static bool ia32_possible_memory_operand(const ir_node *irn, unsigned int i)
317
{
318
319
	if (!is_ia32_irn(irn)                    || /* must be an ia32 irn */
	    get_ia32_op_type(irn) != ia32_Normal || /* must not already be a addressmode irn */
320
	    get_ia32_frame_use(irn) != IA32_FRAME_USE_NONE) /* must not already use frame */
Matthias Braun's avatar
Matthias Braun committed
321
		return false;
322

323
	switch (get_ia32_am_support(irn)) {
Matthias Braun's avatar
cleanup    
Matthias Braun committed
324
	case ia32_am_none:
Matthias Braun's avatar
Matthias Braun committed
325
		return false;
Matthias Braun's avatar
cleanup    
Matthias Braun committed
326
327
328

	case ia32_am_unary:
		if (i != n_ia32_unary_op)
Matthias Braun's avatar
Matthias Braun committed
329
			return false;
Matthias Braun's avatar
cleanup    
Matthias Braun committed
330
		break;
331

Matthias Braun's avatar
cleanup    
Matthias Braun committed
332
333
334
335
	case ia32_am_binary:
		switch (i) {
		case n_ia32_binary_left: {
			if (!is_ia32_commutative(irn))
Matthias Braun's avatar
Matthias Braun committed
336
				return false;
337

Matthias Braun's avatar
cleanup    
Matthias Braun committed
338
339
340
			/* we can't swap left/right for limited registers
			 * (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);
341
			if (req->limited != NULL)
Matthias Braun's avatar
Matthias Braun committed
342
				return false;
Matthias Braun's avatar
cleanup    
Matthias Braun committed
343
344
			break;
		}
345

Matthias Braun's avatar
cleanup    
Matthias Braun committed
346
		case n_ia32_binary_right:
347
			break;
348
349

		default:
Matthias Braun's avatar
Matthias Braun committed
350
			return false;
Matthias Braun's avatar
cleanup    
Matthias Braun committed
351
352
353
354
		}
		break;

	default:
355
		panic("unknown AM type");
356
	}
357
358
359
360

	/* HACK: must not already use "real" memory.
	 * This can happen for Call and Div */
	if (!is_NoMem(get_irn_n(irn, n_ia32_mem)))
Matthias Braun's avatar
Matthias Braun committed
361
		return false;
362

363
364
365
366
367
368
369
370
371
372
373
374
375
	ir_node       *const op   = get_irn_n(irn, i);
	ir_node const *const load = get_Proj_pred(op);
	ir_mode const *const mode = get_ia32_ls_mode(load);
	if (mode_is_float(mode)) {
		if (mode != ia32_mode_float64 && mode != mode_F)
			return false;
		/* Don't do reload folding for x87 nodes for now, as we can't predict
		 * yet wether the spillslot must be widened to 80bit for which no AM
		 * operations exist. */
		if (is_ia32_fld(load))
			return false;
	}

Matthias Braun's avatar
Matthias Braun committed
376
	return true;
377
378
}

379
static void ia32_perform_memory_operand(ir_node *irn, unsigned int i)
380
{
381
382
	if (!ia32_possible_memory_operand(irn, i))
		return;
383

384
385
386
387
	ir_node *op           = get_irn_n(irn, i);
	ir_node *load         = get_Proj_pred(op);
	ir_mode *load_mode    = get_ia32_ls_mode(load);
	ir_node *spill        = get_irn_n(load, n_ia32_mem);
388
	ir_mode *dest_op_mode = get_ia32_ls_mode(irn);
Matthias Braun's avatar
Matthias Braun committed
389
	if (get_mode_size_bits(load_mode) <= get_mode_size_bits(dest_op_mode))
390
		set_ia32_ls_mode(irn, load_mode);
391
	set_ia32_op_type(irn, ia32_AddrModeS);
392
	set_ia32_frame_use(irn, IA32_FRAME_USE_AUTO);
393

394
395
	if (i == n_ia32_binary_left                    &&
	    get_ia32_am_support(irn) == ia32_am_binary &&
396
397
	    /* immediates are only allowed on the right side */
	    !is_ia32_Immediate(get_irn_n(irn, n_ia32_binary_right))) {
398
		ia32_swap_left_right(irn);
399
		i = n_ia32_binary_right;
400
	}
401

402
403
	assert(is_NoMem(get_irn_n(irn, n_ia32_mem)));

404
405
	set_irn_n(irn, n_ia32_base, get_irg_frame(get_irn_irg(irn)));
	set_irn_n(irn, n_ia32_mem,  spill);
406
	set_irn_n(irn, i,           ia32_get_admissible_noreg(irn, i));
407
	set_ia32_is_reload(irn);
408
409
410
411
412
413
414

	/* kill the reload */
	assert(get_irn_n_edges(op) == 0);
	assert(get_irn_n_edges(load) == 1);
	sched_remove(load);
	kill_node(op);
	kill_node(load);
415
416
}

Matthias Braun's avatar
Matthias Braun committed
417
static bool gprof;
Michael Beck's avatar
Michael Beck committed
418

419
420
421
422
423
424
425
static ir_node *ia32_turn_back_dest_am(ir_node *node)
{
	typedef ir_node *construct_binop_func(
		dbg_info *db, ir_node *block,
		ir_node *base, ir_node *index, ir_node *mem,
		ir_node *op1, ir_node *op2);

yb9976's avatar
yb9976 committed
426
427
428
	ir_mode *ls_mode = get_ia32_ls_mode(node);
	bool     is_8bit = get_mode_size_bits(ls_mode) == 8;

429
	construct_binop_func *func;
430
	switch (get_ia32_irn_opcode(node)) {
yb9976's avatar
yb9976 committed
431
432
433
434
435
	case iro_ia32_AddMem: func = is_8bit ? new_bd_ia32_Add_8bit : new_bd_ia32_Add; break;
	case iro_ia32_AndMem: func = is_8bit ? new_bd_ia32_And_8bit : new_bd_ia32_And; break;
	case iro_ia32_OrMem:  func = is_8bit ? new_bd_ia32_Or_8bit  : new_bd_ia32_Or;  break;
	case iro_ia32_SubMem: func = is_8bit ? new_bd_ia32_Sub_8bit : new_bd_ia32_Sub; break;
	case iro_ia32_XorMem: func = is_8bit ? new_bd_ia32_Xor_8bit : new_bd_ia32_Xor; break;
436
	default: panic("cannot turn back DestAM for %+F", node);
437
438
	}

439
440
441
442
443
444
	dbg_info *const dbgi  = get_irn_dbg_info(node);
	ir_node  *const block = get_nodes_block(node);
	ir_node  *const base  = get_irn_n(node, n_ia32_base);
	ir_node  *const idx   = get_irn_n(node, n_ia32_index);
	ir_node  *const mem   = get_irn_n(node, n_ia32_mem);
	ir_node  *const load  = new_bd_ia32_Load(dbgi, block, base, idx, mem);
445
446
447
	ia32_copy_am_attrs(load, node);
	if (is_ia32_is_reload(node))
		set_ia32_is_reload(load);
448
	sched_add_before(node, load);
449
450
	ir_node *const load_res = be_new_Proj(load, pn_ia32_Load_res);
	ir_node *const load_mem = be_new_Proj(load, pn_ia32_Load_M);
451
452
453
454
455
456

	ir_graph *const irg      = get_irn_irg(node);
	ir_node  *const noreg    = ia32_new_NoReg_gp(irg);
	ir_node  *const nomem    = get_irg_no_mem(irg);
	ir_node  *const operand  = get_irn_n(node, n_ia32_binary_left);
	ir_node  *const new_node = func(dbgi, block, noreg, noreg, nomem, load_res, operand);
yb9976's avatar
yb9976 committed
457
	set_ia32_ls_mode(new_node, ls_mode);
458
459
	set_irn_mode(new_node, mode_T);

460
	arch_set_irn_register_out(new_node, pn_ia32_flags, &ia32_registers[REG_EFLAGS]);
461

462
	ir_node *const res_proj = be_new_Proj(new_node, pn_ia32_res);
yb9976's avatar
yb9976 committed
463
464
	ir_node *const store    = is_8bit ? new_bd_ia32_Store_8bit(dbgi, block, base, idx, load_mem, res_proj)
	                                  : new_bd_ia32_Store(dbgi, block, base, idx, load_mem, res_proj);
465
466
	ia32_copy_am_attrs(store, node);
	set_ia32_op_type(store, ia32_AddrModeD);
467
	sched_add_after(node, store);
468

469
470
471
	ir_node *const mem_proj = get_Proj_for_pn(node, pn_ia32_M);
	set_Proj_pred(mem_proj, store);
	set_Proj_num(mem_proj, pn_ia32_Store_M);
472

473
474
	sched_replace(node, new_node);
	exchange(node, new_node);
475
476
477
	return new_node;
}

478
ir_node *ia32_turn_back_am(ir_node *node)
479
{
Matthias Braun's avatar
Matthias Braun committed
480
481
482
483
484
485
	dbg_info *dbgi     = get_irn_dbg_info(node);
	ir_graph *irg      = get_irn_irg(node);
	ir_node  *block    = get_nodes_block(node);
	ir_node  *base     = get_irn_n(node, n_ia32_base);
	ir_node  *idx      = get_irn_n(node, n_ia32_index);
	ir_node  *mem      = get_irn_n(node, n_ia32_mem);
486
	ir_node  *load     = new_bd_ia32_Load(dbgi, block, base, idx, mem);
487
	ir_node  *load_res = be_new_Proj(load, pn_ia32_Load_res);
488
489

	ia32_copy_am_attrs(load, node);
490
491
	if (is_ia32_is_reload(node))
		set_ia32_is_reload(load);
492
	set_irn_n(node, n_ia32_mem, get_irg_no_mem(irg));
493

494
	switch (get_ia32_am_support(node)) {
Matthias Braun's avatar
cleanup    
Matthias Braun committed
495
496
497
	case ia32_am_unary:
		set_irn_n(node, n_ia32_unary_op, load_res);
		break;
498

Matthias Braun's avatar
cleanup    
Matthias Braun committed
499
500
501
502
503
504
505
	case ia32_am_binary:
		if (is_ia32_Immediate(get_irn_n(node, n_ia32_binary_right))) {
			set_irn_n(node, n_ia32_binary_left, load_res);
		} else {
			set_irn_n(node, n_ia32_binary_right, load_res);
		}
		break;
506

Matthias Braun's avatar
cleanup    
Matthias Braun committed
507
	default:
508
		panic("unknown AM type");
509
	}
Matthias Braun's avatar
Matthias Braun committed
510
	ir_node *noreg = ia32_new_NoReg_gp(irg);
511
	set_irn_n(node, n_ia32_base,  noreg);
512
	set_irn_n(node, n_ia32_index, noreg);
513
514
	ia32_attr_t *const attr = get_ia32_attr(node);
	attr->am_imm = (x86_imm32_t) { .kind = X86_IMM_VALUE, .offset = 0 };
515
	attr->frame_use = IA32_FRAME_USE_NONE;
516
	set_ia32_am_scale(node, 0);
517
518

	/* rewire mem-proj */
Michael Beck's avatar
Michael Beck committed
519
	if (get_irn_mode(node) == mode_T) {
520
521
		foreach_out_edge(node, edge) {
			ir_node *out = get_edge_src_irn(edge);
522
523
			if (get_irn_mode(out) == mode_M) {
				set_Proj_pred(out, load);
524
				set_Proj_num(out, pn_ia32_Load_M);
525
				break;
526
527
528
529
530
			}
		}
	}

	set_ia32_op_type(node, ia32_Normal);
Michael Beck's avatar
Michael Beck committed
531
	if (sched_is_scheduled(node))
532
		sched_add_before(node, load);
533
534

	return load_res;
535
536
537
538
}

static ir_node *flags_remat(ir_node *node, ir_node *after)
{
539
	/* we should turn back address modes when rematerializing nodes */
Christoph Mallon's avatar
Christoph Mallon committed
540
	ir_node *const block = get_block(after);
541

Matthias Braun's avatar
Matthias Braun committed
542
	ia32_op_type_t type = get_ia32_op_type(node);
543
	switch (type) {
Matthias Braun's avatar
cleanup    
Matthias Braun committed
544
545
546
	case ia32_AddrModeS:
		ia32_turn_back_am(node);
		break;
547

Matthias Braun's avatar
cleanup    
Matthias Braun committed
548
	case ia32_AddrModeD:
549
550
		node = ia32_turn_back_dest_am(node);
		break;
551

Matthias Braun's avatar
Matthias Braun committed
552
553
554
	default:
		assert(type == ia32_Normal);
		break;
555
556
	}

Matthias Braun's avatar
Matthias Braun committed
557
	ir_node *copy = exact_copy(node);
558
	set_nodes_block(copy, block);
559
560
561
562
	sched_add_after(after, copy);
	return copy;
}

563
564
COMPILETIME_ASSERT((int)(n_ia32_Sub_minuend)    == (int)(n_ia32_Cmp_left) &&
                   (int)(n_ia32_Sub_subtrahend) == (int)(n_ia32_Cmp_right),
Matthias Braun's avatar
Matthias Braun committed
565
                   Cmp_and_Sub_operand_numbers_equal)
566

567
static bool ia32_try_replace_flags(ir_node *consumers, ir_node *flags, ir_node *available)
568
{
569
570
	if (!is_ia32_Sub(flags) && !is_ia32_Cmp(flags))
		return false;
571
572
573
574
575
576
	unsigned pn;
	if (is_ia32_Sub(available)) {
		pn = pn_ia32_Sub_flags;
	} else if (is_ia32_Cmp(available)) {
		pn = pn_ia32_Cmp_eflags;
	} else {
577
		return false;
578
	}
579
580
581
582
583
584
585
586
587
588
589
	/* Assuming CSE would have found the more obvious case */
	ir_node *const flags_left  = get_irn_n(flags,     n_ia32_binary_left);
	ir_node *const avail_right = get_irn_n(available, n_ia32_binary_right);
	if (flags_left != avail_right)
		return false;
	ir_node *const avail_left  = get_irn_n(available, n_ia32_binary_left);
	ir_node *const flags_right = get_irn_n(flags,     n_ia32_binary_right);
	if (avail_left != flags_right)
		return false;

	/* We can use available if we reverse the consumers' condition codes. */
590
	arch_set_irn_register_out(available, pn, &ia32_registers[REG_EFLAGS]);
591
	ir_node *const proj      = get_irn_mode(available) == mode_T ? be_get_or_make_Proj_for_pn(available, pn) : available;
592
593
594
595
596
597
	ir_mode *const flag_mode = ia32_reg_classes[CLASS_ia32_flags].mode;
	for (ir_node *c = consumers; c != NULL; c = get_irn_link(c)) {
		x86_condition_code_t cc = get_ia32_condcode(c);
		set_ia32_condcode(c, x86_invert_condition_code(cc));

		foreach_irn_in(c, i, in) {
598
			if (get_irn_mode(in) == flag_mode)
599
				set_irn_n(c, i, proj);
600
601
		}
	}
602
	return true;
603
604
}

605
static void remat_simplifier(ir_node *node, void *env)
606
607
608
{
	(void)env;

609
610
	/* A Sub with unused result is a Cmp. */
	if (is_ia32_Sub(node) && get_irn_mode(node) == mode_T) {
611
		ir_node *projs[] = { [pn_ia32_Sub_M] = NULL };
612
		foreach_out_edge(node, out) {
613
614
615
616
617
			ir_node *const proj = get_edge_src_irn(out);
			unsigned const num  = get_Proj_num(proj);
			assert(num < ARRAY_SIZE(projs));
			assert(!projs[num] && "duplicate Proj");
			projs[num] = proj;
618
		}
619

620
621
622
623
624
625
626
627
628
629
		ir_node       *res_keep = NULL;
		ir_node *const sub_res  = projs[pn_ia32_Sub_res];
		if (sub_res) {
			foreach_out_edge(sub_res, out) {
				ir_node *const user = get_edge_src_irn(out);
				if (be_is_Keep(user)) {
					assert(!res_keep && "Proj has two be_Keep");
					res_keep = user;
				} else {
					return;
630
				}
631
			}
632
		}
633

634
635
636
637
638
639
640
641
642
643
644
		dbg_info *const dbgi    = get_irn_dbg_info(node);
		ir_node  *const block   = get_nodes_block(node);
		ir_node  *const base    = get_irn_n(node, n_ia32_Sub_base);
		ir_node  *const idx     = get_irn_n(node, n_ia32_Sub_index);
		ir_node  *const mem     = get_irn_n(node, n_ia32_Sub_mem);
		ir_node  *const minu    = get_irn_n(node, n_ia32_Sub_minuend);
		ir_node  *const subt    = get_irn_n(node, n_ia32_Sub_subtrahend);
		ir_mode  *const ls_mode = get_ia32_ls_mode(node);
		bool            is_8bit = get_mode_size_bits(ls_mode) == 8;
		ir_node        *cmp     = is_8bit ? new_bd_ia32_Cmp_8bit(dbgi, block, base, idx, mem, minu, subt, false)
		                                  : new_bd_ia32_Cmp(dbgi, block, base, idx, mem, minu, subt, false);
645
646
647
648
649
650
651
652
653
654
655
656
657
		arch_set_irn_register(cmp, &ia32_registers[REG_EFLAGS]);
		ia32_copy_am_attrs(cmp, node);

		sched_replace(node, cmp);

		if (get_ia32_op_type(node) == ia32_AddrModeS) {
			set_ia32_op_type(cmp, ia32_AddrModeS);
			set_irn_mode(cmp, mode_T);

			ir_node *const sub_mem = projs[pn_ia32_Sub_M];
			if (sub_mem) {
				ir_node *const proj_M = be_new_Proj(cmp, pn_ia32_Cmp_M);
				exchange(sub_mem, proj_M);
658
659
			}

660
661
662
			cmp = be_new_Proj(cmp, pn_ia32_Cmp_eflags);
		} else {
			assert(get_ia32_op_type(node) == ia32_Normal);
663
664
		}

665
666
667
668
669
670
671
672
		exchange(projs[pn_ia32_Sub_flags], cmp);

		if (res_keep) {
			sched_remove(res_keep);
			remove_keep_alive(res_keep);
			kill_node(res_keep);
		}
		kill_node(node);
673
	}
674
675
676
677
}

static void simplify_remat_nodes(ir_graph *irg)
{
678
679
	irg_walk_graph(irg, remat_simplifier, NULL, NULL);
	remove_End_Bads_and_doublets(get_irg_end(irg));
680
681
}

682
static ir_node *ia32_new_spill(ir_node *value, ir_node *after)
683
{
684
685
686
687
688
689
	ir_graph *irg   = get_irn_irg(value);
	ir_node  *block = get_block(after);
	ir_node  *frame = get_irg_frame(irg);
	ir_mode  *mode  = get_spill_mode(value);
	ir_node  *noreg = ia32_new_NoReg_gp(irg);
	ir_node  *nomem = get_irg_no_mem(irg);
Christian Würdig's avatar
Christian Würdig committed
690

691
	ir_node *res;
692
	ir_node *store;
Christian Würdig's avatar
Christian Würdig committed
693
	if (mode_is_float(mode)) {
694
		if (ia32_cg_config.use_sse2) {
695
			store = new_bd_ia32_xStore(NULL, block, frame, noreg, nomem, value);
696
			res   = be_new_Proj(store, pn_ia32_xStore_M);
697
		} else {
698
			store = new_bd_ia32_fst(NULL, block, frame, noreg, nomem, value, mode);
699
			res   = be_new_Proj(store, pn_ia32_fst_M);
700
		}
701
	} else if (get_mode_size_bits(mode) == 128) {
702
		/* Spill 128 bit SSE registers */
703
		store = new_bd_ia32_xxStore(NULL, block, frame, noreg, nomem, value);
704
		res   = be_new_Proj(store, pn_ia32_xxStore_M);
705
	} else {
706
		store = get_mode_size_bits(mode) == 8
707
708
			? new_bd_ia32_Store_8bit(NULL, block, frame, noreg, nomem, value)
			: new_bd_ia32_Store     (NULL, block, frame, noreg, nomem, value);
709
		res   = be_new_Proj(store, pn_ia32_Store_M);
Christian Würdig's avatar
Christian Würdig committed
710
	}
711
712
	set_ia32_op_type(store, ia32_AddrModeD);
	set_ia32_ls_mode(store, mode);
713
	set_ia32_frame_use(store, IA32_FRAME_USE_AUTO);
714
	set_ia32_is_spill(store);
715
	sched_add_after(after, store);
Christian Würdig's avatar
Christian Würdig committed
716

717
718
719
720
721
722
723
	return res;
}

static ir_node *ia32_new_reload(ir_node *value, ir_node *spill, ir_node *before)
{
	ir_graph *irg       = get_irn_irg(before);
	ir_node  *block     = get_block(before);
724
	ir_mode  *spillmode = get_spill_mode(value);
725
726
727
	ir_node  *noreg     = ia32_new_NoReg_gp(irg);
	ir_node  *frame     = get_irg_frame(irg);

728
	ir_node *load;
729
	if (mode_is_float(spillmode)) {
730
		if (ia32_cg_config.use_sse2) {
731
			load = new_bd_ia32_xLoad(NULL, block, frame, noreg, spill, spillmode);
732
		} else {
733
			load = new_bd_ia32_fld(NULL, block, frame, noreg, spill, spillmode);
734
		}
735
736
737
738
739
740
741
742
	} else if (get_mode_size_bits(spillmode) == 128) {
		/* Reload 128 bit SSE registers */
		load = new_bd_ia32_xxLoad(NULL, block, frame, noreg, spill);
	} else {
		load = new_bd_ia32_Load(NULL, block, frame, noreg, spill);
	}
	set_ia32_op_type(load, ia32_AddrModeS);
	set_ia32_ls_mode(load, spillmode);
743
	set_ia32_frame_use(load, IA32_FRAME_USE_AUTO);
744
745
746
747
	set_ia32_is_reload(load);
	arch_add_irn_flags(load, arch_irn_flag_reload);
	sched_add_before(before, load);

748
	return be_new_Proj(load, pn_ia32_res);
Christian Würdig's avatar
Christian Würdig committed
749
750
}

Matthias Braun's avatar
Matthias Braun committed
751
752
static ir_node *create_push(ir_node *node, ir_node *schedpoint, ir_node *sp,
                            ir_node *mem, ir_entity *ent, ir_mode *mode)
753
{
754
755
756
757
758
	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);
759

760
761
762
763
	ir_node *const push = new_bd_ia32_Push(dbgi, block, frame, noreg, mem,
	                                       noreg, sp, mode);
	ia32_attr_t *const attr = get_ia32_attr(push);
	attr->am_imm = (x86_imm32_t) {
764
		.kind   = X86_IMM_FRAMEENT,
765
766
767
		.entity = ent,
	};
	set_ia32_frame_use(push, IA32_FRAME_USE_AUTO);
768
	set_ia32_op_type(push, ia32_AddrModeS);
769
	set_ia32_is_spill(push);
770
771
772
773
774

	sched_add_before(schedpoint, push);
	return push;
}

Matthias Braun's avatar
Matthias Braun committed
775
776
static ir_node *create_pop(ir_node *node, ir_node *schedpoint, ir_node *sp,
                           ir_entity *ent, ir_mode *mode)
777
{
778
	dbg_info *dbgi  = get_irn_dbg_info(node);
779
780
781
782
	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);
Matthias Braun's avatar
Matthias Braun committed
783
784
	ir_node  *pop   = new_bd_ia32_PopMem(dbgi, block, frame, noreg,
	                                     get_irg_no_mem(irg), sp);
785
786
	ia32_attr_t *const attr = get_ia32_attr(pop);
	attr->am_imm = (x86_imm32_t) {
787
		.kind   = X86_IMM_FRAMEENT,
788
789
790
		.entity = ent,
	};
	set_ia32_frame_use(pop, IA32_FRAME_USE_AUTO);
791
	set_ia32_op_type(pop, ia32_AddrModeD);
Matthias Braun's avatar
Matthias Braun committed
792
	set_ia32_ls_mode(pop, mode);
793
	set_ia32_is_reload(pop);
794
795
796
797
	sched_add_before(schedpoint, pop);
	return pop;
}

798
static ir_node *create_spproj(ir_node *const pred, unsigned const pos)
799
{
800
	return be_new_Proj_reg(pred, pos, &ia32_registers[REG_ESP]);
801
802
}

803
/**
804
 * Transform MemPerm, currently we do this the ugly way and produce
805
806
807
 * push/pop into/from memory cascades. This is possible without using
 * any registers.
 */
808
static void transform_MemPerm(ir_node *node)
809
{
810
	ir_graph *irg   = get_irn_irg(node);
Christoph Mallon's avatar
Christoph Mallon committed
811
	ir_node  *sp    = be_get_Start_proj(irg, &ia32_registers[REG_ESP]);
812
813
	int       arity = be_get_MemPerm_entity_arity(node);
	ir_node **pops  = ALLOCAN(ir_node*, arity);
814

815
	/* create Pushs */
Matthias Braun's avatar
Matthias Braun committed
816
	for (int i = 0; i < arity; ++i) {
817
818
819
		ir_entity *inent = be_get_MemPerm_in_entity(node, i);
		ir_entity *outent = be_get_MemPerm_out_entity(node, i);
		ir_type *enttype = get_entity_type(inent);
820
821
		unsigned entsize = get_type_size(enttype);
		unsigned entsize2 = get_type_size(get_entity_type(outent));
822
		ir_node *mem = get_irn_n(node, i);
823

824
		/* work around cases where entities have different sizes */
825
		if (entsize2 < entsize)
826
			entsize = entsize2;
827
828
829
830
831
832
833
834
835
836
837

		int offset = 0;
		do {
			ir_mode *mode;
			if (entsize%2 == 1) {
				mode = mode_Bu;
			} else if (entsize % 4