ia32_transform.c 186 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
static ir_heights_t         *heights;
static x86_immediate_kind_t  lconst_imm_kind;
60
static x86_addr_variant_t    lconst_variant;
61
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
static void set_am_const_entity(ir_node *node, ir_entity *entity)
{
	ia32_attr_t *const attr = get_ia32_attr(node);
337
	attr->addr.immediate = (x86_imm32_t) {
338
		.kind   = lconst_imm_kind,
339
340
		.entity = entity,
	};
341
	attr->addr.variant = lconst_variant;
342
343
}

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

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

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

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

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

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

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

		return cnst;
	}
}

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

474
	if (!mode_needs_gp_reg(mode))
475
		panic("unexpected mode for Address");
476

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

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

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

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

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

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

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

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

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

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

574
	ir_entity *ent = ent_cache[kct];
575

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

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

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

596
			set_entity_ld_ident(ent, name);
597

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

611
	return ent_cache[kct];
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
676
677
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;
	}
}

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

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

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

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

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

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

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

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

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

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

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

816
	return true;
817
818
819
820
}

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

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

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

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

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

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