ia32_transform.c 184 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
#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
61
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
	['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 },
96
	['e'] = { MATCH_IMM, GP, 0 },
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
	['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
115
	// logic at play not everything is documented in the manual. In the gcc
116
117
118
119
120
121
	// 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

122
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,
        ir_node *op2);
Christian Würdig's avatar
Christian Würdig committed
125

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,
        ir_node *flags);
129

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

133
134
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);
135

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

139
140
141
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
142

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	ir_graph *const irg = get_irn_irg(node);
285
	return ia32_create_Immediate_full(irg, &immediate);
286
287
288
289
}

static ir_type *get_prim_type(const ir_mode *mode)
{
290
291
	if (mode == x86_mode_E) {
		return x86_type_E;
292
293
294
295
296
	} else {
		return get_type_for_mode(mode);
	}
}

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

315
	ir_entity *res = pmap_get(ir_entity, ia32_tv_ent, tv);
316
317
318
319
320
	if (!res) {
		if (!name)
			name = id_unique("C%u");

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

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

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

334
335
336
337
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) {
338
		.kind   = lconst_imm_kind,
339
340
341
342
		.entity = entity,
	};
}

343
344
345
/**
 * Transforms a Const.
 */
Christoph Mallon's avatar
Christoph Mallon committed
346
347
static ir_node *gen_Const(ir_node *node)
{
348
349
350
351
	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);
352
353

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

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

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

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

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

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

		return cnst;
	}
}

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

466
	if (!mode_needs_gp_reg(mode))
467
		panic("unexpected mode for Address");
468

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

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

Matthias Braun's avatar
Matthias Braun committed
490
491
492
493
494
495
496
497
498
499
500
501
502
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;
}

503
static ir_type *make_array_type(ir_type *tp)
504
{
505
506
	unsigned alignment = get_type_alignment_bytes(tp);
	unsigned size      = get_type_size_bytes(tp);
507
	ir_type *res       = new_type_array(tp);
508
	set_type_alignment_bytes(res, alignment);
509
	set_array_size_int(res, 2);
510
511
512
513
514
	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
515
516
517
518
519
520
521
}

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

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

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

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

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

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

565
	ir_entity *ent = ent_cache[kct];
566

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

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

583
584
585
			ent = new_global_entity(get_glob_type(), name, atype,
			                        ir_visibility_private,
			                        IR_LINKAGE_CONSTANT|IR_LINKAGE_NO_IDENTITY);
586

587
			set_entity_ld_ident(ent, name);
588

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

602
	return ent_cache[kct];
603
604
}

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
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;
	}
}

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
694
695
696
697
698
699
700
701
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;
}

702
703
704
705
706
707
708
/**
 * 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)
{
709
	ir_node *sub = NULL;
710

711
	/* Check that there is one Sub and some Cmps. */
712
713
714
	foreach_out_edge(proj, edge) {
		ir_node *user = get_edge_src_irn(edge);

715
716
717
		if (is_Sub(user)) {
			if (sub == NULL) {
				sub = user;
718
			} else {
719
				/* Two Subs will not merge */
720
721
				return false;
			}
722
723
724
725
		} else if (!is_Cmp(user)) {
			return false;
		}
	}
726

727
728
729
730
731
	if (sub == NULL) {
		/* Cmps only will not merge.
		 * (probably need to be rematerialized later anyway) */
		return false;
	}
732

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

736
737
738
		if (is_Cmp(user)) {
			bool dump;
			if (!cmp_can_use_sub_flags(user, sub, &dump)) {
739
740
741
742
743
744
745
				return false;
			}
		}
	}
	return true;
}

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

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

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

804
	if (other2 != NULL && prevents_AM(block, load, other2))
805
		return false;
806

807
	return true;
808
809
810
811
}

typedef struct ia32_address_mode_t ia32_address_mode_t;
struct ia32_address_mode_t {
812
	x86_address_t   addr;
813
814
	ir_mode        *ls_mode;
	ir_node        *mem_proj;
815
	ir_node        *am_node;
816
817
818
	ia32_op_type_t  op_type;
	ir_node        *new_op1;
	ir_node        *new_op2;
Matthias Braun's avatar
Matthias Braun committed
819
	bool            pinned       : 1;
Matthias Braun's avatar
Matthias Braun committed
820
821
	unsigned        commutative  : 1;
	unsigned        ins_permuted : 1;
822
823
};

824
825
826
827
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);
828
	adjust_relocation(&addr->imm);
829
830
}

831
static void build_address_ptr(x86_address_t *addr, ir_node *ptr, ir_node *mem)
Matthias Braun's avatar
Matthias Braun committed
832
833
834
{
	/* construct load address */
	memset(addr, 0, sizeof(addr[0]));
835
	ia32_create_address_mode(addr, ptr, x86_create_am_normal);
Matthias Braun's avatar
Matthias Braun committed
836

837
838
	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
839
840
841
	addr->mem   = be_transform_node(mem);
}

842
static void build_address(ia32_address_mode_t *am, ir_node *node,
843
                          x86_create_am_flags_t flags)
844
{
845
	x86_address_t *addr = &am->addr;
846

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

866
867
868
869
870
871
	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);
872
	am->mem_proj     = get_Proj_for_pn(load, pn_Load_M);
873
	am->am_node      = node;
874
875

	/* construct load address */
876
	ia32_create_address_mode(addr, ptr, flags);
877

878
879
	addr->base  = addr->base  ? be_transform_node(addr->base)  : noreg_GP;
	addr->index = addr->index ? be_transform_node(addr->index) : noreg_GP;
880
	addr->mem   = new_mem;
881
882
}

883
static void set_address(ir_node *node, const x86_address_t *addr)
884
{
885
886
	ia32_attr_t *const attr = get_ia32_attr(node);
	attr->am_imm = addr->imm;