ia32_transform.c 183 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
 * @file
8
9
 * @brief       This file implements the IR transformation from firm into
 *              ia32-Firm.
Christian Würdig's avatar
Christian Würdig committed
10
 * @author      Christian Wuerdig, Matthias Braun
Christian Würdig's avatar
Christian Würdig committed
11
 */
12
#include <stdbool.h>
Christian Würdig's avatar
Christian Würdig committed
13

Christian Würdig's avatar
Christian Würdig committed
14
#include "irargs_t.h"
15
16
17
#include "irnode_t.h"
#include "irgraph_t.h"
#include "irmode_t.h"
Christian Würdig's avatar
Christian Würdig committed
18
19
20
#include "iropt_t.h"
#include "irop_t.h"
#include "irprog_t.h"
Christian Würdig's avatar
Christian Würdig committed
21
#include "iredges_t.h"
22
#include "irouts.h"
23
24
#include "irgmod.h"
#include "ircons.h"
25
#include "irgwalk.h"
26
#include "irprintf.h"
27
#include "debug.h"
28
#include "irdom.h"
29
#include "iropt.h"
Matthias Braun's avatar
Matthias Braun committed
30
#include "panic.h"
31
#include "array.h"
32
#include "heights.h"
33

34
#include "bediagnostic.h"
35
36
37
#include "benode.h"
#include "betranshlp.h"
#include "be_t.h"
38
#include "beutil.h"
Christian Würdig's avatar
Christian Würdig committed
39

40
#include "bearch_ia32_t.h"
41
42
43
44
45
#include "gen_ia32_regalloc_if.h"
#include "ia32_architecture.h"
#include "ia32_new_nodes.h"
#include "ia32_nodes_attr.h"
#include "ia32_transform.h"
46
#include "util.h"
47
#include "x86_address_mode.h"
48
#include "x86_cconv.h"
49

50
51
52
/* define this to construct SSE constants instead of load them */
#undef CONSTRUCT_SSE_CONST

53
DEBUG_ONLY(static firm_dbg_module_t *dbg;)
54

55
56
57
58
59
60
61
static x86_cconv_t          *current_cconv;
static pmap                 *node_to_stack;
static be_stackorder_t      *stackorder;
static ir_heights_t         *heights;
static x86_immediate_kind_t  lconst_imm_kind;
static ir_entity            *va_start_entity;
static ir_node              *initial_va_list;
62

63
64
65
66
67
68
69
70
71
72
73
74
75
/** we don't have a concept of aliasing registers, so enumerate them
 * manually for the asm nodes. */
const x86_clobber_name_t ia32_additional_clobber_names[] = {
	{ "al", REG_EAX }, { "ah", REG_EAX }, { "ax", REG_EAX },
	{ "bl", REG_EBX }, { "bh", REG_EBX }, { "bx", REG_EBX },
	{ "cl", REG_ECX }, { "ch", REG_ECX }, { "cx", REG_ECX },
	{ "dl", REG_EDX }, { "dh", REG_EDX }, { "dx", REG_EDX },
	{ "si", REG_ESI }, { "di", REG_EDI }, { "sp", REG_ESP },
	{ "bp", REG_EBP }, { NULL, ~0u }
};

#define GP &ia32_reg_classes[CLASS_ia32_gp]
#define FP &ia32_reg_classes[CLASS_ia32_fp]
76
const x86_asm_constraint_list_t ia32_asm_constraints = {
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
	['A'] = { MATCH_REG, GP, 1 << REG_GP_EAX | 1 << REG_GP_EDX },
	['D'] = { MATCH_REG, GP, 1 << REG_GP_EDI },
	['I'] = { MATCH_IMM, GP, 0 },
	['J'] = { MATCH_IMM, GP, 0 },
	['K'] = { MATCH_IMM, GP, 0 },
	['L'] = { MATCH_IMM, GP, 0 },
	['M'] = { MATCH_IMM, GP, 0 },
	['N'] = { MATCH_IMM, GP, 0 },
	['O'] = { MATCH_IMM, GP, 0 },
	['R'] = { MATCH_REG, GP, 0 },
	['S'] = { MATCH_REG, GP, 1 << REG_GP_ESI },
	['Q'] = { MATCH_REG, GP, 1 << REG_GP_EAX | 1 << REG_GP_EBX
		| 1 << REG_GP_ECX | 1 << REG_GP_EDX },
	['V'] = { MATCH_MEM, GP, 0 },
	['X'] = { MATCH_ANY, GP, 0 },
	['a'] = { MATCH_REG, GP, 1 << REG_GP_EAX },
	['b'] = { MATCH_REG, GP, 1 << REG_GP_EBX },
	['c'] = { MATCH_REG, GP, 1 << REG_GP_ECX },
	['d'] = { MATCH_REG, GP, 1 << REG_GP_EDX },
	['f'] = { MATCH_REG, FP, 0 },
	['g'] = { MATCH_ANY, GP, 0 },
	['i'] = { MATCH_IMM, GP, 0 },
	['l'] = { MATCH_REG, GP, 1 << REG_GP_EAX | 1 << REG_GP_EBX
		| 1 << REG_GP_ECX | 1 << REG_GP_EDX | 1 << REG_GP_ESI
		| 1 << REG_GP_EDI | 1 << REG_GP_EBP },
	['m'] = { MATCH_MEM, GP, 0 },
	['n'] = { MATCH_IMM, GP, 0 },
	['o'] = { MATCH_MEM, GP, 0 },
	['p'] = { MATCH_REG, GP, 0 },
	['q'] = { MATCH_REG, GP, 1 << REG_GP_EAX | 1 << REG_GP_EBX
		| 1 << REG_GP_ECX | 1 << REG_GP_EDX },
	['r'] = { MATCH_REG, GP, 0 },
	['t'] = { MATCH_REG, FP, 1 << REG_FP_ST0 },
	['u'] = { MATCH_REG, FP, 1 << REG_FP_ST1 },
	['x'] = { MATCH_REG, &ia32_reg_classes[CLASS_ia32_xmm], 0 },

	// There are more constraints and in general there is alot of internal gcc
114
	// logic at play not everything is documented in the manual. In the gcc
115
116
117
118
119
120
	// source you can look at reload.c, stmt.c and constraints.md. I am not sure
	// how much we want/need to understand and reimplement here.
};
#undef GP
#undef FP

121
122
123
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);
Christian Würdig's avatar
Christian Würdig committed
124

125
126
127
typedef ir_node *construct_binop_flags_func(dbg_info *db, ir_node *block,
        ir_node *base, ir_node *index, ir_node *mem, ir_node *op1, ir_node *op2,
        ir_node *flags);
128

129
130
typedef ir_node *construct_shift_func(dbg_info *db, ir_node *block,
        ir_node *op1, ir_node *op2);
131

132
133
typedef ir_node *construct_binop_dest_func(dbg_info *db, ir_node *block,
        ir_node *base, ir_node *index, ir_node *mem, ir_node *op);
134

135
136
typedef ir_node *construct_unop_dest_func(dbg_info *db, ir_node *block,
        ir_node *base, ir_node *index, ir_node *mem);
137

138
139
140
typedef ir_node *construct_binop_float_func(dbg_info *db, ir_node *block,
        ir_node *base, ir_node *index, ir_node *mem, ir_node *op1, ir_node *op2,
        ir_node *fpcw);
Matthias Braun's avatar
Matthias Braun committed
141

142
typedef ir_node *construct_unop_func(dbg_info *db, ir_node *block, ir_node *op);
143

144
145
static ir_node *create_immediate_or_transform(ir_node *node,
                                              const char immediate_mode);
146

147
static ir_node *create_I2I_Conv(ir_mode *src_mode, dbg_info *dbgi, ir_node *block, ir_node *op, ir_node *orig_node);
148

149
/* its enough to have those once */
150
151
static ir_node *nomem;
static ir_node *noreg_GP;
152

153
154
155
156
157
static bool mode_needs_gp_reg(ir_mode *mode)
{
	return get_mode_arithmetic(mode) == irma_twos_complement;
}

Michael Beck's avatar
Michael Beck committed
158
/** Return non-zero is a node represents the 0 constant. */
Christoph Mallon's avatar
Christoph Mallon committed
159
160
static bool is_Const_0(ir_node *node)
{
161
	return is_Const(node) && is_Const_null(node);
162
163
}

Michael Beck's avatar
Michael Beck committed
164
/** Return non-zero is a node represents the 1 constant. */
Christoph Mallon's avatar
Christoph Mallon committed
165
166
static bool is_Const_1(ir_node *node)
{
167
	return is_Const(node) && is_Const_one(node);
168
169
}

Michael Beck's avatar
Michael Beck committed
170
/** Return non-zero is a node represents the -1 constant. */
Christoph Mallon's avatar
Christoph Mallon committed
171
172
static bool is_Const_Minus_1(ir_node *node)
{
173
	return is_Const(node) && is_Const_all_one(node);
174
175
}

176
177
178
/**
 * returns true if constant can be created with a simple float command
 */
179
static bool is_simple_x87_Const(ir_node *node)
180
{
Matthias Braun's avatar
Matthias Braun committed
181
	ir_tarval *tv = get_Const_tarval(node);
182
	if (tarval_is_null(tv) || tarval_is_one(tv))
183
		return true;
184
185

	/* TODO: match all the other float constants */
186
	return false;
187
188
189
190
191
}

/**
 * returns true if constant can be created with a simple float command
 */
192
static bool is_simple_sse_Const(ir_node *node)
193
{
Matthias Braun's avatar
Matthias Braun committed
194
195
	ir_tarval *tv   = get_Const_tarval(node);
	ir_mode   *mode = get_tarval_mode(tv);
196

197
	if (mode == ia32_mode_float32)
198
		return true;
199

200
201
202
203
204
	if (tarval_is_null(tv)
#ifdef CONSTRUCT_SSE_CONST
	    || tarval_is_one(tv)
#endif
	   )
205
		return true;
206
#ifdef CONSTRUCT_SSE_CONST
207
	if (mode == ia32_mode_float64) {
208
		unsigned const val = be_get_tv_bits32(tv, 0);
209
		if (val == 0)
210
			/* lower 32bit are zero, really a 32bit constant */
211
			return true;
212
	}
213
#endif /* CONSTRUCT_SSE_CONST */
214
	/* TODO: match all the other float constants */
215
	return false;
216
217
}

218
219
ir_node *ia32_get_pic_base(ir_graph *irg)
{
220
221
222
223
224
225
	ir_node **const get_eip = &ia32_get_irg_data(irg)->get_eip;
	if (!*get_eip) {
		ir_node *const block = get_irg_start_block(irg);
		*get_eip = new_bd_ia32_GetEIP(NULL, block);
	}
	return *get_eip;
226
227
}

228
229
230
231
/**
 * return NoREG or pic_base in case of PIC.
 * This is necessary as base address for newly created symbols
 */
232
static ir_node *get_global_base(ir_graph *const irg)
233
{
234
	if (ia32_pic_style != IA32_PIC_NONE)
235
		return ia32_get_pic_base(irg);
236
237
238
	return noreg_GP;
}

239
240
static ir_node *get_initial_sp(ir_graph *irg)
{
Christoph Mallon's avatar
Christoph Mallon committed
241
	return be_get_Start_proj(irg, &ia32_registers[REG_ESP]);
242
243
244
245
}

static ir_node *get_initial_fp(ir_graph *irg)
{
Christoph Mallon's avatar
Christoph Mallon committed
246
	return be_get_Start_proj(irg, &ia32_registers[REG_EBP]);
247
248
249
250
}

static ir_node *get_initial_fpcw(ir_graph *irg)
{
Christoph Mallon's avatar
Christoph Mallon committed
251
	return be_get_Start_proj(irg, &ia32_registers[REG_FPCW]);
252
253
}

254
ir_node *ia32_create_Immediate_full(ir_graph *const irg,
255
                                    x86_imm32_t const *const imm)
256
257
258
{
	ir_node *const start_block = get_irg_start_block(irg);
	ir_node *const immediate
259
		= new_bd_ia32_Immediate(NULL, start_block, imm);
260
261
262
263
	arch_set_irn_register(immediate, &ia32_registers[REG_GP_NOREG]);
	return immediate;
}

264
static void adjust_relocation(x86_imm32_t *imm)
265
{
266
267
268
	if (imm->kind != X86_IMM_ADDR)
		return;
	ir_entity *entity = imm->entity;
269
	if (is_tls_entity(entity)) {
270
271
		imm->kind = entity_has_definition(entity) ? X86_IMM_TLS_LE
		                                          : X86_IMM_TLS_IE;
272
		return;
273
	}
274
275
}

276
static ir_node *try_create_Immediate(const ir_node *node, char const constraint)
277
{
278
279
	x86_imm32_t immediate;
	if (!x86_match_immediate(&immediate, node, constraint))
280
		return NULL;
281
	adjust_relocation(&immediate);
282
283

	ir_graph *const irg = get_irn_irg(node);
284
	return ia32_create_Immediate_full(irg, &immediate);
285
286
287
288
289
290
291
292
293
294
295
}

static ir_type *get_prim_type(const ir_mode *mode)
{
	if (mode == ia32_mode_E) {
		return ia32_type_E;
	} else {
		return get_type_for_mode(mode);
	}
}

296
static ir_entity *create_float_const_entity(ir_tarval *tv, ident *name)
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
{
	ir_mode *mode = get_tarval_mode(tv);
	if (!ia32_cg_config.use_sse2) {
		/* try to reduce the mode to produce smaller sized entities */
		ir_mode *const modes[] = { mode_F, mode_D, NULL };
		for (ir_mode *const *i = modes;; ++i) {
			ir_mode *const to = *i;
			if (!to || to == mode)
				break;
			if (tarval_ieee754_can_conv_lossless(tv, to)) {
				tv   = tarval_convert_to(tv, to);
				mode = to;
				break;
			}
		}
	}

314
	ir_entity *res = pmap_get(ir_entity, ia32_tv_ent, tv);
315
316
317
318
319
320
321
322
323
324
325
326
327
	if (!res) {
		if (!name)
			name = id_unique("C%u");

		ir_type *const tp = get_prim_type(mode);
		res = new_entity(get_glob_type(), name, tp);
		set_entity_ld_ident(res, get_entity_ident(res));
		set_entity_visibility(res, ir_visibility_private);
		add_entity_linkage(res, IR_LINKAGE_CONSTANT);

		ir_initializer_t *const initializer = create_initializer_tarval(tv);
		set_entity_initializer(res, initializer);

328
		pmap_insert(ia32_tv_ent, tv, res);
329
330
331
332
	}
	return res;
}

333
334
335
336
static void set_am_const_entity(ir_node *node, ir_entity *entity)
{
	ia32_attr_t *const attr = get_ia32_attr(node);
	attr->am_imm = (x86_imm32_t) {
337
		.kind   = lconst_imm_kind,
338
339
340
341
		.entity = entity,
	};
}

342
343
344
/**
 * Transforms a Const.
 */
Christoph Mallon's avatar
Christoph Mallon committed
345
346
static ir_node *gen_Const(ir_node *node)
{
347
348
349
350
	ir_node   *block = be_transform_nodes_block(node);
	dbg_info  *dbgi  = get_irn_dbg_info(node);
	ir_mode   *mode  = get_irn_mode(node);
	ir_tarval *tv    = get_Const_tarval(node);
351
352

	if (mode_is_float(mode)) {
353
354
355
		ir_graph *const irg = get_irn_irg(node);
		ir_node        *res = NULL;
		ir_node        *load;
356

357
		if (ia32_cg_config.use_sse2) {
358
			if (tarval_is_null(tv)) {
359
				load = new_bd_ia32_xZero(dbgi, block);
360
361
				set_ia32_ls_mode(load, mode);
				res  = load;
362
#ifdef CONSTRUCT_SSE_CONST
363
			} else if (tarval_is_one(tv)) {
364
				int     cnst  = mode == ia32_mode_float32 ? 26 : 55;
365
366
				ir_node *imm1 = ia32_create_Immediate(irg, cnst);
				ir_node *imm2 = ia32_create_Immediate(irg, 2);
367
368
				ir_node *pslld, *psrld;

369
				load = new_bd_ia32_xAllOnes(dbgi, block);
370
				set_ia32_ls_mode(load, mode);
371
				pslld = new_bd_ia32_xPslld(dbgi, block, load, imm1);
372
				set_ia32_ls_mode(pslld, mode);
373
				psrld = new_bd_ia32_xPsrld(dbgi, block, pslld, imm2);
374
375
				set_ia32_ls_mode(psrld, mode);
				res = psrld;
376
#endif /* CONSTRUCT_SSE_CONST */
377
			} else if (mode == ia32_mode_float32) {
378
				/* we can place any 32bit constant by using a movd gp, sse */
379
380
381
				x86_imm32_t imm = {
					.offset = be_get_tv_bits32(tv, 0),
				};
382
				ir_node *cnst = new_bd_ia32_Const(dbgi, block, &imm);
383
				load = new_bd_ia32_xMovd(dbgi, block, cnst);
384
385
				set_ia32_ls_mode(load, mode);
				res = load;
386
			} else {
387
#ifdef CONSTRUCT_SSE_CONST
388
				if (mode == ia32_mode_float64) {
389
					if (be_get_tv_bits32(tv, 0) == 0) {
390
						ir_node *imm32 = ia32_create_Immediate(irg, 32);
391
392
393
						ir_node *cnst, *psllq;

						/* fine, lower 32bit are zero, produce 32bit value */
394
						unsigned const val = be_get_tv_bits32(tv, 4);
395
						cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, val);
396
						load = new_bd_ia32_xMovd(dbgi, block, cnst);
397
						set_ia32_ls_mode(load, mode);
398
						psllq = new_bd_ia32_xPsllq(dbgi, block, load, imm32);
399
400
401
402
403
						set_ia32_ls_mode(psllq, mode);
						res = psllq;
						goto end;
					}
				}
404
#endif /* CONSTRUCT_SSE_CONST */
405
				ir_entity *const floatent = create_float_const_entity(tv, NULL);
406

407
				ir_node *base = get_global_base(irg);
408
409
				load = new_bd_ia32_xLoad(dbgi, block, base, noreg_GP, nomem,
				                         mode);
Matthias Braun's avatar
Matthias Braun committed
410
				set_irn_pinned(load, false);
411
				set_ia32_op_type(load, ia32_AddrModeS);
412
				set_am_const_entity(load, floatent);
413
				arch_add_irn_flags(load, arch_irn_flag_rematerializable);
414
				res = be_new_Proj(load, pn_ia32_xLoad_res);
415
416
			}
		} else {
417
			if (tarval_is_null(tv)) {
418
				load = new_bd_ia32_fldz(dbgi, block);
419
				res  = load;
420
			} else if (tarval_is_one(tv)) {
421
				load = new_bd_ia32_fld1(dbgi, block);
422
				res  = load;
423
			} else {
424
				ir_entity *const floatent = create_float_const_entity(tv, NULL);
425
426
				/* create_float_const_ent is smart and sometimes creates
				   smaller entities */
427
				ir_mode *ls_mode  = get_type_mode(get_entity_type(floatent));
428
				ir_node *base     = get_global_base(irg);
429
430
				load = new_bd_ia32_fld(dbgi, block, base, noreg_GP, nomem,
				                       ls_mode);
Matthias Braun's avatar
Matthias Braun committed
431
				set_irn_pinned(load, false);
432
				set_ia32_op_type(load, ia32_AddrModeS);
433
				set_am_const_entity(load, floatent);
434
				arch_add_irn_flags(load, arch_irn_flag_rematerializable);
435
				res = be_new_Proj(load, pn_ia32_fld_res);
436
437
			}
		}
438
#ifdef CONSTRUCT_SSE_CONST
439
end:
440
#endif /* CONSTRUCT_SSE_CONST */
441
		SET_IA32_ORIG_NODE(load, node);
442
		return res;
443
	} else { /* non-float mode */
444
		tv = tarval_convert_to(tv, ia32_mode_gp);
445

446
		if (tv == get_tarval_bad() || tv == get_tarval_unknown() ||
447
		    tv == NULL) {
448
449
450
			panic("couldn't convert constant tarval (%+F)", node);
		}

451
		x86_imm32_t imm = { .offset = get_tarval_long(tv) };
452
		ir_node *cnst = new_bd_ia32_Const(dbgi, block, &imm);
453
		SET_IA32_ORIG_NODE(cnst, node);
454
455
456
457
458
459

		return cnst;
	}
}

/**
460
 * Transforms an Address.
461
 */
462
static ir_node *gen_Address(ir_node *node)
Christoph Mallon's avatar
Christoph Mallon committed
463
{
464
465
466
	ir_node  *block = be_transform_nodes_block(node);
	dbg_info *dbgi  = get_irn_dbg_info(node);
	ir_mode  *mode  = get_irn_mode(node);
467

468
	if (!mode_needs_gp_reg(mode))
469
		panic("unexpected mode for Address");
470

471
	ir_entity *entity = get_Address_entity(node);
472
473
474
475
	x86_imm32_t imm = {
		.kind   = X86_IMM_ADDR,
		.entity = entity,
	};
476
	adjust_relocation(&imm);
477
478

	ir_node *cnst;
479
	if (is_tls_entity(entity)) {
480
481
		ir_node *tls_base = new_bd_ia32_LdTls(NULL, block);
		ir_node *lea      = new_bd_ia32_Lea(dbgi, block, tls_base, noreg_GP);
482
483
		ia32_attr_t *const attr = get_ia32_attr(lea);
		attr->am_imm = imm;
484
		cnst = lea;
485
	} else {
486
		cnst = new_bd_ia32_Const(dbgi, block, &imm);
487
	}
488
	SET_IA32_ORIG_NODE(cnst, node);
489
490
491
	return cnst;
}

Matthias Braun's avatar
Matthias Braun committed
492
493
494
495
496
497
498
499
500
501
502
503
504
static ir_node *gen_be_Relocation(ir_node *node)
{
	ir_node  *block = be_transform_nodes_block(node);
	dbg_info *dbgi  = get_irn_dbg_info(node);
	x86_imm32_t imm = {
		.kind   = (x86_immediate_kind_t)be_get_Relocation_kind(node),
		.entity = be_get_Relocation_entity(node),
	};
	ir_node *cnst = new_bd_ia32_Const(dbgi, block, &imm);
	SET_IA32_ORIG_NODE(cnst, node);
	return cnst;
}

505
static ir_type *make_array_type(ir_type *tp)
506
{
507
508
	unsigned alignment = get_type_alignment_bytes(tp);
	unsigned size      = get_type_size_bytes(tp);
509
	ir_type *res       = new_type_array(tp);
510
	set_type_alignment_bytes(res, alignment);
511
	set_array_size_int(res, 2);
512
513
514
515
516
	if (alignment > size)
		size = alignment;
	set_type_size_bytes(res, 2 * size);
	set_type_state(res, layout_fixed);
	return res;
Michael Beck's avatar
Michael Beck committed
517
518
519
520
521
522
523
}

/**
 * Create a float[2] array type for the given atomic type.
 *
 * @param tp  the atomic type
 */
524
525
static ir_type *ia32_create_float_array(ir_type *tp)
{
526
527
	ir_mode *mode = get_type_mode(tp);
	ir_type *arr;
Michael Beck's avatar
Michael Beck committed
528

529
	if (mode == ia32_mode_float32) {
530
		static ir_type *float_F;
Michael Beck's avatar
Michael Beck committed
531

532
533
534
		arr = float_F;
		if (arr == NULL)
			arr = float_F = make_array_type(tp);
535
	} else if (mode == ia32_mode_float64) {
536
		static ir_type *float_D;
Michael Beck's avatar
Michael Beck committed
537

538
539
540
		arr = float_D;
		if (arr == NULL)
			arr = float_D = make_array_type(tp);
Michael Beck's avatar
Michael Beck committed
541
	} else {
542
		static ir_type *float_E;
Michael Beck's avatar
Michael Beck committed
543

544
545
546
		arr = float_E;
		if (arr == NULL)
			arr = float_E = make_array_type(tp);
Michael Beck's avatar
Michael Beck committed
547
548
549
550
	}
	return arr;
}

551
/* Generates an entity for a known FP const (used for FP Neg + Abs) */
552
ir_entity *ia32_gen_fp_known_const(ia32_known_const_t const kct)
Christoph Mallon's avatar
Christoph Mallon committed
553
{
554
	static const struct {
555
		const char *name;
556
		const char *cnst_str;
557
		char        mode;
558
	} names [ia32_known_const_max] = {
559
560
561
562
563
		{ "C_sfp_sign", "0x80000000",          0 },
		{ "C_dfp_sign", "0x8000000000000000",  1 },
		{ "C_sfp_abs",  "0x7FFFFFFF",          0 },
		{ "C_dfp_abs",  "0x7FFFFFFFFFFFFFFF",  1 },
		{ "C_ull_bias", "0x10000000000000000", 2 }
564
	};
565
	static ir_entity *ent_cache[ia32_known_const_max];
566

567
	ir_entity *ent = ent_cache[kct];
568

569
	if (ent == NULL) {
570
571
		char const *const cnst_str = names[kct].cnst_str;
		ident      *const name     = new_id_from_str(names[kct].name);
572
		ir_mode          *mode;
573
		switch (names[kct].mode) {
574
		case 0:  mode = ia32_mode_gp; break;
575
		case 1:  mode = mode_Lu; break;
576
		case 2:  mode = ia32_mode_float32;  break;
577
		default: panic("internal compiler error");
578
		}
579
		ir_tarval *tv = new_tarval_from_str(cnst_str, strlen(cnst_str), mode);
580

581
		if (kct == ia32_ULLBIAS) {
582
			ir_type *type  = get_prim_type(ia32_mode_float32);
583
			ir_type *atype = ia32_create_float_array(type);
584

585
			ent = new_entity(get_glob_type(), name, atype);
586

587
588
589
			set_entity_ld_ident(ent, name);
			set_entity_visibility(ent, ir_visibility_private);
			add_entity_linkage(ent, IR_LINKAGE_CONSTANT);
590

591
			ir_initializer_t *initializer = create_initializer_compound(2);
592
			set_initializer_compound_value(initializer, 0,
593
				create_initializer_tarval(get_mode_null(mode)));
594
595
596
597
			set_initializer_compound_value(initializer, 1,
				create_initializer_tarval(tv));
			set_entity_initializer(ent, initializer);
		} else {
598
			ent = create_float_const_entity(tv, name);
599
		}
600
601
		/* cache the entry */
		ent_cache[kct] = ent;
602
	}
603

604
	return ent_cache[kct];
605
606
}

607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
static ir_node *gen_Unknown(ir_node *node)
{
	ir_mode  *mode  = get_irn_mode(node);
	dbg_info *dbgi  = get_irn_dbg_info(node);
	ir_graph *irg   = get_irn_irg(node);
	ir_node  *block = get_irg_start_block(irg);
	ir_node  *res   = NULL;

	if (mode_is_float(mode)) {
		if (ia32_cg_config.use_sse2) {
			res = new_bd_ia32_xUnknown(dbgi, block);
		} else {
			res = new_bd_ia32_fldz(dbgi, block);
		}
	} else if (mode_needs_gp_reg(mode)) {
		res = new_bd_ia32_Unknown(dbgi, block);
	} else {
		panic("unsupported Unknown-Mode");
	}

	return res;
}

/**
 * Checks whether other node inputs depend on the am_candidate (via mem-proj).
 */
static bool prevents_AM(ir_node *const block, ir_node *const am_candidate,
                        ir_node *const other)
{
	if (get_nodes_block(other) != block)
		return false;

	if (is_Sync(other)) {
		int i;

		for (i = get_Sync_n_preds(other) - 1; i >= 0; --i) {
			ir_node *const pred = get_Sync_pred(other, i);

			if (get_nodes_block(pred) != block)
				continue;

			/* Do not block ourselves from getting eaten */
			if (is_Proj(pred) && get_Proj_pred(pred) == am_candidate)
				continue;

			if (!heights_reachable_in_block(heights, pred, am_candidate))
				continue;

			return true;
		}

		return false;
	} else {
		/* Do not block ourselves from getting eaten */
		if (is_Proj(other) && get_Proj_pred(other) == am_candidate)
			return false;

		if (!heights_reachable_in_block(heights, other, am_candidate))
			return false;

		return true;
	}
}

671
672
673
674
675
676
677
/**
 * return true if the users of the given value will be merged by later
 * optimization. This applies to multiple Cmp nodes (and maybe a Sub
 * node) with the same inputs.
 */
static bool users_will_merge(ir_node *proj)
{
678
679
	ir_node *first     = NULL;
	ir_node *block     = NULL;
680
681
682
683
684
685
686
	ir_node *left      = NULL;
	ir_node *right     = NULL;
	bool     found_sub = false;

	foreach_out_edge(proj, edge) {
		ir_node *user = get_edge_src_irn(edge);

687
		if (first == NULL) {
688
689
690
			if (is_Cmp(user) || is_Sub(user)) {
				// Take the first user as a sample to compare
				// the next ones to.
691
				first     = user;
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
				block     = get_nodes_block(user);
				left      = get_binop_left(user);
				right     = get_binop_right(user);
				found_sub = is_Sub(user);
			} else {
				return false;
			}
		} else {
			if (get_nodes_block(user) != block) {
				return false;
			}

			if (is_Cmp(user) || is_Sub(user)) {
				ir_node *user_left  = get_binop_left(user);
				ir_node *user_right = get_binop_right(user);

				if (found_sub && is_Sub(user)) {
					// Two subs will not be merged
					return false;
				}
712
713
714
715
716
717
				found_sub |= is_Sub(user);

				if ((is_Sub(user) || is_Sub(first)) &&
				    user_left == right && user_right == left) {
					continue;
				}
718
719
720
721
722
723
724
725
726
727
728
				if (user_left != left || user_right != right) {
					return false;
				}
			} else {
				return false;
			}
		}
	}
	return true;
}

729
730
731
732
733
734
/**
 * return true if the node is a Proj(Load) and could be used in source address
 * mode for another node. Will return only true if the @p other node is not
 * dependent on the memory of the Load (for binary operations use the other
 * input here, for unary operations use NULL).
 */
735
736
737
static bool ia32_use_source_address_mode(ir_node *block, ir_node *node,
                                         ir_node *other, ir_node *other2,
                                         match_flags_t flags)
738
{
739
	/* float constants are always available */
Michael Beck's avatar
Michael Beck committed
740
	if (is_Const(node)) {
741
		ir_mode *mode = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
742
		if (mode_is_float(mode)) {
743
			ir_tarval *tv = get_Const_tarval(node);
744
			if (!tarval_ieee754_can_conv_lossless(tv, ia32_mode_float64))
745
				return false;
Michael Beck's avatar
Michael Beck committed
746
747
			if (ia32_cg_config.use_sse2) {
				if (is_simple_sse_Const(node))
748
					return false;
Michael Beck's avatar
Michael Beck committed
749
750
			} else {
				if (is_simple_x87_Const(node))
751
					return false;
Michael Beck's avatar
Michael Beck committed
752
753
			}
			if (get_irn_n_edges(node) > 1)
754
755
				return false;
			return true;
756
		}
757
		return false;
758
759
	}

Michael Beck's avatar
Michael Beck committed
760
	if (!is_Proj(node))
761
762
		return false;
	ir_node *load = get_Proj_pred(node);
763
	if (!is_Load(load))
764
		return false;
765
	assert(get_Proj_num(node) == pn_Load_res);
Michael Beck's avatar
Michael Beck committed
766
	if (get_nodes_block(load) != block)
767
768
		return false;
	ir_mode *mode = get_irn_mode(node);
769
770
	/* we can't fold mode_E AM */
	if (mode == ia32_mode_E)
771
		return false;
772
773
774
775
	/* we only use address mode if we're the only user of the load
	 * or the users will be merged later anyway */
	if (get_irn_n_edges(node) != (flags & match_two_users ? 2 : 1) &&
	    !users_will_merge(node))
776
		return false;
777
778
779
	/* in some edge cases with address mode we might reach the load normally
	 * and through some AM sequence, if it is already materialized then we
	 * can't create an AM node from it */
Michael Beck's avatar
Michael Beck committed
780
	if (be_is_transformed(node))
781
		return false;
782
783

	/* don't do AM if other node inputs depend on the load (via mem-proj) */
784
	if (other != NULL && prevents_AM(block, load, other))
785
		return false;
786

787
	if (other2 != NULL && prevents_AM(block, load, other2))
788
		return false;
789

790
	return true;
791
792
793
794
}

typedef struct ia32_address_mode_t ia32_address_mode_t;
struct ia32_address_mode_t {
795
	x86_address_t   addr;
796
797
	ir_mode        *ls_mode;
	ir_node        *mem_proj;
798
	ir_node        *am_node;
799
800
801
	ia32_op_type_t  op_type;
	ir_node        *new_op1;
	ir_node        *new_op2;
Matthias Braun's avatar
Matthias Braun committed
802
	bool            pinned       : 1;
Matthias Braun's avatar
Matthias Braun committed
803
804
	unsigned        commutative  : 1;
	unsigned        ins_permuted : 1;
805
806
};

807
808
809
810
static void ia32_create_address_mode(x86_address_t *addr, ir_node *ptr,
                                     x86_create_am_flags_t flags)
{
	x86_create_address_mode(addr, ptr, flags);
811
	adjust_relocation(&addr->imm);
812
813
}

814
static void build_address_ptr(x86_address_t *addr, ir_node *ptr, ir_node *mem)
Matthias Braun's avatar
Matthias Braun committed
815
816
817
{
	/* construct load address */
	memset(addr, 0, sizeof(addr[0]));
818
	ia32_create_address_mode(addr, ptr, x86_create_am_normal);
Matthias Braun's avatar
Matthias Braun committed
819

820
821
	addr->base  = addr->base  ? be_transform_node(addr->base)  : noreg_GP;
	addr->index = addr->index ? be_transform_node(addr->index) : noreg_GP;
Matthias Braun's avatar
Matthias Braun committed
822
823
824
	addr->mem   = be_transform_node(mem);
}

825
static void build_address(ia32_address_mode_t *am, ir_node *node,
826
                          x86_create_am_flags_t flags)
827
{
828
	x86_address_t *addr = &am->addr;
829

830
	/* floating point immediates */
831
	if (is_Const(node)) {
832
833
		ir_graph  *const irg    = get_irn_irg(node);
		ir_tarval *const tv     = get_Const_tarval(node);
834
		ir_entity *const entity = create_float_const_entity(tv, NULL);
835
		addr->base        = get_global_base(irg);
836
837
		addr->index       = noreg_GP;
		addr->mem         = nomem;
838
		addr->imm         = (x86_imm32_t) {
839
			.kind   = lconst_imm_kind,
840
841
			.entity = entity,
		};
842
		adjust_relocation(&addr->imm);
843
		addr->tls_segment = false;
844
		addr->use_frame   = false;
845
		am->ls_mode       = get_type_mode(get_entity_type(entity));
Matthias Braun's avatar
Matthias Braun committed
846
		am->pinned        = false;
847
848
849
		return;
	}

850
851
852
853
854
855
	ir_node *load    = get_Proj_pred(node);
	ir_node *ptr     = get_Load_ptr(load);
	ir_node *mem     = get_Load_mem(load);
	ir_node *new_mem = be_transform_node(mem);
	am->pinned       = get_irn_pinned(load);
	am->ls_mode      = get_Load_mode(load);
856
	am->mem_proj     = get_Proj_for_pn(load, pn_Load_M);
857
	am->am_node      = node;
858
859

	/* construct load address */
860
	ia32_create_address_mode(addr, ptr, flags);
861

862
863
	addr->base  = addr->base  ? be_transform_node(addr->base)  : noreg_GP;
	addr->index = addr->index ? be_transform_node(addr->index) : noreg_GP;
864
	addr->mem   = new_mem;
865
866
}

867
static void set_address(ir_node *node, const x86_address_t *addr)
868
{
869
870
	ia32_attr_t *const attr = get_ia32_attr(node);
	attr->am_imm = addr->imm;
871
	set_ia32_am_scale(node, addr->scale);
872
	set_ia32_am_tls_segment(node, addr->tls_segment);
873
874
	if (addr->imm.kind == X86_IMM_FRAMEOFFSET) {
		assert(addr->use_frame);
875
		set_ia32_frame_use(node, IA32_FRAME_USE_AUTO);
876
877
878
	} else {
		assert(!addr->use_frame);
	}
879
880
}

Michael Beck's avatar
Michael Beck committed
881
882
883
/**
 * Apply attributes of a given address mode to a node.
 */
884
static void set_am_attributes(ir_node *node, const ia32_address_mode_t *am)
885
886
{
	set_address(node, &am->addr);
887

888
889
	set_ia32_op_type(node, am->op_type);
	set_ia32_ls_mode(node, am->ls_mode);
Matthias Braun's avatar
Matthias Braun committed
890
	if (am->pinned) {
891
		/* beware: some nodes are already pinned and did not allow to change the state */