ia32_bearch.c 50.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 */
61
static bool return_small_struct_in_regs;
62

63
typedef ir_node *(*create_const_node_func) (dbg_info *dbgi, ir_node *block);
64

65
/**
66
 * Used to create per-graph unique pseudo nodes.
67
 */
68
static inline ir_node *create_const(ir_graph *irg, ir_node **place,
69
                                    create_const_node_func func,
70
                                    const arch_register_t* reg)
71
{
72
	if (*place != NULL)
73
74
		return *place;

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

85
ir_node *ia32_new_NoReg_gp(ir_graph *irg)
86
{
87
88
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
	return create_const(irg, &irg_data->noreg_gp, new_bd_ia32_NoReg_GP,
89
	                    &ia32_registers[REG_GP_NOREG]);
90
91
}

92
ir_node *ia32_new_NoReg_fp(ir_graph *irg)
93
{
94
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
95
96
	return create_const(irg, &irg_data->noreg_fp, new_bd_ia32_NoReg_FP,
	                    &ia32_registers[REG_FP_NOREG]);
97
98
}

99
ir_node *ia32_new_NoReg_xmm(ir_graph *irg)
100
{
101
102
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
	return create_const(irg, &irg_data->noreg_xmm, new_bd_ia32_NoReg_XMM,
103
	                    &ia32_registers[REG_XMM_NOREG]);
104
105
}

106
ir_node *ia32_new_Fpu_truncate(ir_graph *irg)
107
{
108
109
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
	return create_const(irg, &irg_data->fpu_trunc_mode, new_bd_ia32_ChangeCW,
110
                        &ia32_registers[REG_FPCW]);
111
112
}

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

123
	if (ia32_cg_config.use_sse2) {
124
		return ia32_new_NoReg_xmm(irg);
125
	} else {
126
		return ia32_new_NoReg_fp(irg);
127
	}
128
129
}

130
131
static void ia32_set_frame_entity(ir_node *node, ir_entity *entity,
                                  const ir_type *type)
132
{
133
134
	ia32_attr_t *const attr = get_ia32_attr(node);
	attr->am_imm = (x86_imm32_t) {
135
		.kind   = X86_IMM_FRAMEENT,
136
137
138
139
		.entity = entity,
		.offset = attr->am_imm.offset,
	};
	assert(get_ia32_frame_use(node) != IA32_FRAME_USE_NONE);
140

sebastian.buchwald1's avatar
sebastian.buchwald1 committed
141
	/* set ls_mode based on entity unless we explicitly requested
142
	 * a certain mode */
143
144
	if (get_ia32_frame_use(node) != IA32_FRAME_USE_AUTO
	    || is_ia32_Cmp(node) || is_ia32_Conv_I2I(node))
145
146
		return;
	ir_mode *mode = get_type_mode(type);
147
	/** 8bit stores have a special register requirement, so we can't simply
148
	 * change the ls_mode to 8bit here. The "hack" in
149
	 * ia32_collect_frame_entity_nodes() should take care that it never happens.
150
151
152
	 */
	assert(!is_ia32_Store(node) || get_mode_size_bits(mode) > 8);
	set_ia32_ls_mode(node, mode);
153
154
}

155
static bool node_has_sp_base(ir_node const *const node)
156
{
157
158
159
160
	assert(is_ia32_irn(node));
	arch_register_t const *const base_reg
		= arch_get_irn_register_in(node, n_ia32_base);
	return base_reg == &ia32_registers[REG_ESP];
161
162
}

163
static void ia32_determine_frameoffset(ir_node *node, int sp_offset)
164
{
165
166
	if (!is_ia32_irn(node))
		return;
167

168
169
170
171
172
173
174
175
	ia32_attr_t *const attr = get_ia32_attr(node);
	if (attr->am_imm.kind == X86_IMM_FRAMEENT) {
#ifndef NDEBUG
		attr->old_frame_ent = attr->am_imm.entity;
#endif
		attr->am_imm.offset += get_entity_offset(attr->am_imm.entity);
		attr->am_imm.entity  = NULL;
		attr->am_imm.kind    = X86_IMM_FRAMEOFFSET;
Matthias Braun's avatar
Matthias Braun committed
176
	}
177

178
179
180
181
182
183
184
185
186
187
188
	if (attr->am_imm.kind == X86_IMM_FRAMEOFFSET) {
		if (node_has_sp_base(node))
			attr->am_imm.offset += sp_offset;
		else {
			assert(arch_get_irn_register_in(node, n_ia32_base)
			       == &ia32_registers[REG_EBP]);
			/* we calculate offsets relative to the SP value at function begin,
			 * but EBP points after the saved old frame pointer */
			attr->am_imm.offset += IA32_REGISTER_SIZE;
		}
		attr->am_imm.kind = X86_IMM_VALUE;
Matthias Braun's avatar
Matthias Braun committed
189
	}
190
191
}

192
static void ia32_sp_sim(ir_node *const node, stack_pointer_state_t *state)
193
{
194
195
196
197
198
199
	/* Pop nodes modify the stack pointer before calculating destination
	 * address, so do this first */
	if (is_ia32_Pop(node) || is_ia32_PopMem(node)) {
		ir_mode *ls_mode = get_ia32_ls_mode(node);
		state->offset       -= get_mode_size_bytes(ls_mode);
	}
200

201
202
	if (!state->no_change)
		ia32_determine_frameoffset(node, state->offset);
203

204
205
206
207
208
209
210
211
212
213
	if (is_ia32_Call(node)) {
		state->offset -= get_ia32_call_attr_const(node)->pop;
	} else if (is_ia32_Push(node)) {
		ir_mode *ls_mode = get_ia32_ls_mode(node);
		state->offset       += get_mode_size_bytes(ls_mode);
	} else if (is_ia32_Leave(node) || is_ia32_CopyEbpEsp(node)) {
		state->offset        = 0;
		state->align_padding = 0;
	} else if (is_ia32_SubSP(node)) {
		state->align_padding = 0;
Sebastian Hack's avatar
Sebastian Hack committed
214
	}
215
216
}

217
int ia32_get_sp_change(ir_node *const node)
218
{
219
220
221
222
223
224
225
226
227
228
	if (be_is_IncSP(node))
		return -be_get_IncSP_offset(node);
	stack_pointer_state_t state = {
		.offset    = 160,
		.no_change = true,
	};
	ia32_sp_sim(node, &state);
	int res = 160 - state.offset;
	assert(-16 <= res && res <= 16);
	return res;
Sebastian Hack's avatar
Sebastian Hack committed
229
230
}

231
232
233
234
235
236
237
/**
 * Get the estimated cycle count for @p irn.
 *
 * @param irn  The node.
 *
 * @return     The estimated cycle count for this operation
 */
238
static unsigned ia32_get_op_estimated_cost(ir_node const *const irn)
239
{
240
241
242
	if (!is_ia32_irn(irn))
		return 1;

243
	if (is_ia32_CopyB_i(irn)) {
244
245
		unsigned const size = get_ia32_copyb_size(irn);
		return 20 + size * 4 / 3;
Christian Würdig's avatar
Christian Würdig committed
246
	}
247
248
249

	unsigned cost = get_ia32_latency(irn);

Christian Würdig's avatar
Christian Würdig committed
250
	/* in case of address mode operations add additional cycles */
251
	if (get_ia32_op_type(irn) != ia32_Normal) {
252
		if (get_ia32_frame_use(irn) != IA32_FRAME_USE_NONE || (
253
254
		      is_ia32_NoReg_GP(get_irn_n(irn, n_ia32_base)) &&
		      is_ia32_NoReg_GP(get_irn_n(irn, n_ia32_index))
255
		    )) {
256
			/* Stack access, assume it is cached. */
257
258
			cost += 5;
		} else {
259
			/* Access probably elsewhere. */
260
261
			cost += 20;
		}
Christian Würdig's avatar
Christian Würdig committed
262
263
264
	}

	return cost;
265
266
}

267
static ir_mode *get_spill_mode(const ir_node *value)
268
{
269
270
271
272
273
	/* 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);

274
	return get_irn_mode(value);
275
276
}

277
/**
Christoph Mallon's avatar
Christoph Mallon committed
278
 * Check if irn can load its operand at position i from memory (source addressmode).
279
280
 * @param irn    The irn to be checked
 * @param i      The operands position
281
 * @return whether operand can be loaded
282
 */
283
static bool ia32_possible_memory_operand(const ir_node *irn, unsigned int i)
284
{
285
286
	if (!is_ia32_irn(irn)                    || /* must be an ia32 irn */
	    get_ia32_op_type(irn) != ia32_Normal || /* must not already be a addressmode irn */
287
	    get_ia32_frame_use(irn) != IA32_FRAME_USE_NONE) /* must not already use frame */
Matthias Braun's avatar
Matthias Braun committed
288
		return false;
289

290
	switch (get_ia32_am_support(irn)) {
Matthias Braun's avatar
cleanup    
Matthias Braun committed
291
	case ia32_am_none:
Matthias Braun's avatar
Matthias Braun committed
292
		return false;
Matthias Braun's avatar
cleanup    
Matthias Braun committed
293
294
295

	case ia32_am_unary:
		if (i != n_ia32_unary_op)
Matthias Braun's avatar
Matthias Braun committed
296
			return false;
Matthias Braun's avatar
cleanup    
Matthias Braun committed
297
		break;
298

Matthias Braun's avatar
cleanup    
Matthias Braun committed
299
300
301
302
	case ia32_am_binary:
		switch (i) {
		case n_ia32_binary_left: {
			if (!is_ia32_commutative(irn))
Matthias Braun's avatar
Matthias Braun committed
303
				return false;
304

Matthias Braun's avatar
cleanup    
Matthias Braun committed
305
306
307
			/* 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);
308
			if (req->limited != NULL)
Matthias Braun's avatar
Matthias Braun committed
309
				return false;
Matthias Braun's avatar
cleanup    
Matthias Braun committed
310
311
			break;
		}
312

Matthias Braun's avatar
cleanup    
Matthias Braun committed
313
		case n_ia32_binary_right:
314
			break;
315
316

		default:
Matthias Braun's avatar
Matthias Braun committed
317
			return false;
Matthias Braun's avatar
cleanup    
Matthias Braun committed
318
319
320
321
		}
		break;

	default:
322
		panic("unknown AM type");
323
	}
324
325
326
327

	/* 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
328
		return false;
329

330
331
332
333
334
335
336
337
338
339
340
341
342
	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
343
	return true;
344
345
}

346
static void ia32_perform_memory_operand(ir_node *irn, unsigned int i)
347
{
348
349
	if (!ia32_possible_memory_operand(irn, i))
		return;
350

351
352
353
354
	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);
355
	ir_mode *dest_op_mode = get_ia32_ls_mode(irn);
Matthias Braun's avatar
Matthias Braun committed
356
	if (get_mode_size_bits(load_mode) <= get_mode_size_bits(dest_op_mode))
357
		set_ia32_ls_mode(irn, load_mode);
358
	set_ia32_op_type(irn, ia32_AddrModeS);
359
	set_ia32_frame_use(irn, IA32_FRAME_USE_AUTO);
360

361
362
	if (i == n_ia32_binary_left                    &&
	    get_ia32_am_support(irn) == ia32_am_binary &&
363
364
	    /* immediates are only allowed on the right side */
	    !is_ia32_Immediate(get_irn_n(irn, n_ia32_binary_right))) {
365
		ia32_swap_left_right(irn);
366
		i = n_ia32_binary_right;
367
	}
368

369
370
	assert(is_NoMem(get_irn_n(irn, n_ia32_mem)));

371
372
	set_irn_n(irn, n_ia32_base, get_irg_frame(get_irn_irg(irn)));
	set_irn_n(irn, n_ia32_mem,  spill);
373
	set_irn_n(irn, i,           ia32_get_admissible_noreg(irn, i));
374
	set_ia32_is_reload(irn);
375
376
377
378
379
380
381

	/* 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);
382
383
}

Matthias Braun's avatar
Matthias Braun committed
384
static bool gprof;
Michael Beck's avatar
Michael Beck committed
385

386
387
388
389
390
391
392
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);

393
394
395
	ir_mode *ls_mode = get_ia32_ls_mode(node);
	bool     is_8bit = get_mode_size_bits(ls_mode) == 8;

396
	construct_binop_func *func;
397
	switch (get_ia32_irn_opcode(node)) {
398
399
400
401
402
	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;
403
	default: panic("cannot turn back DestAM for %+F", node);
404
405
	}

406
407
408
409
410
411
	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);
412
413
414
	ia32_copy_am_attrs(load, node);
	if (is_ia32_is_reload(node))
		set_ia32_is_reload(load);
415
	sched_add_before(node, load);
416
417
	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);
418
419
420
421
422
423

	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);
424
	set_ia32_ls_mode(new_node, ls_mode);
425
426
	set_irn_mode(new_node, mode_T);

427
	arch_set_irn_register_out(new_node, pn_ia32_flags, &ia32_registers[REG_EFLAGS]);
428

429
	ir_node *const res_proj = be_new_Proj(new_node, pn_ia32_res);
430
431
	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);
432
433
	ia32_copy_am_attrs(store, node);
	set_ia32_op_type(store, ia32_AddrModeD);
434
	sched_add_after(node, store);
435

436
437
438
	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);
439

440
441
	sched_replace(node, new_node);
	exchange(node, new_node);
442
443
444
	return new_node;
}

445
ir_node *ia32_turn_back_am(ir_node *node)
446
{
Matthias Braun's avatar
Matthias Braun committed
447
448
449
450
451
452
	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);
453
	ir_node  *load     = new_bd_ia32_Load(dbgi, block, base, idx, mem);
454
	ir_node  *load_res = be_new_Proj(load, pn_ia32_Load_res);
455
456

	ia32_copy_am_attrs(load, node);
457
458
	if (is_ia32_is_reload(node))
		set_ia32_is_reload(load);
459
	set_irn_n(node, n_ia32_mem, get_irg_no_mem(irg));
460

461
	switch (get_ia32_am_support(node)) {
Matthias Braun's avatar
cleanup    
Matthias Braun committed
462
463
464
	case ia32_am_unary:
		set_irn_n(node, n_ia32_unary_op, load_res);
		break;
465

Matthias Braun's avatar
cleanup    
Matthias Braun committed
466
467
468
469
470
471
472
	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;
473

Matthias Braun's avatar
cleanup    
Matthias Braun committed
474
	default:
475
		panic("unknown AM type");
476
	}
Matthias Braun's avatar
Matthias Braun committed
477
	ir_node *noreg = ia32_new_NoReg_gp(irg);
478
	set_irn_n(node, n_ia32_base,  noreg);
479
	set_irn_n(node, n_ia32_index, noreg);
480
481
	ia32_attr_t *const attr = get_ia32_attr(node);
	attr->am_imm = (x86_imm32_t) { .kind = X86_IMM_VALUE, .offset = 0 };
482
	attr->frame_use = IA32_FRAME_USE_NONE;
483
	set_ia32_am_scale(node, 0);
484
485

	/* rewire mem-proj */
Michael Beck's avatar
Michael Beck committed
486
	if (get_irn_mode(node) == mode_T) {
487
488
		foreach_out_edge(node, edge) {
			ir_node *out = get_edge_src_irn(edge);
489
490
			if (get_irn_mode(out) == mode_M) {
				set_Proj_pred(out, load);
491
				set_Proj_num(out, pn_ia32_Load_M);
492
				break;
493
494
495
496
497
			}
		}
	}

	set_ia32_op_type(node, ia32_Normal);
Michael Beck's avatar
Michael Beck committed
498
	if (sched_is_scheduled(node))
499
		sched_add_before(node, load);
500
501

	return load_res;
502
503
504
505
}

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

Matthias Braun's avatar
Matthias Braun committed
509
	ia32_op_type_t type = get_ia32_op_type(node);
510
	switch (type) {
Matthias Braun's avatar
cleanup    
Matthias Braun committed
511
512
513
	case ia32_AddrModeS:
		ia32_turn_back_am(node);
		break;
514

Matthias Braun's avatar
cleanup    
Matthias Braun committed
515
	case ia32_AddrModeD:
516
517
		node = ia32_turn_back_dest_am(node);
		break;
518

Matthias Braun's avatar
Matthias Braun committed
519
520
521
	default:
		assert(type == ia32_Normal);
		break;
522
523
	}

Matthias Braun's avatar
Matthias Braun committed
524
	ir_node *copy = exact_copy(node);
525
	set_nodes_block(copy, block);
526
527
528
529
	sched_add_after(after, copy);
	return copy;
}

530
531
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
532
                   Cmp_and_Sub_operand_numbers_equal)
533

534
static bool ia32_try_replace_flags(ir_node *consumers, ir_node *flags, ir_node *available)
535
{
536
537
	if (!is_ia32_Sub(flags) && !is_ia32_Cmp(flags))
		return false;
538
539
540
541
542
543
	unsigned pn;
	if (is_ia32_Sub(available)) {
		pn = pn_ia32_Sub_flags;
	} else if (is_ia32_Cmp(available)) {
		pn = pn_ia32_Cmp_eflags;
	} else {
544
		return false;
545
	}
546
547
548
549
550
551
552
553
554
555
556
	/* 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. */
557
	arch_set_irn_register_out(available, pn, &ia32_registers[REG_EFLAGS]);
558
	ir_node *const proj      = get_irn_mode(available) == mode_T ? be_get_or_make_Proj_for_pn(available, pn) : available;
559
560
561
562
563
564
	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) {
565
			if (get_irn_mode(in) == flag_mode)
566
				set_irn_n(c, i, proj);
567
568
		}
	}
569
	return true;
570
571
}

572
static void remat_simplifier(ir_node *node, void *env)
573
574
575
{
	(void)env;

576
577
	/* A Sub with unused result is a Cmp. */
	if (is_ia32_Sub(node) && get_irn_mode(node) == mode_T) {
578
		ir_node *projs[] = { [pn_ia32_Sub_M] = NULL };
579
		foreach_out_edge(node, out) {
580
581
582
583
584
			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;
585
		}
586

587
588
589
590
591
592
593
594
595
596
		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;
597
				}
598
			}
599
		}
600

601
602
603
604
605
606
607
608
609
610
611
		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);
612
613
614
615
616
617
618
619
620
621
622
623
624
		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);
625
626
			}

627
628
629
			cmp = be_new_Proj(cmp, pn_ia32_Cmp_eflags);
		} else {
			assert(get_ia32_op_type(node) == ia32_Normal);
630
631
		}

632
633
634
635
636
637
638
639
		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);
640
	}
641
642
643
644
}

static void simplify_remat_nodes(ir_graph *irg)
{
645
646
	irg_walk_graph(irg, remat_simplifier, NULL, NULL);
	remove_End_Bads_and_doublets(get_irg_end(irg));
647
648
}

649
static ir_node *ia32_new_spill(ir_node *value, ir_node *after)
650
{
651
652
653
654
655
656
	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
657

658
	ir_node *res;
659
	ir_node *store;
Christian Würdig's avatar
Christian Würdig committed
660
	if (mode_is_float(mode)) {
661
		if (ia32_cg_config.use_sse2) {
662
			store = new_bd_ia32_xStore(NULL, block, frame, noreg, nomem, value);
663
			res   = be_new_Proj(store, pn_ia32_xStore_M);
664
		} else {
665
			store = new_bd_ia32_fst(NULL, block, frame, noreg, nomem, value, mode);
666
			res   = be_new_Proj(store, pn_ia32_fst_M);
667
		}
668
	} else if (get_mode_size_bits(mode) == 128) {
669
		/* Spill 128 bit SSE registers */
670
		store = new_bd_ia32_xxStore(NULL, block, frame, noreg, nomem, value);
671
		res   = be_new_Proj(store, pn_ia32_xxStore_M);
672
	} else {
673
		store = get_mode_size_bits(mode) == 8
674
675
			? new_bd_ia32_Store_8bit(NULL, block, frame, noreg, nomem, value)
			: new_bd_ia32_Store     (NULL, block, frame, noreg, nomem, value);
676
		res   = be_new_Proj(store, pn_ia32_Store_M);
Christian Würdig's avatar
Christian Würdig committed
677
	}
678
679
	set_ia32_op_type(store, ia32_AddrModeD);
	set_ia32_ls_mode(store, mode);
680
	set_ia32_frame_use(store, IA32_FRAME_USE_AUTO);
681
	set_ia32_is_spill(store);
682
	sched_add_after(after, store);
Christian Würdig's avatar
Christian Würdig committed
683

684
685
686
687
688
689
690
	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);
691
	ir_mode  *spillmode = get_spill_mode(value);
692
693
694
	ir_node  *noreg     = ia32_new_NoReg_gp(irg);
	ir_node  *frame     = get_irg_frame(irg);

695
	ir_node *load;
696
	if (mode_is_float(spillmode)) {
697
		if (ia32_cg_config.use_sse2) {
698
			load = new_bd_ia32_xLoad(NULL, block, frame, noreg, spill, spillmode);
699
		} else {
700
			load = new_bd_ia32_fld(NULL, block, frame, noreg, spill, spillmode);
701
		}
702
703
704
705
706
707
708
709
	} 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);
710
	set_ia32_frame_use(load, IA32_FRAME_USE_AUTO);
711
712
713
714
	set_ia32_is_reload(load);
	arch_add_irn_flags(load, arch_irn_flag_reload);
	sched_add_before(before, load);

715
	return be_new_Proj(load, pn_ia32_res);
Christian Würdig's avatar
Christian Würdig committed
716
717
}

Matthias Braun's avatar
Matthias Braun committed
718
719
static ir_node *create_push(ir_node *node, ir_node *schedpoint, ir_node *sp,
                            ir_node *mem, ir_entity *ent, ir_mode *mode)
720
{
721
722
723
724
725
	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);
726

727
728
729
730
	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) {
731
		.kind   = X86_IMM_FRAMEENT,
732
733
734
		.entity = ent,
	};
	set_ia32_frame_use(push, IA32_FRAME_USE_AUTO);
735
	set_ia32_op_type(push, ia32_AddrModeS);
736
	set_ia32_is_spill(push);
737
738
739
740
741

	sched_add_before(schedpoint, push);
	return push;
}

Matthias Braun's avatar
Matthias Braun committed
742
743
static ir_node *create_pop(ir_node *node, ir_node *schedpoint, ir_node *sp,
                           ir_entity *ent, ir_mode *mode)
744
{
745
	dbg_info *dbgi  = get_irn_dbg_info(node);
746
747
748
749
	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
750
751
	ir_node  *pop   = new_bd_ia32_PopMem(dbgi, block, frame, noreg,
	                                     get_irg_no_mem(irg), sp);
752
753
	ia32_attr_t *const attr = get_ia32_attr(pop);
	attr->am_imm = (x86_imm32_t) {
754
		.kind   = X86_IMM_FRAMEENT,
755
756
757
		.entity = ent,
	};
	set_ia32_frame_use(pop, IA32_FRAME_USE_AUTO);
758
	set_ia32_op_type(pop, ia32_AddrModeD);
Matthias Braun's avatar
Matthias Braun committed
759
	set_ia32_ls_mode(pop, mode);
760
	set_ia32_is_reload(pop);
761
762
763
764
	sched_add_before(schedpoint, pop);
	return pop;
}

765
static ir_node *create_spproj(ir_node *const pred, unsigned const pos)
766
{
767
	return be_new_Proj_reg(pred, pos, &ia32_registers[REG_ESP]);
768
769
}

770
/**
771
 * Transform MemPerm, currently we do this the ugly way and produce
772
773
774
 * push/pop into/from memory cascades. This is possible without using
 * any registers.
 */
775
static void transform_MemPerm(ir_node *node)
776
{
777
	ir_graph *irg   = get_irn_irg(node);
Christoph Mallon's avatar
Christoph Mallon committed
778
	ir_node  *sp    = be_get_Start_proj(irg, &ia32_registers[REG_ESP]);
779
780
	int       arity = be_get_MemPerm_entity_arity(node);
	ir_node **pops  = ALLOCAN(ir_node*, arity);
781

782
	/* create Pushs */
Matthias Braun's avatar
Matthias Braun committed
783
	for (int i = 0; i < arity; ++i) {
784
785
		ir_entity *inent = be_get_MemPerm_in_entity(node, i);
		ir_entity *outent = be_get_MemPerm_out_entity(node, i);
786
787
788
789
		assert(inent->kind == IR_ENTITY_SPILLSLOT);
		assert(outent->kind == IR_ENTITY_SPILLSLOT);
		unsigned entsize = inent->attr.spillslot.size;
		unsigned entsize2 = outent->attr.spillslot.size;
790
		ir_node *mem = get_irn_n(node, i);
791

792
		/* work around cases where entities have different sizes */
793
		if (entsize2 < entsize)
794
			entsize = entsize2;
795
796
797
798
799
800
801
802
803
804
805

		int offset = 0;
		do {
			ir_mode *mode;
			if (entsize%2 == 1) {
				mode = mode_Bu;
			} else if (entsize % 4 == 2) {
				mode = mode_Hu;
			} else {
				assert(entsize%4 == 0);
				mode = ia32_mode_gp;
Matthias Braun's avatar
Matthias Braun committed
806
			}
807

808
			ir_node *push = create_push(node, node, sp, mem, inent, mode);
809
			sp = create_spproj(push, pn_ia32_Push_stack);
810
811
812
813
814
815
			add_ia32_am_offs_int(push, offset);

			unsigned size = get_mode_size_bytes(mode);
			offset  += size;
			entsize -= size;
		} while(entsize > 0);
Matthias Braun's avatar
Matthias Braun committed
816
		set_irn_n(node, i, new_r_Bad(irg, mode_X));
817
818
	}

819
	/* create pops */
Matthias Braun's avatar
Matthias Braun committed
820
	for (int i = arity; i-- > 0; ) {
821
822
		ir_entity *inent = be_get_MemPerm_in_entity(node, i);
		ir_entity *outent = be_get_MemPerm_out_entity(node, i);
823
824
825
826
		assert(inent->kind == IR_ENTITY_SPILLSLOT);
		assert(outent->kind == IR_ENTITY_SPILLSLOT);
		unsigned entsize = outent->attr.spillslot.size;
		unsigned entsize2 = inent->attr.spillslot.size;
827

828
		/* work around cases where entities have different sizes */
829
		if (entsize2 < entsize)
830
			entsize = entsize2;
831

832
833
834
835
836
837
838
839
840
841
842
843
844
		int      offset = entsize;
		ir_node *pop;
		do {
			ir_mode *mode;
			if (entsize%2 == 1) {
				mode = mode_Bu;
			} else if (entsize%4 == 2) {
				mode = mode_Hu;
			} else {
				assert(entsize%4 == 0);
				mode = ia32_mode_gp;
			}
			pop = create_pop(node, node, sp, outent, mode);
845
			sp  = create_spproj(pop, pn_ia32_PopMem_stack);
846
847
848
849
850
851

			unsigned size = get_mode_size_bytes(mode);
			offset  -= size;
			entsize -= size;
			add_ia32_am_offs_int(pop, offset);
		} while(entsize > 0);
852
853
854
		pops[i] = pop;
	}

855
	ir_node *const keep = be_new_Keep_one(sp);
856
	sched_replace(node, keep);
857

858
	/* exchange memprojs */
859
	foreach_out_edge_safe(node, edge) {
860
		ir_node *proj = get_edge_src_irn(edge);
861
		unsigned p = get_Proj_num(proj);
862

863
		assert(p < (unsigned)arity);
864
865

		set_Proj_pred(proj, pops[p]);
866
		set_Proj_num(proj, pn_ia32_PopMem_M);
867
868
	}

869
	/* remove memperm */
Matthias Braun's avatar
Matthias Braun committed
870
	kill_node(node);
871
872
}

873
874
875
/**
 * Block-Walker: Calls the transform functions Spill and Reload.
 */
876
877
static void ia32_after_ra_walker(ir_node *block, void *env)
{