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

Christian Würdig's avatar
Christian Würdig committed
6
/**
Christian Würdig's avatar
Christian Würdig committed
7
8
9
 * @file
 * @brief       This is the main ia32 firm backend driver.
 * @author      Christian Wuerdig
Christian Würdig's avatar
Christian Würdig committed
10
 */
11
#include "be_t.h"
Matthias Braun's avatar
Matthias Braun committed
12
13
14
15
#include "bearch_ia32_t.h"
#include "beflags.h"
#include "begnuas.h"
#include "bemodule.h"
16
#include "bera.h"
Matthias Braun's avatar
Matthias Braun committed
17
18
19
20
#include "besched.h"
#include "bespillslots.h"
#include "bestack.h"
#include "beutil.h"
21
22
23
24
25
26
27
28
29
#include "gen_ia32_regalloc_if.h"
#include "ia32_architecture.h"
#include "ia32_emitter.h"
#include "ia32_finish.h"
#include "ia32_fpu.h"
#include "ia32_new_nodes.h"
#include "ia32_optimize.h"
#include "ia32_transform.h"
#include "ia32_x87.h"
30
#include "ident_t.h"
Matthias Braun's avatar
Matthias Braun committed
31
#include "instrument.h"
Christian Würdig's avatar
Christian Würdig committed
32
#include "irgmod.h"
Christian Würdig's avatar
Christian Würdig committed
33
#include "irgopt.h"
Matthias Braun's avatar
Matthias Braun committed
34
#include "irgwalk.h"
35
#include "iropt_t.h"
Matthias Braun's avatar
Matthias Braun committed
36
37
#include "irtools.h"
#include "lc_opts_enum.h"
38
#include "lower_alloc.h"
Matthias Braun's avatar
Matthias Braun committed
39
#include "lower_builtins.h"
40
#include "lower_calls.h"
41
#include "lower_mode_b.h"
42
#include "lower_softfloat.h"
43
#include "lowering.h"
Matthias Braun's avatar
Matthias Braun committed
44
#include "panic.h"
45

46
47
pmap *ia32_tv_ent; /**< A map of entities that store const tarvals */

48
ir_mode *ia32_mode_fpcw;
49
ir_mode *ia32_mode_flags;
50
51
ir_mode *ia32_mode_E;
ir_type *ia32_type_E;
52
53
54
ir_mode *ia32_mode_gp;
ir_mode *ia32_mode_float64;
ir_mode *ia32_mode_float32;
55

56
/** The current omit-fp state */
Matthias Braun's avatar
Matthias Braun committed
57
58
59
60
61
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;
62
static bool       precise_x87_spills;
63
static bool       return_small_struct_in_regs;
64

65
typedef ir_node *(*create_const_node_func) (dbg_info *dbgi, ir_node *block);
66

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

Matthias Braun's avatar
Matthias Braun committed
77
78
	ir_node *block = get_irg_start_block(irg);
	ir_node *res   = func(NULL, block);
79
	arch_set_irn_register(res, reg);
80
81
82
83
	*place = res;
	return res;
}

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

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

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

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

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

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

129
130
static ir_entity *ia32_get_frame_entity(const ir_node *irn)
{
Christian Würdig's avatar
Christian Würdig committed
131
	return is_ia32_irn(irn) ? get_ia32_frame_ent(irn) : NULL;
132
133
}

134
135
static void ia32_set_frame_entity(ir_node *node, ir_entity *entity,
                                  const ir_type *type)
136
{
137
138
139
140
	set_ia32_frame_ent(node, entity);

	/* set ls_mode based on entity unless we explicitely requested
	 * a certain mode */
141
	if (get_ia32_frame_use(node) != IA32_FRAME_USE_AUTO || is_ia32_Conv_I2I(node))
142
143
144
145
146
147
148
149
		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);
150
151
}

152
static void ia32_set_frame_offset(ir_node *irn, int bias)
153
154
155
{
	if (get_ia32_frame_ent(irn) == NULL)
		return;
156

157
	if (is_ia32_Pop(irn) || is_ia32_PopMem(irn)) {
158
159
160
		ir_graph          *irg     = get_irn_irg(irn);
		be_stack_layout_t *layout  = be_get_irg_stack_layout(irg);
		if (layout->sp_relative) {
161
162
163
			/* Pop nodes modify the stack pointer before calculating the
			 * destination address, so fix this here
			 */
Matthias Braun's avatar
Matthias Braun committed
164
165
			ir_mode *mode = get_ia32_ls_mode(irn);
			bias -= get_mode_size_bytes(mode);
166
		}
167
	}
168
	add_ia32_am_offs_int(irn, bias);
169
170
}

171
int ia32_get_sp_bias(const ir_node *node)
172
{
173
174
175
	if (is_ia32_Call(node))
		return -(int)get_ia32_call_attr_const(node)->pop;

Matthias Braun's avatar
Matthias Braun committed
176
177
178
179
	if (is_ia32_Push(node)) {
		ir_mode *ls_mode = get_ia32_ls_mode(node);
		return get_mode_size_bytes(ls_mode);
	}
180

Matthias Braun's avatar
Matthias Braun committed
181
182
183
184
	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);
	}
185

Matthias Braun's avatar
Matthias Braun committed
186
	if (is_ia32_Leave(node) || is_ia32_CopyEbpEsp(node))
187
188
		return SP_BIAS_RESET;

189
190
191
	return 0;
}

Sebastian Hack's avatar
Sebastian Hack committed
192
/**
193
 * Build the between type and entities if not already built.
Sebastian Hack's avatar
Sebastian Hack committed
194
 */
195
196
static void ia32_build_between_type(void)
{
197
	if (between_type == NULL) {
198
199
		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
200

201
202
203
		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
204

205
206
207
		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));
208
		set_type_state(between_type, layout_fixed);
209

210
211
		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);
212
213
214
215

		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
216
	}
217
218
219
220
221
}

/**
 * Return the stack entity that contains the return address.
 */
222
ir_entity *ia32_get_return_address_entity(ir_graph *irg)
223
{
224
	const be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
225
	ia32_build_between_type();
226
	return layout->sp_relative ? omit_fp_ret_addr_ent : ret_addr_ent;
227
228
229
230
231
}

/**
 * Return the stack entity that contains the frame address.
 */
232
ir_entity *ia32_get_frame_address_entity(ir_graph *irg)
233
{
234
	const be_stack_layout_t *layout = be_get_irg_stack_layout(irg);
235
	ia32_build_between_type();
236
	return layout->sp_relative ? NULL : old_bp_ent;
Sebastian Hack's avatar
Sebastian Hack committed
237
238
}

239
240
241
242
243
244
245
/**
 * Get the estimated cycle count for @p irn.
 *
 * @param irn  The node.
 *
 * @return     The estimated cycle count for this operation
 */
246
static unsigned ia32_get_op_estimated_cost(ir_node const *const irn)
247
{
248
249
250
	if (!is_ia32_irn(irn))
		return 1;

251
	if (is_ia32_CopyB_i(irn)) {
252
253
		unsigned const size = get_ia32_copyb_size(irn);
		return 20 + size * 4 / 3;
Christian Würdig's avatar
Christian Würdig committed
254
	}
255
256
257

	unsigned cost = get_ia32_latency(irn);

Christian Würdig's avatar
Christian Würdig committed
258
	/* in case of address mode operations add additional cycles */
259
	if (get_ia32_op_type(irn) != ia32_Normal) {
260
		if (get_ia32_frame_use(irn) != IA32_FRAME_USE_NONE || (
261
262
		      is_ia32_NoReg_GP(get_irn_n(irn, n_ia32_base)) &&
		      is_ia32_NoReg_GP(get_irn_n(irn, n_ia32_index))
263
		    )) {
264
			/* Stack access, assume it is cached. */
265
266
			cost += 5;
		} else {
267
			/* Access probably elsewhere. */
268
269
			cost += 20;
		}
Christian Würdig's avatar
Christian Würdig committed
270
271
272
	}

	return cost;
273
274
}

275
static ir_mode *get_spill_mode(const ir_node *value)
276
{
277
278
279
280
281
282
283
	/* 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);

	ir_mode *mode = get_irn_mode(value);
	return mode_is_float(mode) ? ia32_mode_E : ia32_mode_gp;
284
285
}

286
/**
Christoph Mallon's avatar
Christoph Mallon committed
287
 * Check if irn can load its operand at position i from memory (source addressmode).
288
289
 * @param irn    The irn to be checked
 * @param i      The operands position
290
 * @return whether operand can be loaded
291
 */
292
static bool ia32_possible_memory_operand(const ir_node *irn, unsigned int i)
293
{
294
295
	if (!is_ia32_irn(irn)                    || /* must be an ia32 irn */
	    get_ia32_op_type(irn) != ia32_Normal || /* must not already be a addressmode irn */
296
	    get_ia32_frame_use(irn) != IA32_FRAME_USE_NONE) /* must not already use frame */
Matthias Braun's avatar
Matthias Braun committed
297
		return false;
298

299
	switch (get_ia32_am_support(irn)) {
Matthias Braun's avatar
cleanup    
Matthias Braun committed
300
	case ia32_am_none:
Matthias Braun's avatar
Matthias Braun committed
301
		return false;
Matthias Braun's avatar
cleanup    
Matthias Braun committed
302
303
304

	case ia32_am_unary:
		if (i != n_ia32_unary_op)
Matthias Braun's avatar
Matthias Braun committed
305
			return false;
Matthias Braun's avatar
cleanup    
Matthias Braun committed
306
		break;
307

Matthias Braun's avatar
cleanup    
Matthias Braun committed
308
309
310
311
	case ia32_am_binary:
		switch (i) {
		case n_ia32_binary_left: {
			if (!is_ia32_commutative(irn))
Matthias Braun's avatar
Matthias Braun committed
312
				return false;
313

Matthias Braun's avatar
cleanup    
Matthias Braun committed
314
315
316
317
			/* 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);
			if (arch_register_req_is(req, limited))
Matthias Braun's avatar
Matthias Braun committed
318
				return false;
Matthias Braun's avatar
cleanup    
Matthias Braun committed
319
320
			break;
		}
321

Matthias Braun's avatar
cleanup    
Matthias Braun committed
322
		case n_ia32_binary_right:
323
			break;
324
325

		default:
Matthias Braun's avatar
Matthias Braun committed
326
			return false;
Matthias Braun's avatar
cleanup    
Matthias Braun committed
327
328
329
330
		}
		break;

	default:
331
		panic("unknown AM type");
332
	}
333
334
335
336

	/* 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
337
		return false;
338

339
340
341
342
343
344
345
346
347
348
349
350
351
	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
352
	return true;
353
354
}

355
static void ia32_perform_memory_operand(ir_node *irn, unsigned int i)
356
{
357
358
	if (!ia32_possible_memory_operand(irn, i))
		return;
359

360
361
362
363
	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);
364
	ir_mode *dest_op_mode = get_ia32_ls_mode(irn);
Matthias Braun's avatar
Matthias Braun committed
365
	if (get_mode_size_bits(load_mode) <= get_mode_size_bits(dest_op_mode))
366
		set_ia32_ls_mode(irn, load_mode);
367
	set_ia32_op_type(irn, ia32_AddrModeS);
368
	set_ia32_frame_use(irn, IA32_FRAME_USE_AUTO);
369

370
371
	if (i == n_ia32_binary_left                    &&
	    get_ia32_am_support(irn) == ia32_am_binary &&
372
373
	    /* immediates are only allowed on the right side */
	    !is_ia32_Immediate(get_irn_n(irn, n_ia32_binary_right))) {
374
		ia32_swap_left_right(irn);
375
		i = n_ia32_binary_right;
376
	}
377

378
379
	assert(is_NoMem(get_irn_n(irn, n_ia32_mem)));

380
381
	set_irn_n(irn, n_ia32_base, get_irg_frame(get_irn_irg(irn)));
	set_irn_n(irn, n_ia32_mem,  spill);
382
	set_irn_n(irn, i,           ia32_get_admissible_noreg(irn, i));
383
	set_ia32_is_reload(irn);
384
385
386
387
388
389
390

	/* 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);
391
392
}

Matthias Braun's avatar
Matthias Braun committed
393
static bool gprof;
Michael Beck's avatar
Michael Beck committed
394

395
396
397
398
399
400
401
402
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);

	construct_binop_func *func;
403
404
405
406
407
408
409
	switch (get_ia32_irn_opcode(node)) {
	case iro_ia32_AddMem: func = new_bd_ia32_Add; break;
	case iro_ia32_AndMem: func = new_bd_ia32_And; break;
	case iro_ia32_OrMem:  func = new_bd_ia32_Or;  break;
	case iro_ia32_SubMem: func = new_bd_ia32_Sub; break;
	case iro_ia32_XorMem: func = new_bd_ia32_Xor; break;
	default: panic("cannot turn back DestAM for %+F", node);
410
411
	}

412
413
414
415
416
417
	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);
418
419
420
	ia32_copy_am_attrs(load, node);
	if (is_ia32_is_reload(node))
		set_ia32_is_reload(load);
421
422
423
424
425
426
427
428
429
	sched_add_before(node, load);
	ir_node *const load_res = new_rd_Proj(dbgi, load, ia32_mode_gp, pn_ia32_Load_res);
	ir_node *const load_mem = new_rd_Proj(dbgi, load, mode_M, pn_ia32_Load_M);

	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);
430
431
	set_ia32_ls_mode(new_node, get_ia32_ls_mode(node));
	set_irn_mode(new_node, mode_T);
432
	ir_node *const res_proj = new_rd_Proj(dbgi, new_node, ia32_mode_gp, pn_ia32_res);
433

434
	ir_node *const store = new_bd_ia32_Store(dbgi, block, base, idx, load_mem, res_proj);
435
436
	ia32_copy_am_attrs(store, node);
	set_ia32_op_type(store, ia32_AddrModeD);
437
	sched_add_after(node, store);
438

439
440
441
	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);
442

443
444
	sched_replace(node, new_node);
	exchange(node, new_node);
445
446
447
	return new_node;
}

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

	ia32_copy_am_attrs(load, node);
460
461
	if (is_ia32_is_reload(node))
		set_ia32_is_reload(load);
462
	set_irn_n(node, n_ia32_mem, get_irg_no_mem(irg));
463

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

Matthias Braun's avatar
cleanup    
Matthias Braun committed
469
470
471
472
473
474
475
	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;
476

Matthias Braun's avatar
cleanup    
Matthias Braun committed
477
	default:
478
		panic("unknown AM type");
479
	}
Matthias Braun's avatar
Matthias Braun committed
480
	ir_node *noreg = ia32_new_NoReg_gp(irg);
481
	set_irn_n(node, n_ia32_base,  noreg);
482
483
	set_irn_n(node, n_ia32_index, noreg);
	set_ia32_am_offs_int(node, 0);
484
	set_ia32_am_ent(node, NULL);
485
	set_ia32_am_scale(node, 0);
486
	set_ia32_frame_ent(node, NULL);
487
488

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

	set_ia32_op_type(node, ia32_Normal);
Michael Beck's avatar
Michael Beck committed
501
	if (sched_is_scheduled(node))
502
		sched_add_before(node, load);
503
504

	return load_res;
505
506
507
508
}

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

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

Matthias Braun's avatar
cleanup    
Matthias Braun committed
518
	case ia32_AddrModeD:
519
520
		node = ia32_turn_back_dest_am(node);
		break;
521

Matthias Braun's avatar
Matthias Braun committed
522
523
524
	default:
		assert(type == ia32_Normal);
		break;
525
526
	}

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

533
534
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
535
                   Cmp_and_Sub_operand_numbers_equal)
536

537
static bool ia32_try_replace_flags(ir_node *consumers, ir_node *flags, ir_node *available, unsigned pn)
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
{
	if ((is_ia32_Sub(flags) || is_ia32_Cmp(flags)) &&
	    (is_ia32_Sub(available) || is_ia32_Cmp(available))) {

		ir_node *flags_left  = get_irn_n(flags,     n_ia32_Cmp_left);
		ir_node *flags_right = get_irn_n(flags,     n_ia32_Cmp_right);
		ir_node *avail_left  = get_irn_n(available, n_ia32_Cmp_left);
		ir_node *avail_right = get_irn_n(available, n_ia32_Cmp_right);

		/* Assuming CSE would have found the more obvious case */
		if (flags_left == avail_right && avail_left == flags_right) {
			/* We can use available if we reverse the
			 * consumers' condition codes. */
			ir_mode               *flag_mode =  ia32_reg_classes[CLASS_ia32_flags].mode;
			const arch_register_t *flag_reg  = &ia32_reg_classes[CLASS_ia32_flags].regs[0];

			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) {
					if (get_irn_mode(in) == flag_mode) {
						ir_node *proj = new_r_Proj(available, flag_mode, pn);
						arch_set_irn_register(proj, flag_reg);
						set_irn_n(c, i, proj);
					}
				}
			}
			return true;
		}
	}
	return false;
}

572
static void remat_simplifier(ir_node *node, void *env)
573
574
575
576
{
	(void)env;
	const arch_register_t *flags_reg = &(ia32_reg_classes[CLASS_ia32_flags].regs[0]);

577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
	/* A Sub with unused result is a Cmp. */
	if (is_ia32_Sub(node) && get_irn_mode(node) == mode_T) {
		bool      has_res_users  = false;
		ir_node  *res_keep       = NULL;
		ir_node **flag_users     = NEW_ARR_F(ir_node*, 0);
		int      *flag_users_pos = NEW_ARR_F(int, 0);
		ir_node **mem_users      = NEW_ARR_F(ir_node*, 0);
		int      *mem_users_pos  = NEW_ARR_F(int, 0);

		foreach_out_edge(node, out) {
			ir_node *proj = get_edge_src_irn(out);
			ir_mode *proj_mode = get_irn_mode(proj);
			if (proj_mode == ia32_mode_flags) {
				foreach_out_edge(proj, out2) {
					ir_node *user = get_edge_src_irn(out2);
					ARR_APP1(ir_node*, flag_users, user);
					ARR_APP1(int, flag_users_pos, get_edge_src_pos(out2));
				}
			} else if (proj_mode == ia32_mode_gp) {
				foreach_out_edge(proj, out2) {
					ir_node *user = get_edge_src_irn(out2);
					if (!be_is_Keep(user)) {
						has_res_users = true;
					} else {
						assert(res_keep == NULL && "Proj has two be_Keep");
						res_keep = user;
603
					}
604
				}
605
606
607
608
609
			} else if (proj_mode == mode_M) {
				foreach_out_edge(proj, out2) {
					ir_node *user = get_edge_src_irn(out2);
					ARR_APP1(ir_node*, mem_users, user);
					ARR_APP1(int, mem_users_pos, get_edge_src_pos(out2));
610
				}
611
612
			} else {
				panic("unexpected mode for %+F", proj);
613
614
			}
		}
615

616
617
618
619
620
621
622
623
624
625
626
		if (!has_res_users) {
			ir_node *cmp = new_bd_ia32_Cmp(
				get_irn_dbg_info(node),
				get_nodes_block(node),
				get_irn_n(node, n_ia32_Sub_base),
				get_irn_n(node, n_ia32_Sub_index),
				get_irn_n(node, n_ia32_Sub_mem),
				get_irn_n(node, n_ia32_Sub_minuend),
				get_irn_n(node, n_ia32_Sub_subtrahend),
				false);
			arch_set_irn_register(cmp, flags_reg);
627
			ia32_copy_am_attrs(cmp, node);
628
629
630
631

			sched_replace(node, cmp);

			if (get_ia32_op_type(node) == ia32_AddrModeD) {
632
				panic("unexpected DestAM node %+F", node);
633
634
635
636
			}
			if (get_ia32_op_type(node) == ia32_AddrModeS) {
				set_ia32_op_type(cmp, ia32_AddrModeS);
				set_irn_mode(cmp, mode_T);
637

638
639
640
				ir_node *proj_M = new_r_Proj(cmp, mode_M, pn_ia32_Cmp_M);
				for(unsigned i = 0; i < ARR_LEN(mem_users); i++) {
					set_irn_n(mem_users[i], mem_users_pos[i], proj_M);
641
642
				}

643
				cmp = new_r_Proj(cmp, ia32_mode_flags, pn_ia32_Cmp_eflags);
644
			}
645

646
647
			for (unsigned i = 0; i < ARR_LEN(flag_users); i++) {
				set_irn_n(flag_users[i], flag_users_pos[i], cmp);
648
649
			}

650
651
652
653
654
655
656
			if (res_keep) {
				sched_remove(res_keep);
				remove_keep_alive(res_keep);
				kill_node(res_keep);
			}
			kill_node(node);
			node = cmp;
657
658
		}

659
660
661
662
663
		DEL_ARR_F(flag_users);
		DEL_ARR_F(flag_users_pos);
		DEL_ARR_F(mem_users);
		DEL_ARR_F(mem_users_pos);
	}
664
665
666
667
}

static void simplify_remat_nodes(ir_graph *irg)
{
668
669
	irg_walk_graph(irg, remat_simplifier, NULL, NULL);
	remove_End_Bads_and_doublets(get_irg_end(irg));
670
671
}

672
static ir_node *ia32_new_spill(ir_node *value, ir_node *after)
673
{
674
675
676
677
678
679
	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
680

681
	ir_node *res;
682
	ir_node *store;
Christian Würdig's avatar
Christian Würdig committed
683
	if (mode_is_float(mode)) {
684
		if (ia32_cg_config.use_sse2) {
685
			store = new_bd_ia32_xStore(NULL, block, frame, noreg, nomem, value);
686
687
			res   = new_r_Proj(store, mode_M, pn_ia32_xStore_M);
		} else {
688
			store = new_bd_ia32_fst(NULL, block, frame, noreg, nomem, value, mode);
689
			res   = new_r_Proj(store, mode_M, pn_ia32_fst_M);
690
		}
691
	} else if (get_mode_size_bits(mode) == 128) {
692
		/* Spill 128 bit SSE registers */
693
		store = new_bd_ia32_xxStore(NULL, block, frame, noreg, nomem, value);
694
		res   = new_r_Proj(store, mode_M, pn_ia32_xxStore_M);
695
	} else {
696
		store = get_mode_size_bits(mode) == 8
697
698
			? new_bd_ia32_Store_8bit(NULL, block, frame, noreg, nomem, value)
			: new_bd_ia32_Store     (NULL, block, frame, noreg, nomem, value);
699
		res   = new_r_Proj(store, mode_M, pn_ia32_Store_M);
Christian Würdig's avatar
Christian Würdig committed
700
	}
701
702
	set_ia32_op_type(store, ia32_AddrModeD);
	set_ia32_ls_mode(store, mode);
703
	set_ia32_frame_use(store, IA32_FRAME_USE_AUTO);
704
	set_ia32_is_spill(store);
705
	sched_add_after(after, store);
Christian Würdig's avatar
Christian Würdig committed
706

707
708
709
710
711
712
713
714
	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);
	ir_mode  *mode      = get_irn_mode(value);
715
	ir_mode  *spillmode = get_spill_mode(value);
716
717
718
	ir_node  *noreg     = ia32_new_NoReg_gp(irg);
	ir_node  *frame     = get_irg_frame(irg);

719
	ir_node *load;
720
	if (mode_is_float(spillmode)) {
721
		if (ia32_cg_config.use_sse2) {
722
			load = new_bd_ia32_xLoad(NULL, block, frame, noreg, spill, spillmode);
723
		} else {
724
			load = new_bd_ia32_fld(NULL, block, frame, noreg, spill, spillmode);
725
		}
726
727
728
729
730
731
732
733
	} 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);
734
	set_ia32_frame_use(load, IA32_FRAME_USE_AUTO);
735
736
737
738
739
740
	set_ia32_is_reload(load);
	arch_add_irn_flags(load, arch_irn_flag_reload);
	sched_add_before(before, load);

	ir_node *proj = new_r_Proj(load, mode, pn_ia32_res);
	return proj;
Christian Würdig's avatar
Christian Würdig committed
741
742
}

Matthias Braun's avatar
Matthias Braun committed
743
744
static ir_node *create_push(ir_node *node, ir_node *schedpoint, ir_node *sp,
                            ir_node *mem, ir_entity *ent, ir_mode *mode)
745
{
746
747
748
749
750
	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);
751

752
	ir_node *const push = new_bd_ia32_Push(dbgi, block, frame, noreg, mem, noreg, sp, mode);
753
754
755

	set_ia32_frame_ent(push, ent);
	set_ia32_op_type(push, ia32_AddrModeS);
756
	set_ia32_is_spill(push);
757
758
759
760
761

	sched_add_before(schedpoint, push);
	return push;
}

Matthias Braun's avatar
Matthias Braun committed
762
763
static ir_node *create_pop(ir_node *node, ir_node *schedpoint, ir_node *sp,
                           ir_entity *ent, ir_mode *mode)
764
{
765
	dbg_info *dbgi  = get_irn_dbg_info(node);
766
767
768
769
	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
770
771
	ir_node  *pop   = new_bd_ia32_PopMem(dbgi, block, frame, noreg,
	                                     get_irg_no_mem(irg), sp);
772
773
	set_ia32_frame_ent(pop, ent);
	set_ia32_op_type(pop, ia32_AddrModeD);
Matthias Braun's avatar
Matthias Braun committed
774
	set_ia32_ls_mode(pop, mode);
775
	set_ia32_is_reload(pop);
776
777
778
779
	sched_add_before(schedpoint, pop);
	return pop;
}

780
781
static ir_node* create_spproj(ir_node *node, ir_node *pred, int pos)
{
Matthias Braun's avatar
Matthias Braun committed
782
783
784
785
	dbg_info              *dbgi   = get_irn_dbg_info(node);
	ir_mode               *spmode = ia32_mode_gp;
	const arch_register_t *spreg  = &ia32_registers[REG_ESP];
	ir_node               *sp     = new_rd_Proj(dbgi, pred, spmode, pos);
786
	arch_set_irn_register(sp, spreg);
787
788
789
	return sp;
}

790
/**
791
 * Transform MemPerm, currently we do this the ugly way and produce
792
793
794
 * push/pop into/from memory cascades. This is possible without using
 * any registers.
 */
795
static void transform_MemPerm(ir_node *node)
796
{
797
798
799
800
	ir_graph *irg   = get_irn_irg(node);
	ir_node  *sp    = be_get_initial_reg_value(irg, &ia32_registers[REG_ESP]);
	int       arity = be_get_MemPerm_entity_arity(node);
	ir_node **pops  = ALLOCAN(ir_node*, arity);
801

802
	/* create Pushs */
Matthias Braun's avatar
Matthias Braun committed
803
	for (int i = 0; i < arity; ++i) {
804
805
806
		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);
807
808
		unsigned entsize = get_type_size_bytes(enttype);
		unsigned entsize2 = get_type_size_bytes(get_entity_type(outent));
809
		ir_node *mem = get_irn_n(node, i);
810

811
		/* work around cases where entities have different sizes */
812
		if (entsize2 < entsize)
813
			entsize = entsize2;
814
815
816
817
818
819
820
821
822
823
824

		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
825
			}
826

827
828
829
830
831
832
833
834
			ir_node *push = create_push(node, node, sp, mem, inent, mode);
			sp = create_spproj(node, push, pn_ia32_Push_stack);
			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
835
		set_irn_n(node, i, new_r_Bad(irg, mode_X));
836
837
	}

838
	/* create pops */
Matthias Braun's avatar
Matthias Braun committed
839
	for (int i = arity; i-- > 0; ) {
840
841
842
		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(outent);
843
844
		unsigned entsize = get_type_size_bytes(enttype);
		unsigned entsize2 = get_type_size_bytes(get_entity_type(inent));
845

846
		/* work around cases where entities have different sizes */
847
		if (entsize2 < entsize)
848
			entsize = entsize2;
849

850
851
852
853
854
855
856
857
858
859
860
861
862
		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);
863
			sp  = create_spproj(node, pop, pn_ia32_PopMem_stack);
864
865
866
867
868
869

			unsigned size = get_mode_size_bytes(mode);
			offset  -= size;
			entsize -= size;
			add_ia32_am_offs_int(pop, offset);
		} while(entsize > 0);
870
871
872
		pops[i] = pop;
	}

873
	ir_node *const keep = be_new_Keep_one(sp);
874
	sched_replace(node, keep);
875

876
	/* exchange memprojs */
877
	foreach_out_edge_safe(node, edge) {
878
		ir_node *proj = get_edge_src_irn(edge);
879
		unsigned p = get_Proj_num(proj);
880

881
		assert(p < (unsigned)arity);
882
883

		set_Proj_pred(proj, pops[p]);
884
		set_Proj_num(proj, pn_ia32_PopMem_M);
885
886
	}

887
	/* remove memperm */
Matthias Braun's avatar
Matthias Braun committed
888
	kill_node(node);
889
890
}

891
892
893
/**
 * Block-Walker: Calls the transform functions Spill and Reload.
 */
894
895
static void ia32_after_ra_walker(ir_node *block, void *env)
{
Matthias Braun's avatar
Matthias Braun committed
896
	(void)env;
897
898

	/* beware: the schedule is changed here */
899
	sched_foreach_reverse_safe(block, node) {
900
		if (be_is_MemPerm(node)) {
901
			transform_MemPerm(node);
902
		}
Christian Würdig's avatar
Christian Würdig committed
903
904
905
	}
}

906
907
908
909
910
/**
 * Collects nodes that need frame entities assigned.
 */
static void ia32_collect_frame_entity_nodes(ir_node *node, void *data)
{
911
	be_fec_env_t *env = (be_fec_env_t*)data;
912
913
914
915
916
917
	/* Disable coalescing for "returns twice" calls: In case of setjmp/longjmp
	 * our control flow graph isn't completely correct: There are no backedges
	 * from longjmp to the setjmp => coalescing would produce wrong results. */
	if (is_ia32_Call(node)) {
		const ia32_call_attr_t    *attrs = get_ia32_call_attr_const(node);
		const ir_type             *type  = attrs->call_tp;
918
919
<