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
#include "tv_t.h"
34

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

41
42
#include "gen_ia32_regalloc_if.h"
#include "ia32_architecture.h"
43
#include "ia32_bearch_t.h"
44
45
46
#include "ia32_new_nodes.h"
#include "ia32_nodes_attr.h"
#include "ia32_transform.h"
47
#include "util.h"
48
#include "x86_address_mode.h"
49
#include "x86_cconv.h"
50
#include "x86_x87.h"
51

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

55
DEBUG_ONLY(static firm_dbg_module_t *dbg;)
56

57
static x86_cconv_t          *current_cconv;
58
static be_stack_env_t        stack_env;
59
60
static ir_heights_t         *heights;
static x86_immediate_kind_t  lconst_imm_kind;
61
static x86_addr_variant_t    lconst_variant;
62
static ir_node              *initial_va_list;
63

64
65
66
67
68
69
70
71
72
73
74
75
76
/** 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]
77
const x86_asm_constraint_list_t ia32_asm_constraints = {
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
	['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 },
97
	['e'] = { MATCH_IMM, GP, 0 },
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
	['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
116
	// logic at play not everything is documented in the manual. In the gcc
117
118
119
120
121
122
	// 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

123
124
typedef ir_node *construct_binop_func(dbg_info *db, ir_node *block,
        ir_node *base, ir_node *index, ir_node *mem, ir_node *op1,
125
        ir_node *op2, x86_insn_size_t size);
Christian Würdig's avatar
Christian Würdig committed
126

127
128
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,
129
        ir_node *flags, x86_insn_size_t size);
130

131
typedef ir_node *construct_shift_func(dbg_info *db, ir_node *block,
132
        ir_node *op1, ir_node *op2, x86_insn_size_t size);
133

134
typedef ir_node *construct_binop_dest_func(dbg_info *db, ir_node *block,
135
136
        ir_node *base, ir_node *index, ir_node *mem, ir_node *op,
        x86_insn_size_t size);
137

138
typedef ir_node *construct_unop_dest_func(dbg_info *db, ir_node *block,
139
        ir_node *base, ir_node *index, ir_node *mem, x86_insn_size_t size);
140

141
142
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,
143
        ir_node *fpcw, x86_insn_size_t size);
Matthias Braun's avatar
Matthias Braun committed
144

145
146
typedef ir_node *construct_unop_func(dbg_info *db, ir_node *block, ir_node *op,
                                     x86_insn_size_t size);
147

148
149
static ir_node *create_immediate_or_transform(ir_node *node,
                                              const char immediate_mode);
150

151
static ir_node *create_I2I_Conv(ir_mode *src_mode, dbg_info *dbgi, ir_node *block, ir_node *op);
152

153
/* its enough to have those once */
154
155
static ir_node *nomem;
static ir_node *noreg_GP;
156

157
158
159
160
161
static bool mode_needs_gp_reg(ir_mode *mode)
{
	return get_mode_arithmetic(mode) == irma_twos_complement;
}

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

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

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

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

	/* TODO: match all the other float constants */
190
	return false;
191
192
193
194
195
}

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

201
	if (get_mode_size_bits(mode) == 32)
202
		return true;
203

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

222
223
ir_node *ia32_get_pic_base(ir_graph *irg)
{
224
225
226
227
228
229
	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;
230
231
}

232
233
234
235
/**
 * return NoREG or pic_base in case of PIC.
 * This is necessary as base address for newly created symbols
 */
236
static ir_node *get_global_base(ir_graph *const irg)
237
{
238
	if (be_options.pic_style != BE_PIC_NONE)
239
		return ia32_get_pic_base(irg);
240
241
242
	return noreg_GP;
}

243
244
static ir_node *get_initial_sp(ir_graph *irg)
{
Christoph Mallon's avatar
Christoph Mallon committed
245
	return be_get_Start_proj(irg, &ia32_registers[REG_ESP]);
246
247
248
249
}

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

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

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

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

280
static ir_node *try_create_Immediate(const ir_node *node, char const constraint)
281
{
282
283
	x86_imm32_t immediate;
	if (!x86_match_immediate(&immediate, node, constraint))
284
		return NULL;
285
	adjust_relocation(&immediate);
286
287

	ir_graph *const irg = get_irn_irg(node);
288
	return ia32_create_Immediate_full(irg, &immediate);
289
290
291
292
}

static ir_type *get_prim_type(const ir_mode *mode)
{
293
294
	if (mode == x86_mode_E) {
		return x86_type_E;
295
296
297
298
299
	} else {
		return get_type_for_mode(mode);
	}
}

300
static ir_entity *create_float_const_entity(ir_tarval *tv, ident *name)
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
{
	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;
			}
		}
	}

318
	ir_entity *res = pmap_get(ir_entity, ia32_tv_ent, tv);
319
320
321
322
323
	if (!res) {
		if (!name)
			name = id_unique("C%u");

		ir_type *const tp = get_prim_type(mode);
324
325
326
		res = new_global_entity(get_glob_type(), name, tp,
		                        ir_visibility_private,
		                        IR_LINKAGE_CONSTANT | IR_LINKAGE_NO_IDENTITY);
327
328
329
330

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

331
		pmap_insert(ia32_tv_ent, tv, res);
332
333
334
335
	}
	return res;
}

336
337
338
static void set_am_const_entity(ir_node *node, ir_entity *entity)
{
	ia32_attr_t *const attr = get_ia32_attr(node);
339
	attr->addr.immediate = (x86_imm32_t) {
340
		.kind   = lconst_imm_kind,
341
342
		.entity = entity,
	};
343
	attr->addr.variant = lconst_variant;
344
345
}

346
347
348
/**
 * Transforms a Const.
 */
Christoph Mallon's avatar
Christoph Mallon committed
349
350
static ir_node *gen_Const(ir_node *node)
{
351
352
353
354
355
	ir_node        *const block = be_transform_nodes_block(node);
	dbg_info       *const dbgi  = get_irn_dbg_info(node);
	ir_mode        *const mode  = get_irn_mode(node);
	ir_tarval      *const tv    = get_Const_tarval(node);
	x86_insn_size_t const size  = x86_size_from_mode(mode);
356
357

	if (mode_is_float(mode)) {
358
		ir_graph *const irg = get_irn_irg(node);
359
		ir_node        *res;
360
		if (ia32_cg_config.use_sse2) {
361
			if (tarval_is_null(tv)) {
362
				res = new_bd_ia32_xZero(dbgi, block, size);
363
#ifdef CONSTRUCT_SSE_CONST
364
			} else if (tarval_is_one(tv)) {
365
366
367
368
369
370
371
				int      cnst    = mode == ia32_mode_float32 ? 26 : 55;
				ir_node *imm1    = ia32_create_Immediate(irg, cnst);
				ir_node *imm2    = ia32_create_Immediate(irg, 2);
				ir_node *allones = new_bd_ia32_xAllOnes(dbgi, block, size);
				ir_node *pslld   = new_bd_ia32_xPslld(dbgi, block, allones,
				                                      imm1, size);
				res = new_bd_ia32_xPsrld(dbgi, block, pslld, imm2, size);
372
#endif /* CONSTRUCT_SSE_CONST */
373
			} else if (mode == ia32_mode_float32) {
374
				/* we can place any 32bit constant by using a movd gp, sse */
375
376
377
				x86_imm32_t imm = {
					.offset = be_get_tv_bits32(tv, 0),
				};
378
				ir_node *cnst = new_bd_ia32_Const(dbgi, block, &imm);
379
				res = new_bd_ia32_xMovd(dbgi, block, cnst);
380
			} else {
381
#ifdef CONSTRUCT_SSE_CONST
382
383
384
385
				if (mode == ia32_mode_float64 && be_get_tv_bits32(tv, 0) == 0) {
					ir_node *imm32 = ia32_create_Immediate(irg, 32);

					/* fine, lower 32bit are zero, produce 32bit value */
386
387
388
389
390
391
					x86_imm32_t const imm = {
						.offset = be_get_tv_bits32(tv, 4),
					};
					ir_node *const cnst = new_bd_ia32_Const(dbgi, block, &imm);
					ir_node *const movd = new_bd_ia32_xMovd(dbgi, block, cnst);
					res = new_bd_ia32_xPsllq(dbgi, block, movd, imm32, size);
392
					goto end;
393
				}
394
#endif /* CONSTRUCT_SSE_CONST */
395
				ir_entity *const floatent = create_float_const_entity(tv, NULL);
396

397
				ir_node *base = get_global_base(irg);
398
399
				ir_node *load = new_bd_ia32_xLoad(dbgi, block, base, noreg_GP,
				                                  nomem, size);
Matthias Braun's avatar
Matthias Braun committed
400
				set_irn_pinned(load, false);
401
				set_ia32_op_type(load, ia32_AddrModeS);
402
				set_am_const_entity(load, floatent);
403
				arch_add_irn_flags(load, arch_irn_flag_rematerializable);
404
				res = be_new_Proj(load, pn_ia32_xLoad_res);
405
406
			}
		} else {
407
			if (tarval_is_null(tv)) {
408
				res = new_bd_ia32_fldz(dbgi, block);
409
			} else if (tarval_is_one(tv)) {
410
				res = new_bd_ia32_fld1(dbgi, block);
411
			} else if (tarval_is_minus_null(tv)) {
412
				res = new_bd_ia32_fldz(dbgi, block);
413
414
				goto negate;
			} else if (tarval_is_minus_one(tv)) {
415
				res = new_bd_ia32_fld1(dbgi, block);
416
negate:
417
				res = new_bd_ia32_fchs(dbgi, block, res);
418
			} else {
419
				ir_entity *const floatent = create_float_const_entity(tv, NULL);
420
421
				/* create_float_const_ent is smart and sometimes creates
				   smaller entities */
422
423
424
425
426
				ir_mode *ent_mode = get_type_mode(get_entity_type(floatent));
				x86_insn_size_t const size = x86_size_from_mode(ent_mode);
				ir_node *base = get_global_base(irg);
				ir_node *load = new_bd_ia32_fld(dbgi, block, base, noreg_GP,
				                                nomem, size);
Matthias Braun's avatar
Matthias Braun committed
427
				set_irn_pinned(load, false);
428
429
430
431
432
433
				ia32_attr_t *const attr = get_ia32_attr(load);
				attr->addr = (x86_addr_t) {
					.immediate = {
						.kind   = lconst_imm_kind,
						.entity = floatent,
					},
434
					.variant = lconst_variant,
435
				};
436
				set_ia32_op_type(load, ia32_AddrModeS);
437
				arch_add_irn_flags(load, arch_irn_flag_rematerializable);
438
				res = be_new_Proj(load, pn_ia32_fld_res);
439
440
			}
		}
441
#ifdef CONSTRUCT_SSE_CONST
442
end:
443
#endif
444
		return res;
445
	} else { /* non-float mode */
446
447
		ir_tarval *conv_tv = tarval_convert_to(tv, ia32_mode_gp);
		if (conv_tv == get_tarval_bad())
448
449
			panic("couldn't convert constant tarval (%+F)", node);

450
		x86_imm32_t imm = { .offset = get_tarval_long(conv_tv) };
451
		return new_bd_ia32_Const(dbgi, block, &imm);
452
453
454
455
	}
}

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

464
	if (!mode_needs_gp_reg(mode))
465
		panic("unexpected mode for Address");
466

467
	ir_entity *entity = get_Address_entity(node);
468
469
470
471
	x86_imm32_t imm = {
		.kind   = X86_IMM_ADDR,
		.entity = entity,
	};
472
	adjust_relocation(&imm);
473

474
	if (is_tls_entity(entity)) {
475
476
477
		ir_node     *const tls_base = new_bd_ia32_LdTls(NULL, block);
		ir_node     *const lea      = new_bd_ia32_Lea(dbgi, block, tls_base, noreg_GP);
		ia32_attr_t *const attr     = get_ia32_attr(lea);
478
		attr->addr.variant   = X86_ADDR_BASE;
479
		attr->addr.immediate = imm;
480
		return lea;
481
	} else {
482
		return new_bd_ia32_Const(dbgi, block, &imm);
483
484
485
	}
}

Matthias Braun's avatar
Matthias Braun committed
486
487
488
489
490
491
492
493
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),
	};
494
	return new_bd_ia32_Const(dbgi, block, &imm);
Matthias Braun's avatar
Matthias Braun committed
495
496
}

497
static ir_type *make_array_type(ir_type *tp)
498
{
499
500
	unsigned alignment = get_type_alignment(tp);
	unsigned size      = get_type_size(tp);
501
	ir_type *res       = new_type_array(tp);
502
	set_type_alignment(res, alignment);
503
	set_array_size_int(res, 2);
504
505
	if (alignment > size)
		size = alignment;
506
	set_type_size(res, 2 * size);
507
508
	set_type_state(res, layout_fixed);
	return res;
Michael Beck's avatar
Michael Beck committed
509
510
511
512
513
514
515
}

/**
 * Create a float[2] array type for the given atomic type.
 *
 * @param tp  the atomic type
 */
516
517
static ir_type *ia32_create_float_array(ir_type *tp)
{
518
519
	ir_mode *mode = get_type_mode(tp);
	ir_type *arr;
Michael Beck's avatar
Michael Beck committed
520

521
	if (mode == ia32_mode_float32) {
522
		static ir_type *float_F;
Michael Beck's avatar
Michael Beck committed
523

524
525
526
		arr = float_F;
		if (arr == NULL)
			arr = float_F = make_array_type(tp);
527
	} else if (mode == ia32_mode_float64) {
528
		static ir_type *float_D;
Michael Beck's avatar
Michael Beck committed
529

530
531
532
		arr = float_D;
		if (arr == NULL)
			arr = float_D = make_array_type(tp);
Michael Beck's avatar
Michael Beck committed
533
	} else {
534
		static ir_type *float_E;
Michael Beck's avatar
Michael Beck committed
535

536
537
538
		arr = float_E;
		if (arr == NULL)
			arr = float_E = make_array_type(tp);
Michael Beck's avatar
Michael Beck committed
539
540
541
542
	}
	return arr;
}

543
/* Generates an entity for a known FP const (used for FP Neg + Abs) */
544
ir_entity *ia32_gen_fp_known_const(ia32_known_const_t const kct)
Christoph Mallon's avatar
Christoph Mallon committed
545
{
546
	static const struct {
547
		const char *name;
548
		const char *cnst_str;
549
		char        mode;
550
	} names [ia32_known_const_max] = {
551
552
553
554
555
		{ "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 }
556
	};
557
	static ir_entity *ent_cache[ia32_known_const_max];
558

559
	ir_entity *ent = ent_cache[kct];
560

561
	if (ent == NULL) {
562
563
		char const *const cnst_str = names[kct].cnst_str;
		ident      *const name     = new_id_from_str(names[kct].name);
564
		ir_mode          *mode;
565
		switch (names[kct].mode) {
566
		case 0:  mode = ia32_mode_gp; break;
567
		case 1:  mode = mode_Lu; break;
568
		case 2:  mode = ia32_mode_float32;  break;
569
		default: panic("internal compiler error");
570
		}
571
		ir_tarval *tv = new_tarval_from_str(cnst_str, strlen(cnst_str), mode);
572

573
		if (kct == ia32_ULLBIAS) {
574
			ir_type *type  = get_prim_type(ia32_mode_float32);
575
			ir_type *atype = ia32_create_float_array(type);
576

577
578
579
			ent = new_global_entity(get_glob_type(), name, atype,
			                        ir_visibility_private,
			                        IR_LINKAGE_CONSTANT|IR_LINKAGE_NO_IDENTITY);
580

581
			ir_initializer_t *initializer = create_initializer_compound(2);
582
			set_initializer_compound_value(initializer, 0,
583
				create_initializer_tarval(get_mode_null(mode)));
584
585
586
587
			set_initializer_compound_value(initializer, 1,
				create_initializer_tarval(tv));
			set_entity_initializer(ent, initializer);
		} else {
588
			ent = create_float_const_entity(tv, name);
589
		}
590
591
		/* cache the entry */
		ent_cache[kct] = ent;
592
	}
593

594
	return ent_cache[kct];
595
596
}

597
598
599
600
601
602
603
604
605
606
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) {
607
			res = new_bd_ia32_xUnknown(dbgi, block, X86_SIZE_128);
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
		} 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;
	}
}

661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
static bool cmp_can_use_sub_flags(ir_node *cmp, ir_node *sub, bool *swap)
{
	ir_node *cmp_block = get_nodes_block(cmp);
	ir_node *sub_block = get_nodes_block(sub);

	if (!(block_dominates(cmp_block, sub_block) ||
	      block_dominates(sub_block, cmp_block))) {
		return false;
	}

	ir_node *cmp_left  = get_Cmp_left(cmp);
	ir_node *cmp_right = get_Cmp_right(cmp);
	ir_node *sub_left  = get_Sub_left(sub);
	ir_node *sub_right = get_Sub_right(sub);

	if (cmp_left == sub_left && cmp_right == sub_right) {
		*swap = false;
	} else if (cmp_left == sub_right && cmp_right == sub_left) {
		*swap = true;
	} else {
		return false;
	}

	ir_mode *sub_mode = get_irn_mode(sub_left);
	if (get_mode_size_bits(sub_mode) != 32 &&
	    (!be_upper_bits_clean(sub_left,  sub_mode) ||
	     !be_upper_bits_clean(sub_right, sub_mode))) {
		return false;
	}

	return true;
}

694
695
696
697
698
699
700
/**
 * 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)
{
701
	ir_node *sub = NULL;
702

703
	/* Check that there is one Sub and some Cmps. */
704
705
706
	foreach_out_edge(proj, edge) {
		ir_node *user = get_edge_src_irn(edge);

707
708
709
		if (is_Sub(user)) {
			if (sub == NULL) {
				sub = user;
710
			} else {
711
				/* Two Subs will not merge */
712
713
				return false;
			}
714
715
716
717
		} else if (!is_Cmp(user)) {
			return false;
		}
	}
718

719
720
721
722
723
	if (sub == NULL) {
		/* Cmps only will not merge.
		 * (probably need to be rematerialized later anyway) */
		return false;
	}
724

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

728
729
730
		if (is_Cmp(user)) {
			bool dump;
			if (!cmp_can_use_sub_flags(user, sub, &dump)) {
731
732
733
734
735
736
737
				return false;
			}
		}
	}
	return true;
}

738
739
740
741
742
743
/**
 * 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).
 */
744
745
746
static bool ia32_use_source_address_mode(ir_node *block, ir_node *node,
                                         ir_node *other, ir_node *other2,
                                         match_flags_t flags)
747
{
748
	/* float constants are always available */
Michael Beck's avatar
Michael Beck committed
749
	if (is_Const(node)) {
750
		ir_mode *mode = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
751
		if (mode_is_float(mode)) {
752
			ir_tarval *tv = get_Const_tarval(node);
753
			if (!tarval_ieee754_can_conv_lossless(tv, ia32_mode_float64))
754
				return false;
Michael Beck's avatar
Michael Beck committed
755
756
			if (ia32_cg_config.use_sse2) {
				if (is_simple_sse_Const(node))
757
					return false;
Michael Beck's avatar
Michael Beck committed
758
759
			} else {
				if (is_simple_x87_Const(node))
760
					return false;
Michael Beck's avatar
Michael Beck committed
761
762
			}
			if (get_irn_n_edges(node) > 1)
763
764
				return false;
			return true;
765
		}
766
		return false;
767
768
	}

Michael Beck's avatar
Michael Beck committed
769
	if (!is_Proj(node))
770
771
		return false;
	ir_node *load = get_Proj_pred(node);
772
	if (!is_Load(load))
773
		return false;
774
	assert(get_Proj_num(node) == pn_Load_res);
Michael Beck's avatar
Michael Beck committed
775
	if (get_nodes_block(load) != block)
776
777
		return false;
	ir_mode *mode = get_irn_mode(node);
778
	/* we can't fold mode_E AM */
779
	if (mode == x86_mode_E)
780
		return false;
781
782
783
784
	/* 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))
785
		return false;
786
787
788
	/* 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
789
	if (be_is_transformed(node))
790
		return false;
791
792

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

796
	if (other2 != NULL && prevents_AM(block, load, other2))
797
		return false;
798

799
	return true;
800
801
802
803
}

typedef struct ia32_address_mode_t ia32_address_mode_t;
struct ia32_address_mode_t {
804
	x86_address_t   addr;
805
	ir_node        *mem_proj;
806
	x86_insn_size_t size;
807
808
809
	ia32_op_type_t  op_type;
	ir_node        *new_op1;
	ir_node        *new_op2;
Matthias Braun's avatar
Matthias Braun committed
810
	bool            pinned       : 1;
Matthias Braun's avatar
Matthias Braun committed
811
812
	unsigned        commutative  : 1;
	unsigned        ins_permuted : 1;
813
814
};

815
816
817
818
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);
819
	adjust_relocation(&addr->imm);
820
821
}

822
static void build_address_ptr(x86_address_t *addr, ir_node *ptr, ir_node *mem)
Matthias Braun's avatar
Matthias Braun committed
823
824
825
{
	/* construct load address */
	memset(addr, 0, sizeof(addr[0]));
826
	ia32_create_address_mode(addr, ptr, x86_create_am_normal);
Matthias Braun's avatar
Matthias Braun committed
827

828
829
830
831
832
833
834
	addr->variant = addr->base ? (addr->index ? X86_ADDR_BASE_INDEX
	                                          : X86_ADDR_BASE)
	                           : (addr->index ? X86_ADDR_INDEX
	                                          : X86_ADDR_JUST_IMM);
	addr->base    = addr->base  ? be_transform_node(addr->base)  : noreg_GP;
	addr->index   = addr->index ? be_transform_node(addr->index) : noreg_GP;
	addr->mem     = be_transform_node(mem);
Matthias Braun's avatar
Matthias Braun committed
835
836
}

837
static void build_address(ia32_address_mode_t *am, ir_node *node,
838
                          x86_create_am_flags_t flags)
839
{
840
	x86_address_t *addr = &am->addr;
841

842
	/* floating point immediates */
843
	if (is_Const(node)) {
844
845
		ir_graph  *const irg    = get_irn_irg(node);
		ir_tarval *const tv     = get_Const_tarval(node);
846
		ir_entity *const entity = create_float_const_entity(tv, NULL);
847
		addr->base        = get_global_base(irg);
848
849
		addr->index       = noreg_GP;
		addr->mem         = nomem;
850
		addr->imm         = (x86_imm32_t) {
851
			.kind   = lconst_imm_kind,
852
853
			.entity = entity,
		};
854
		addr->variant     = lconst_variant,
855
		adjust_relocation(&addr->imm);
856
		addr->tls_segment = false;
857
		am->size          = x86_size_from_mode(get_type_mode(get_entity_type(entity)));
Matthias Braun's avatar
Matthias Braun committed
858
		am->pinned        = false;
859
860
861
		return;
	}

862
863
864
865
866
	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);
867
	am->size         = x86_size_from_mode(get_Load_mode(load));
868
	am->mem_proj     = get_Proj_for_pn(load, pn_Load_M);
869
870

	/* construct load address */
871
	ia32_create_address_mode(addr, ptr, flags);
872

873
874
875
876
877
878
879
	addr->variant = addr->base ? (addr->index ? X86_ADDR_BASE_INDEX
	                                          : X86_ADDR_BASE)
	                           : (addr->index ? X86_ADDR_INDEX
	                                          : X86_ADDR_JUST_IMM);
	addr->base    = addr->base  ? be_transform_node(addr->base)  : noreg_GP;
	addr->index   = addr->index ? be_transform_node(addr->index) : noreg_GP;
	addr->mem     = new_mem;
880
881
}

882
static void set_address(ir_node *node, const x86_address_t *addr)