ia32_transform.c 185 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
41
#include "gen_ia32_regalloc_if.h"
#include "ia32_architecture.h"
42
#include "ia32_bearch_t.h"
43
44
45
#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
#include "x86_x87.h"
50

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

54
DEBUG_ONLY(static firm_dbg_module_t *dbg;)
55

56
static x86_cconv_t          *current_cconv;
57
static be_stack_env_t        stack_env;
58
59
60
static ir_heights_t         *heights;
static x86_immediate_kind_t  lconst_imm_kind;
static ir_node              *initial_va_list;
61

62
63
64
65
66
67
68
69
70
71
72
73
74
/** 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]
75
const x86_asm_constraint_list_t ia32_asm_constraints = {
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
	['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 },
95
	['e'] = { MATCH_IMM, GP, 0 },
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
	['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 (be_options.pic_style != BE_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
}

static ir_type *get_prim_type(const ir_mode *mode)
{
289
290
	if (mode == x86_mode_E) {
		return x86_type_E;
291
292
293
294
295
	} 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
	if (!res) {
		if (!name)
			name = id_unique("C%u");

		ir_type *const tp = get_prim_type(mode);
320
321
322
		res = new_global_entity(get_glob_type(), name, tp,
		                        ir_visibility_private,
		                        IR_LINKAGE_CONSTANT | IR_LINKAGE_NO_IDENTITY);
323
324
325
326
327
		set_entity_ld_ident(res, get_entity_ident(res));

		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
static void set_am_const_entity(ir_node *node, ir_entity *entity)
{
	ia32_attr_t *const attr = get_ia32_attr(node);
336
	attr->addr.immediate = (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
433
434
435
436
437
438
439
				ia32_attr_t *const attr = get_ia32_attr(load);
				attr->addr = (x86_addr_t) {
					.immediate = {
						.kind   = lconst_imm_kind,
						.entity = floatent,
					},
					.variant = X86_ADDR_BASE,
				};
440
				set_ia32_op_type(load, ia32_AddrModeS);
441
				arch_add_irn_flags(load, arch_irn_flag_rematerializable);
442
				res = be_new_Proj(load, pn_ia32_fld_res);
443
444
			}
		}
445
#ifdef CONSTRUCT_SSE_CONST
446
end:
447
#endif /* CONSTRUCT_SSE_CONST */
448
		SET_IA32_ORIG_NODE(load, node);
449
		return res;
450
	} else { /* non-float mode */
451
		tv = tarval_convert_to(tv, ia32_mode_gp);
452
		if (tv == get_tarval_bad())
453
454
			panic("couldn't convert constant tarval (%+F)", node);

455
		x86_imm32_t imm = { .offset = get_tarval_long(tv) };
456
		ir_node *cnst = new_bd_ia32_Const(dbgi, block, &imm);
457
		SET_IA32_ORIG_NODE(cnst, node);
458
459
460
461
462
463

		return cnst;
	}
}

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

472
	if (!mode_needs_gp_reg(mode))
473
		panic("unexpected mode for Address");
474

475
	ir_entity *entity = get_Address_entity(node);
476
477
478
479
	x86_imm32_t imm = {
		.kind   = X86_IMM_ADDR,
		.entity = entity,
	};
480
	adjust_relocation(&imm);
481
482

	ir_node *cnst;
483
	if (is_tls_entity(entity)) {
484
485
		ir_node *tls_base = new_bd_ia32_LdTls(NULL, block);
		ir_node *lea      = new_bd_ia32_Lea(dbgi, block, tls_base, noreg_GP);
486
		ia32_attr_t *const attr = get_ia32_attr(lea);
487
		attr->addr.variant   = X86_ADDR_BASE;
488
		attr->addr.immediate = imm;
489
		cnst = lea;
490
	} else {
491
		cnst = new_bd_ia32_Const(dbgi, block, &imm);
492
	}
493
	SET_IA32_ORIG_NODE(cnst, node);
494
495
496
	return cnst;
}

Matthias Braun's avatar
Matthias Braun committed
497
498
499
500
501
502
503
504
505
506
507
508
509
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;
}

510
static ir_type *make_array_type(ir_type *tp)
511
{
512
513
	unsigned alignment = get_type_alignment(tp);
	unsigned size      = get_type_size(tp);
514
	ir_type *res       = new_type_array(tp);
515
	set_type_alignment(res, alignment);
516
	set_array_size_int(res, 2);
517
518
	if (alignment > size)
		size = alignment;
519
	set_type_size(res, 2 * size);
520
521
	set_type_state(res, layout_fixed);
	return res;
Michael Beck's avatar
Michael Beck committed
522
523
524
525
526
527
528
}

/**
 * Create a float[2] array type for the given atomic type.
 *
 * @param tp  the atomic type
 */
529
530
static ir_type *ia32_create_float_array(ir_type *tp)
{
531
532
	ir_mode *mode = get_type_mode(tp);
	ir_type *arr;
Michael Beck's avatar
Michael Beck committed
533

534
	if (mode == ia32_mode_float32) {
535
		static ir_type *float_F;
Michael Beck's avatar
Michael Beck committed
536

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

543
544
545
		arr = float_D;
		if (arr == NULL)
			arr = float_D = make_array_type(tp);
Michael Beck's avatar
Michael Beck committed
546
	} else {
547
		static ir_type *float_E;
Michael Beck's avatar
Michael Beck committed
548

549
550
551
		arr = float_E;
		if (arr == NULL)
			arr = float_E = make_array_type(tp);
Michael Beck's avatar
Michael Beck committed
552
553
554
555
	}
	return arr;
}

556
/* Generates an entity for a known FP const (used for FP Neg + Abs) */
557
ir_entity *ia32_gen_fp_known_const(ia32_known_const_t const kct)
Christoph Mallon's avatar
Christoph Mallon committed
558
{
559
	static const struct {
560
		const char *name;
561
		const char *cnst_str;
562
		char        mode;
563
	} names [ia32_known_const_max] = {
564
565
566
567
568
		{ "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 }
569
	};
570
	static ir_entity *ent_cache[ia32_known_const_max];
571

572
	ir_entity *ent = ent_cache[kct];
573

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

586
		if (kct == ia32_ULLBIAS) {
587
			ir_type *type  = get_prim_type(ia32_mode_float32);
588
			ir_type *atype = ia32_create_float_array(type);
589

590
591
592
			ent = new_global_entity(get_glob_type(), name, atype,
			                        ir_visibility_private,
			                        IR_LINKAGE_CONSTANT|IR_LINKAGE_NO_IDENTITY);
593

594
			set_entity_ld_ident(ent, name);
595

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

609
	return ent_cache[kct];
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
671
672
673
674
675
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;
	}
}

676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
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;
}

709
710
711
712
713
714
715
/**
 * 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)
{
716
	ir_node *sub = NULL;
717

718
	/* Check that there is one Sub and some Cmps. */
719
720
721
	foreach_out_edge(proj, edge) {
		ir_node *user = get_edge_src_irn(edge);

722
723
724
		if (is_Sub(user)) {
			if (sub == NULL) {
				sub = user;
725
			} else {
726
				/* Two Subs will not merge */
727
728
				return false;
			}
729
730
731
732
		} else if (!is_Cmp(user)) {
			return false;
		}
	}
733

734
735
736
737
738
	if (sub == NULL) {
		/* Cmps only will not merge.
		 * (probably need to be rematerialized later anyway) */
		return false;
	}
739

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

743
744
745
		if (is_Cmp(user)) {
			bool dump;
			if (!cmp_can_use_sub_flags(user, sub, &dump)) {
746
747
748
749
750
751
752
				return false;
			}
		}
	}
	return true;
}

753
754
755
756
757
758
/**
 * 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).
 */
759
760
761
static bool ia32_use_source_address_mode(ir_node *block, ir_node *node,
                                         ir_node *other, ir_node *other2,
                                         match_flags_t flags)
762
{
763
	/* float constants are always available */
Michael Beck's avatar
Michael Beck committed
764
	if (is_Const(node)) {
765
		ir_mode *mode = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
766
		if (mode_is_float(mode)) {
767
			ir_tarval *tv = get_Const_tarval(node);
768
			if (!tarval_ieee754_can_conv_lossless(tv, ia32_mode_float64))
769
				return false;
Michael Beck's avatar
Michael Beck committed
770
771
			if (ia32_cg_config.use_sse2) {
				if (is_simple_sse_Const(node))
772
					return false;
Michael Beck's avatar
Michael Beck committed
773
774
			} else {
				if (is_simple_x87_Const(node))
775
					return false;
Michael Beck's avatar
Michael Beck committed
776
777
			}
			if (get_irn_n_edges(node) > 1)
778
779
				return false;
			return true;
780
		}
781
		return false;
782
783
	}

Michael Beck's avatar
Michael Beck committed
784
	if (!is_Proj(node))
785
786
		return false;
	ir_node *load = get_Proj_pred(node);
787
	if (!is_Load(load))
788
		return false;
789
	assert(get_Proj_num(node) == pn_Load_res);
Michael Beck's avatar
Michael Beck committed
790
	if (get_nodes_block(load) != block)
791
792
		return false;
	ir_mode *mode = get_irn_mode(node);
793
	/* we can't fold mode_E AM */
794
	if (mode == x86_mode_E)
795
		return false;
796
797
798
799
	/* 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))
800
		return false;
801
802
803
	/* 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
804
	if (be_is_transformed(node))
805
		return false;
806
807

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

811
	if (other2 != NULL && prevents_AM(block, load, other2))
812
		return false;
813

814
	return true;
815
816
817
818
}

typedef struct ia32_address_mode_t ia32_address_mode_t;
struct ia32_address_mode_t {
819
	x86_address_t   addr;
820
821
	ir_mode        *ls_mode;
	ir_node        *mem_proj;
822
	ir_node        *am_node;
823
824
825
	ia32_op_type_t  op_type;
	ir_node        *new_op1;
	ir_node        *new_op2;
Matthias Braun's avatar
Matthias Braun committed
826
	bool            pinned       : 1;
Matthias Braun's avatar
Matthias Braun committed
827
828
	unsigned        commutative  : 1;
	unsigned        ins_permuted : 1;
829
830
};

831
832
833
834
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);
835
	adjust_relocation(&addr->imm);
836
837
}

838
static void build_address_ptr(x86_address_t *addr, ir_node *ptr, ir_node *mem)
Matthias Braun's avatar
Matthias Braun committed
839
840
841
{
	/* construct load address */
	memset(addr, 0, sizeof(addr[0]));
842
	ia32_create_address_mode(addr, ptr, x86_create_am_normal);
Matthias Braun's avatar
Matthias Braun committed
843

844
845
846
847
848
849
850
	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
851
852
}

853
static void build_address(ia32_address_mode_t *am, ir_node *node,
854
                          x86_create_am_flags_t flags)
855
{
856
	x86_address_t *addr = &am->addr;
857

858
	/* floating point immediates */
859
	if (is_Const(node)) {
860
861
		ir_graph  *const irg    = get_irn_irg(node);
		ir_tarval *const tv     = get_Const_tarval(node);
862
		ir_entity *const entity = create_float_const_entity(tv, NULL);
863
		addr->base        = get_global_base(irg);
864
865
		addr->index       = noreg_GP;
		addr->mem         = nomem;
866
		addr->imm         = (x86_imm32_t) {
867
			.kind   = lconst_imm_kind,
868
869
			.entity = entity,
		};
870
		addr->variant     = X86_ADDR_BASE,
871
		adjust_relocation(&addr->imm);
872
873
		addr->tls_segment = false;
		am->ls_mode       = get_type_mode(get_entity_type(entity));
Matthias Braun's avatar
Matthias Braun committed
874
		am->pinned        = false;
875
876
877
		return;
	}

878
879
880
881
882
883
	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);
884
	am->mem_proj     = get_Proj_for_pn(load, pn_Load_M);
885
	am->am_node      = node;