ia32_transform.c 170 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 "config.h"
13

Christian Würdig's avatar
Christian Würdig committed
14
#include <limits.h>
15
#include <stdbool.h>
Christian Würdig's avatar
Christian Würdig committed
16

Christian Würdig's avatar
Christian Würdig committed
17
#include "irargs_t.h"
18
19
20
#include "irnode_t.h"
#include "irgraph_t.h"
#include "irmode_t.h"
Christian Würdig's avatar
Christian Würdig committed
21
22
23
#include "iropt_t.h"
#include "irop_t.h"
#include "irprog_t.h"
Christian Würdig's avatar
Christian Würdig committed
24
#include "iredges_t.h"
25
26
#include "irgmod.h"
#include "ircons.h"
27
#include "irgwalk.h"
28
#include "irprintf.h"
29
#include "debug.h"
30
#include "irdom.h"
31
#include "iropt.h"
32
#include "error.h"
33
#include "array_t.h"
34
#include "heights.h"
35

36
37
38
39
40
41
#include "benode.h"
#include "besched.h"
#include "beabi.h"
#include "beutil.h"
#include "betranshlp.h"
#include "be_t.h"
Christian Würdig's avatar
Christian Würdig committed
42

43
#include "bearch_ia32_t.h"
44
#include "ia32_common_transform.h"
45
46
47
#include "ia32_nodes_attr.h"
#include "ia32_transform.h"
#include "ia32_new_nodes.h"
Christian Würdig's avatar
Christian Würdig committed
48
#include "ia32_dbg_stat.h"
49
#include "ia32_optimize.h"
50
#include "ia32_address_mode.h"
51
#include "ia32_architecture.h"
52

Christian Würdig's avatar
Christian Würdig committed
53
54
#include "gen_ia32_regalloc_if.h"

55
56
57
/* define this to construct SSE constants instead of load them */
#undef CONSTRUCT_SSE_CONST

58
#define mode_fp     (ia32_reg_classes[CLASS_ia32_fp].mode)
59
60
#define mode_xmm    (ia32_reg_classes[CLASS_ia32_xmm].mode)

61
DEBUG_ONLY(static firm_dbg_module_t *dbg;)
62

63
64
65
static ir_node *old_initial_fpcw;
static ir_node *initial_fpcw;
bool            ia32_no_pic_adjust;
66

67
68
69
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
70

71
72
73
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);
74

75
76
typedef ir_node *construct_shift_func(dbg_info *db, ir_node *block,
        ir_node *op1, ir_node *op2);
77

78
79
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);
80

81
82
typedef ir_node *construct_unop_dest_func(dbg_info *db, ir_node *block,
        ir_node *base, ir_node *index, ir_node *mem);
83

84
85
86
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
87

88
typedef ir_node *construct_unop_func(dbg_info *db, ir_node *block, ir_node *op);
89

90
static ir_node *create_immediate_or_transform(ir_node *node);
91

92
static ir_node *create_I2I_Conv(ir_mode *src_mode, ir_mode *tgt_mode,
93
94
                                dbg_info *dbgi, ir_node *block,
                                ir_node *op, ir_node *orig_node);
95

96
/* its enough to have those once */
97
98
static ir_node *nomem;
static ir_node *noreg_GP;
99

100
101
102
103
/** a list to postprocess all calls */
static ir_node **call_list;
static ir_type **call_types;

Michael Beck's avatar
Michael Beck committed
104
/** Return non-zero is a node represents the 0 constant. */
Christoph Mallon's avatar
Christoph Mallon committed
105
106
static bool is_Const_0(ir_node *node)
{
107
	return is_Const(node) && is_Const_null(node);
108
109
}

Michael Beck's avatar
Michael Beck committed
110
/** Return non-zero is a node represents the 1 constant. */
Christoph Mallon's avatar
Christoph Mallon committed
111
112
static bool is_Const_1(ir_node *node)
{
113
	return is_Const(node) && is_Const_one(node);
114
115
}

Michael Beck's avatar
Michael Beck committed
116
/** Return non-zero is a node represents the -1 constant. */
Christoph Mallon's avatar
Christoph Mallon committed
117
118
static bool is_Const_Minus_1(ir_node *node)
{
119
	return is_Const(node) && is_Const_all_one(node);
120
121
}

122
123
124
/**
 * returns true if constant can be created with a simple float command
 */
125
static bool is_simple_x87_Const(ir_node *node)
126
{
Matthias Braun's avatar
Matthias Braun committed
127
	ir_tarval *tv = get_Const_tarval(node);
128
	if (tarval_is_null(tv) || tarval_is_one(tv))
129
		return true;
130
131

	/* TODO: match all the other float constants */
132
	return false;
133
134
135
136
137
}

/**
 * returns true if constant can be created with a simple float command
 */
138
static bool is_simple_sse_Const(ir_node *node)
139
{
Matthias Braun's avatar
Matthias Braun committed
140
141
	ir_tarval *tv   = get_Const_tarval(node);
	ir_mode   *mode = get_tarval_mode(tv);
142

143
	if (mode == mode_F)
144
		return true;
145

146
147
148
149
150
	if (tarval_is_null(tv)
#ifdef CONSTRUCT_SSE_CONST
	    || tarval_is_one(tv)
#endif
	   )
151
		return true;
152
#ifdef CONSTRUCT_SSE_CONST
153
154
155
156
157
158
	if (mode == mode_D) {
		unsigned val = get_tarval_sub_bits(tv, 0) |
			(get_tarval_sub_bits(tv, 1) << 8) |
			(get_tarval_sub_bits(tv, 2) << 16) |
			(get_tarval_sub_bits(tv, 3) << 24);
		if (val == 0)
159
			/* lower 32bit are zero, really a 32bit constant */
160
			return true;
161
	}
162
#endif /* CONSTRUCT_SSE_CONST */
163
	/* TODO: match all the other float constants */
164
	return false;
165
166
}

167
168
169
170
171
172
/**
 * return NoREG or pic_base in case of PIC.
 * This is necessary as base address for newly created symbols
 */
static ir_node *get_symconst_base(void)
{
173
174
	ir_graph *irg = current_ir_graph;

175
	if (be_options.pic) {
176
177
		const arch_env_t *arch_env = be_get_irg_arch_env(irg);
		return arch_env->impl->get_pic_base(irg);
178
179
180
181
182
	}

	return noreg_GP;
}

183
184
185
/**
 * Transforms a Const.
 */
Christoph Mallon's avatar
Christoph Mallon committed
186
187
static ir_node *gen_Const(ir_node *node)
{
188
189
190
191
192
	ir_node   *old_block = get_nodes_block(node);
	ir_node   *block     = be_transform_node(old_block);
	dbg_info  *dbgi      = get_irn_dbg_info(node);
	ir_mode   *mode      = get_irn_mode(node);
	ir_tarval *tv        = get_Const_tarval(node);
193
194

	if (mode_is_float(mode)) {
195
196
197
198
199
		ir_graph         *irg      = get_irn_irg(node);
		const arch_env_t *arch_env = be_get_irg_arch_env(irg);
		ia32_isa_t       *isa      = (ia32_isa_t*) arch_env;
		ir_node          *res      = NULL;
		ir_node          *load;
200

201
		if (ia32_cg_config.use_sse2) {
202
			if (tarval_is_null(tv)) {
203
				load = new_bd_ia32_xZero(dbgi, block);
204
205
				set_ia32_ls_mode(load, mode);
				res  = load;
206
#ifdef CONSTRUCT_SSE_CONST
207
208
			} else if (tarval_is_one(tv)) {
				int     cnst  = mode == mode_F ? 26 : 55;
209
210
				ir_node *imm1 = ia32_create_Immediate(irg, NULL, 0, cnst);
				ir_node *imm2 = ia32_create_Immediate(irg, NULL, 0, 2);
211
212
				ir_node *pslld, *psrld;

213
				load = new_bd_ia32_xAllOnes(dbgi, block);
214
				set_ia32_ls_mode(load, mode);
215
				pslld = new_bd_ia32_xPslld(dbgi, block, load, imm1);
216
				set_ia32_ls_mode(pslld, mode);
217
				psrld = new_bd_ia32_xPsrld(dbgi, block, pslld, imm2);
218
219
				set_ia32_ls_mode(psrld, mode);
				res = psrld;
220
#endif /* CONSTRUCT_SSE_CONST */
221
222
223
224
225
226
			} else if (mode == mode_F) {
				/* we can place any 32bit constant by using a movd gp, sse */
				unsigned val = get_tarval_sub_bits(tv, 0) |
				               (get_tarval_sub_bits(tv, 1) << 8) |
				               (get_tarval_sub_bits(tv, 2) << 16) |
				               (get_tarval_sub_bits(tv, 3) << 24);
227
				ir_node *cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, 0, val);
228
				load = new_bd_ia32_xMovd(dbgi, block, cnst);
229
230
				set_ia32_ls_mode(load, mode);
				res = load;
231
			} else {
232
#ifdef CONSTRUCT_SSE_CONST
233
234
235
236
237
238
				if (mode == mode_D) {
					unsigned val = get_tarval_sub_bits(tv, 0) |
						(get_tarval_sub_bits(tv, 1) << 8) |
						(get_tarval_sub_bits(tv, 2) << 16) |
						(get_tarval_sub_bits(tv, 3) << 24);
					if (val == 0) {
239
						ir_node *imm32 = ia32_create_Immediate(irg, NULL, 0, 32);
240
241
242
243
244
245
246
						ir_node *cnst, *psllq;

						/* fine, lower 32bit are zero, produce 32bit value */
						val = get_tarval_sub_bits(tv, 4) |
							(get_tarval_sub_bits(tv, 5) << 8) |
							(get_tarval_sub_bits(tv, 6) << 16) |
							(get_tarval_sub_bits(tv, 7) << 24);
247
						cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, 0, val);
248
						load = new_bd_ia32_xMovd(dbgi, block, cnst);
249
						set_ia32_ls_mode(load, mode);
250
						psllq = new_bd_ia32_xPsllq(dbgi, block, load, imm32);
251
252
253
254
255
						set_ia32_ls_mode(psllq, mode);
						res = psllq;
						goto end;
					}
				}
256
#endif /* CONSTRUCT_SSE_CONST */
257
258
				ir_entity *floatent
					= ia32_create_float_const_entity(isa, tv, NULL);
259

260
261
262
				ir_node *base = get_symconst_base();
				load = new_bd_ia32_xLoad(dbgi, block, base, noreg_GP, nomem,
				                         mode);
263
264
				set_ia32_op_type(load, ia32_AddrModeS);
				set_ia32_am_sc(load, floatent);
265
				arch_add_irn_flags(load, arch_irn_flags_rematerializable);
266
				res = new_r_Proj(load, mode_xmm, pn_ia32_xLoad_res);
267
268
			}
		} else {
269
			if (tarval_is_null(tv)) {
270
				load = new_bd_ia32_fldz(dbgi, block);
271
				res  = load;
272
			} else if (tarval_is_one(tv)) {
273
				load = new_bd_ia32_fld1(dbgi, block);
274
				res  = load;
275
			} else {
276
277
				ir_entity *floatent
					= ia32_create_float_const_entity(isa, tv, NULL);
278
279
				/* create_float_const_ent is smart and sometimes creates
				   smaller entities */
280
281
282
283
				ir_mode *ls_mode  = get_type_mode(get_entity_type(floatent));
				ir_node *base     = get_symconst_base();
				load = new_bd_ia32_fld(dbgi, block, base, noreg_GP, nomem,
				                       ls_mode);
284
				set_ia32_op_type(load, ia32_AddrModeS);
285
				set_ia32_am_sc(load, floatent);
286
				arch_add_irn_flags(load, arch_irn_flags_rematerializable);
287
				res = new_r_Proj(load, mode_fp, pn_ia32_fld_res);
288
289
			}
		}
290
#ifdef CONSTRUCT_SSE_CONST
291
end:
292
#endif /* CONSTRUCT_SSE_CONST */
293
		SET_IA32_ORIG_NODE(load, node);
294
		return res;
295
	} else { /* non-float mode */
296
297
		tv = tarval_convert_to(tv, mode_Iu);

298
299
		if (tv == get_tarval_bad() || tv == get_tarval_undefined() ||
		    tv == NULL) {
300
301
			panic("couldn't convert constant tarval (%+F)", node);
		}
302
		long val = get_tarval_long(tv);
303

304
		ir_node *cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, 0, val);
305
		SET_IA32_ORIG_NODE(cnst, node);
306
307
308
309
310
311
312
313

		return cnst;
	}
}

/**
 * Transforms a SymConst.
 */
Christoph Mallon's avatar
Christoph Mallon committed
314
315
static ir_node *gen_SymConst(ir_node *node)
{
316
	ir_node  *old_block = get_nodes_block(node);
317
318
319
	ir_node  *block     = be_transform_node(old_block);
	dbg_info *dbgi      = get_irn_dbg_info(node);
	ir_mode  *mode      = get_irn_mode(node);
320
321
322
	ir_node  *cnst;

	if (mode_is_float(mode)) {
323
		if (ia32_cg_config.use_sse2)
324
			cnst = new_bd_ia32_xLoad(dbgi, block, noreg_GP, noreg_GP, nomem, mode_D);
325
		else
326
			cnst = new_bd_ia32_fld(dbgi, block, noreg_GP, noreg_GP, nomem, ia32_mode_E);
327
		set_ia32_am_sc(cnst, get_SymConst_entity(node));
328
		set_ia32_use_frame(cnst);
329
	} else {
Christoph Mallon's avatar
Christoph Mallon committed
330
		if (get_SymConst_kind(node) != symconst_addr_ent) {
331
332
			panic("backend only support symconst_addr_ent (at %+F)", node);
		}
333
		ir_entity *entity = get_SymConst_entity(node);
334
335
		if (get_entity_owner(entity) == get_tls_type()) {
			ir_node *tls_base = new_bd_ia32_LdTls(NULL, block);
336
			ir_node *lea      = new_bd_ia32_Lea(dbgi, block, tls_base, noreg_GP);
337
338
339
340
341
			set_ia32_am_sc(lea, entity);
			cnst = lea;
		} else {
			cnst = new_bd_ia32_Const(dbgi, block, entity, 0, 0, 0);
		}
342
343
	}

344
	SET_IA32_ORIG_NODE(cnst, node);
345
346
347
	return cnst;
}

348
static ir_type *make_array_type(ir_type *tp)
349
{
350
351
	unsigned alignment = get_type_alignment_bytes(tp);
	unsigned size      = get_type_size_bytes(tp);
352
	ir_type *res       = new_type_array(1, tp);
353
354
355
356
357
358
359
	set_type_alignment_bytes(res, alignment);
	set_array_bounds_int(res, 0, 0, 2);
	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
360
361
362
363
364
365
366
}

/**
 * Create a float[2] array type for the given atomic type.
 *
 * @param tp  the atomic type
 */
367
368
static ir_type *ia32_create_float_array(ir_type *tp)
{
369
370
	ir_mode *mode = get_type_mode(tp);
	ir_type *arr;
Michael Beck's avatar
Michael Beck committed
371
372

	if (mode == mode_F) {
373
		static ir_type *float_F;
Michael Beck's avatar
Michael Beck committed
374

375
376
377
		arr = float_F;
		if (arr == NULL)
			arr = float_F = make_array_type(tp);
Michael Beck's avatar
Michael Beck committed
378
	} else if (mode == mode_D) {
379
		static ir_type *float_D;
Michael Beck's avatar
Michael Beck committed
380

381
382
383
		arr = float_D;
		if (arr == NULL)
			arr = float_D = make_array_type(tp);
Michael Beck's avatar
Michael Beck committed
384
	} else {
385
		static ir_type *float_E;
Michael Beck's avatar
Michael Beck committed
386

387
388
389
		arr = float_E;
		if (arr == NULL)
			arr = float_E = make_array_type(tp);
Michael Beck's avatar
Michael Beck committed
390
391
392
393
	}
	return arr;
}

394
/* Generates an entity for a known FP const (used for FP Neg + Abs) */
Christoph Mallon's avatar
Christoph Mallon committed
395
396
ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct)
{
397
	static const struct {
398
		const char *name;
399
		const char *cnst_str;
400
		char        mode;
401
	} names [ia32_known_const_max] = {
402
403
404
405
406
		{ "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 }
407
	};
408
	static ir_entity *ent_cache[ia32_known_const_max];
409

410
	ir_entity *ent = ent_cache[kct];
411

412
413
414
415
416
417
418
	if (ent == NULL) {
		ir_graph         *irg      = current_ir_graph;
		const arch_env_t *arch_env = be_get_irg_arch_env(irg);
		ia32_isa_t       *isa      = (ia32_isa_t*) arch_env;
		const char       *cnst_str = names[kct].cnst_str;
		ident            *name     = new_id_from_str(names[kct].name);
		ir_mode          *mode;
419
420
421
		switch (names[kct].mode) {
		case 0:  mode = mode_Iu; break;
		case 1:  mode = mode_Lu; break;
422
		case 2:  mode = mode_F;  break;
423
		default: panic("internal compiler error");
424
		}
425
		ir_tarval *tv = new_tarval_from_str(cnst_str, strlen(cnst_str), mode);
426

427
		if (kct == ia32_ULLBIAS) {
428
429
			ir_type *type  = ia32_get_prim_type(mode_F);
			ir_type *atype = ia32_create_float_array(type);
430

431
			ent = new_entity(get_glob_type(), name, atype);
432

433
434
435
			set_entity_ld_ident(ent, name);
			set_entity_visibility(ent, ir_visibility_private);
			add_entity_linkage(ent, IR_LINKAGE_CONSTANT);
436

437
			ir_initializer_t *initializer = create_initializer_compound(2);
438
			set_initializer_compound_value(initializer, 0,
439
				create_initializer_tarval(get_mode_null(mode)));
440
441
442
443
			set_initializer_compound_value(initializer, 1,
				create_initializer_tarval(tv));
			set_entity_initializer(ent, initializer);
		} else {
444
			ent = ia32_create_float_const_entity(isa, tv, name);
445
		}
446
447
		/* cache the entry */
		ent_cache[kct] = ent;
448
	}
449

450
	return ent_cache[kct];
451
452
}

453
454
455
456
457
458
/**
 * 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).
 */
459
460
461
static bool ia32_use_source_address_mode(ir_node *block, ir_node *node,
                                         ir_node *other, ir_node *other2,
                                         match_flags_t flags)
462
{
463
	/* float constants are always available */
Michael Beck's avatar
Michael Beck committed
464
	if (is_Const(node)) {
465
		ir_mode *mode = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
466
		if (mode_is_float(mode)) {
467
468
			ir_tarval *tv = get_Const_tarval(node);
			if (!tarval_ieee754_can_conv_lossless(tv, mode_D))
469
				return false;
Michael Beck's avatar
Michael Beck committed
470
471
			if (ia32_cg_config.use_sse2) {
				if (is_simple_sse_Const(node))
472
					return false;
Michael Beck's avatar
Michael Beck committed
473
474
			} else {
				if (is_simple_x87_Const(node))
475
					return false;
Michael Beck's avatar
Michael Beck committed
476
477
			}
			if (get_irn_n_edges(node) > 1)
478
479
				return false;
			return true;
480
		}
481
		return false;
482
483
	}

Michael Beck's avatar
Michael Beck committed
484
	if (!is_Proj(node))
485
486
487
		return false;
	ir_node *load = get_Proj_pred(node);
	long     pn   = get_Proj_proj(node);
Michael Beck's avatar
Michael Beck committed
488
	if (!is_Load(load) || pn != pn_Load_res)
489
		return false;
Michael Beck's avatar
Michael Beck committed
490
	if (get_nodes_block(load) != block)
491
492
		return false;
	ir_mode *mode = get_irn_mode(node);
493
494
	/* we can't fold mode_E AM */
	if (mode == ia32_mode_E)
495
		return false;
496
	/* we only use address mode if we're the only user of the load */
497
	if (get_irn_n_edges(node) != (flags & match_two_users ? 2 : 1))
498
		return false;
499
500
501
	/* 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
502
	if (be_is_transformed(node))
503
		return false;
504
505

	/* don't do AM if other node inputs depend on the load (via mem-proj) */
506
	if (other != NULL && ia32_prevents_AM(block, load, other))
507
		return false;
508

509
	if (other2 != NULL && ia32_prevents_AM(block, load, other2))
510
		return false;
511

512
	return true;
513
514
515
516
517
518
519
}

typedef struct ia32_address_mode_t ia32_address_mode_t;
struct ia32_address_mode_t {
	ia32_address_t  addr;
	ir_mode        *ls_mode;
	ir_node        *mem_proj;
520
	ir_node        *am_node;
521
522
523
	ia32_op_type_t  op_type;
	ir_node        *new_op1;
	ir_node        *new_op2;
524
	op_pin_state    pinned;
Matthias Braun's avatar
Matthias Braun committed
525
526
	unsigned        commutative  : 1;
	unsigned        ins_permuted : 1;
527
528
};

Matthias Braun's avatar
Matthias Braun committed
529
530
531
532
static void build_address_ptr(ia32_address_t *addr, ir_node *ptr, ir_node *mem)
{
	/* construct load address */
	memset(addr, 0, sizeof(addr[0]));
533
	ia32_create_address_mode(addr, ptr, ia32_create_am_normal);
Matthias Braun's avatar
Matthias Braun committed
534

535
536
	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
537
538
539
	addr->mem   = be_transform_node(mem);
}

540
541
static void build_address(ia32_address_mode_t *am, ir_node *node,
                          ia32_create_am_flags_t flags)
542
{
543
	ia32_address_t *addr = &am->addr;
544

545
	/* floating point immediates */
546
	if (is_Const(node)) {
547
548
549
550
551
		ir_graph         *irg      = get_irn_irg(node);
		const arch_env_t *arch_env = be_get_irg_arch_env(irg);
		ia32_isa_t       *isa      = (ia32_isa_t*) arch_env;
		ir_tarval        *tv       = get_Const_tarval(node);
		ir_entity *entity  = ia32_create_float_const_entity(isa, tv, NULL);
552
		addr->base         = get_symconst_base();
553
554
		addr->index        = noreg_GP;
		addr->mem          = nomem;
555
		addr->symconst_ent = entity;
556
		addr->tls_segment  = false;
557
		addr->use_frame    = 1;
558
		am->ls_mode        = get_type_mode(get_entity_type(entity));
559
		am->pinned         = op_pin_state_floats;
560
561
562
		return;
	}

563
564
565
566
567
568
569
570
	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);
	am->mem_proj     = be_get_Proj_for_pn(load, pn_Load_M);
	am->am_node      = node;
571
572

	/* construct load address */
573
	ia32_create_address_mode(addr, ptr, flags);
574

575
576
	addr->base  = addr->base  ? be_transform_node(addr->base)  : noreg_GP;
	addr->index = addr->index ? be_transform_node(addr->index) : noreg_GP;
577
	addr->mem   = new_mem;
578
579
}

580
static void set_address(ir_node *node, const ia32_address_t *addr)
581
582
583
584
{
	set_ia32_am_scale(node, addr->scale);
	set_ia32_am_sc(node, addr->symconst_ent);
	set_ia32_am_offs_int(node, addr->offset);
585
	set_ia32_am_tls_segment(node, addr->tls_segment);
Christoph Mallon's avatar
Christoph Mallon committed
586
	if (addr->symconst_sign)
587
		set_ia32_am_sc_sign(node);
Christoph Mallon's avatar
Christoph Mallon committed
588
	if (addr->use_frame)
589
590
		set_ia32_use_frame(node);
	set_ia32_frame_ent(node, addr->frame_entity);
591
592
}

Michael Beck's avatar
Michael Beck committed
593
594
595
/**
 * Apply attributes of a given address mode to a node.
 */
596
static void set_am_attributes(ir_node *node, const ia32_address_mode_t *am)
597
598
{
	set_address(node, &am->addr);
599

600
601
	set_ia32_op_type(node, am->op_type);
	set_ia32_ls_mode(node, am->ls_mode);
Michael Beck's avatar
Michael Beck committed
602
	if (am->pinned == op_pin_state_pinned) {
603
604
605
		/* beware: some nodes are already pinned and did not allow to change the state */
		if (get_irn_pinned(node) != op_pin_state_pinned)
			set_irn_pinned(node, op_pin_state_pinned);
606
	}
Michael Beck's avatar
Michael Beck committed
607
	if (am->commutative)
608
609
		set_ia32_commutative(node);
}
610

611
/**
yb9976's avatar
yb9976 committed
612
 * Check, if a given node is a Down-Conv, i.e. a integer Conv
613
614
615
616
617
618
 * from a mode with a mode with more bits to a mode with lesser bits.
 * Moreover, we return only true if the node has not more than 1 user.
 *
 * @param node   the node
 * @return non-zero if node is a Down-Conv
 */
619
static bool is_downconv(const ir_node *node)
620
{
Christoph Mallon's avatar
Christoph Mallon committed
621
	if (!is_Conv(node))
622
		return false;
623

624
625
	ir_mode *src_mode  = get_irn_mode(get_Conv_op(node));
	ir_mode *dest_mode = get_irn_mode(node);
626
627
628
629
	return
		ia32_mode_needs_gp_reg(src_mode)  &&
		ia32_mode_needs_gp_reg(dest_mode) &&
		get_mode_size_bits(dest_mode) <= get_mode_size_bits(src_mode);
630
631
}

632
/** Skip all Down-Conv's on a given node and return the resulting node. */
Christoph Mallon's avatar
Christoph Mallon committed
633
634
ir_node *ia32_skip_downconv(ir_node *node)
{
635
636
637
638
639
640
641
	while (is_downconv(node)) {
		/* we only want to skip the conv when we're the only user
		 * (because this test is used in the context of address-mode selection
		 *  and we don't want to use address mode for multiple users) */
		if (get_irn_n_edges(node) > 1)
			break;

642
		node = get_Conv_op(node);
643
	}
644
645
646
647

	return node;
}

648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
static bool is_float_downconv(const ir_node *node)
{
	if (!is_Conv(node))
		return false;
	ir_node *pred      = get_Conv_op(node);
	ir_mode *pred_mode = get_irn_mode(pred);
	ir_mode *mode      = get_irn_mode(node);
	return mode_is_float(pred_mode)
	    && get_mode_size_bits(mode) <= get_mode_size_bits(pred_mode);
}

static ir_node *ia32_skip_float_downconv(ir_node *node)
{
	while (is_float_downconv(node)) {
		node = get_Conv_op(node);
	}
	return node;
}

667
668
669
static bool is_sameconv(ir_node *node)
{
	if (!is_Conv(node))
670
		return false;
671

672
673
674
675
	/* we only want to skip the conv when we're the only user
	 * (because this test is used in the context of address-mode selection
	 *  and we don't want to use address mode for multiple users) */
	if (get_irn_n_edges(node) > 1)
676
		return false;
677

678
679
	ir_mode *src_mode  = get_irn_mode(get_Conv_op(node));
	ir_mode *dest_mode = get_irn_mode(node);
680
681
682
683
684
685
686
687
688
	return
		ia32_mode_needs_gp_reg(src_mode)  &&
		ia32_mode_needs_gp_reg(dest_mode) &&
		get_mode_size_bits(dest_mode) == get_mode_size_bits(src_mode);
}

/** Skip all signedness convs */
static ir_node *ia32_skip_sameconv(ir_node *node)
{
689
	while (is_sameconv(node)) {
690
		node = get_Conv_op(node);
691
	}
692
693
694
695

	return node;
}

696
static ir_node *transform_sext(ir_node *node, ir_node *orig_node)
697
{
698
699
700
701
702
	ir_mode  *mode  = get_irn_mode(node);
	ir_node  *block = get_nodes_block(node);
	dbg_info *dbgi  = get_irn_dbg_info(node);
	return create_I2I_Conv(mode, mode_Is, dbgi, block, node, orig_node);
}
703

704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
static ir_node *transform_zext(ir_node *node, ir_node *orig_node)
{
	ir_mode  *mode  = get_irn_mode(node);
	ir_node  *block = get_nodes_block(node);
	dbg_info *dbgi  = get_irn_dbg_info(node);
	/* normalize to an unsigned mode */
	switch (get_mode_size_bits(mode)) {
	case 8:  mode = mode_Bu; break;
	case 16: mode = mode_Hu; break;
	default:
		panic("ia32: invalid mode in zest: %+F", node);
	}
	return create_I2I_Conv(mode, mode_Iu, dbgi, block, node, orig_node);
}

static ir_node *transform_upconv(ir_node *node, ir_node *orig_node)
{
	ir_mode *mode = get_irn_mode(node);
Christoph Mallon's avatar
Christoph Mallon committed
722
	if (mode_is_signed(mode)) {
723
		return transform_sext(node, orig_node);
724
	} else {
725
		return transform_zext(node, orig_node);
726
727
	}
}
728

729
730
731
732
733
734
735
736
737
738
739
static ir_node *get_noreg(ir_mode *const mode)
{
	if (!mode_is_float(mode)) {
		return noreg_GP;
	} else if (ia32_cg_config.use_sse2) {
		return ia32_new_NoReg_xmm(current_ir_graph);
	} else {
		return ia32_new_NoReg_fp(current_ir_graph);
	}
}

740
741
742
743
744
745
746
747
748
749
750
/**
 * matches operands of a node into ia32 addressing/operand modes. This covers
 * usage of source address mode, immediates, operations with non 32-bit modes,
 * ...
 * The resulting data is filled into the @p am struct. block is the block
 * of the node whose arguments are matched. op1, op2 are the first and second
 * input that are matched (op1 may be NULL). other_op is another unrelated
 * input that is not matched! but which is needed sometimes to check if AM
 * for op1/op2 is legal.
 * @p flags describes the supported modes of the operation in detail.
 */
751
static void match_arguments(ia32_address_mode_t *am, ir_node *block,
752
753
                            ir_node *op1, ir_node *op2, ir_node *other_op,
                            match_flags_t flags)
754
755
756
{
	memset(am, 0, sizeof(am[0]));

757
758
759
760
	bool commutative           = (flags & match_commutative) != 0;
	bool use_am_and_immediates = (flags & match_am_and_immediates) != 0;
	bool use_am                = (flags & match_am) != 0;
	bool use_immediate         = (flags & match_immediate) != 0;
761
	assert(!use_am_and_immediates || use_immediate);
762
763
764

	assert(op2 != NULL);
	assert(!commutative || op1 != NULL);
765
766
	assert(use_am || !(flags & match_8bit_am));
	assert(use_am || !(flags & match_16bit_am));
767

768
769
	ir_mode *mode      = get_irn_mode(op2);
	int      mode_bits = get_mode_size_bits(mode);
770
	if ((mode_bits ==  8 && !(flags & match_8bit_am)) ||
771
	    (mode_bits == 16 && !(flags & match_16bit_am))) {
772
		use_am = false;
773
	}
774

775
776
	/* we can simply skip downconvs for mode neutral nodes: the upper bits
	 * can be random for these operations */
777
	if (flags & match_mode_neutral) {
778
		op2 = ia32_skip_downconv(op2);
779
		if (op1 != NULL) {
780
781
			op1 = ia32_skip_downconv(op1);
		}
782
783
784
785
786
	} else {
		op2 = ia32_skip_sameconv(op2);
		if (op1 != NULL) {
			op1 = ia32_skip_sameconv(op1);
		}
787
788
	}

789
790
	/* match immediates. firm nodes are normalized: constants are always on the
	 * op2 input */
791
	ir_node *new_op2 = NULL;
792
	if (!(flags & match_try_am) && use_immediate) {
793
		new_op2 = ia32_try_create_Immediate(op2, 'i');
794
	}
795

796
	ir_node *new_op1;
797
	if (new_op2 == NULL &&
798
	    use_am && ia32_use_source_address_mode(block, op2, op1, other_op, flags)) {
799
		build_address(am, op2, ia32_create_am_normal);
800
		new_op1     = (op1 == NULL ? NULL : be_transform_node(op1));
801
		new_op2     = get_noreg(mode);
802
		am->op_type = ia32_AddrModeS;
803
804
	} else if (commutative && (new_op2 == NULL || use_am_and_immediates) &&
		       use_am &&
805
		       ia32_use_source_address_mode(block, op1, op2, other_op, flags)) {
806
		build_address(am, op1, ia32_create_am_normal);
807

808
		ir_node *const noreg = get_noreg(mode);
Michael Beck's avatar
Michael Beck committed
809
		if (new_op2 != NULL) {
810
			new_op1 = noreg;
811
812
		} else {
			new_op1 = be_transform_node(op2);
813
			new_op2 = noreg;
814
			am->ins_permuted = true;
815
816
		}
		am->op_type = ia32_AddrModeS;
817
	} else {
Christoph Mallon's avatar
Christoph Mallon committed
818
819
		am->op_type = ia32_Normal;

Michael Beck's avatar
Michael Beck committed
820
		if (flags & match_try_am) {
821
822
823
824
825
			am->new_op1 = NULL;
			am->new_op2 = NULL;
			return;
		}

826
		mode = get_irn_mode(op2);
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
		if (get_mode_size_bits(mode) != 32
			&& (flags & (match_mode_neutral | match_upconv | match_zero_ext))) {
			if (flags & match_upconv) {
				new_op1 = (op1 == NULL ? NULL : transform_upconv(op1, op1));
				if (new_op2 == NULL)
					new_op2 = transform_upconv(op2, op2);
			} else if (flags & match_zero_ext) {
				new_op1 = (op1 == NULL ? NULL : transform_zext(op1, op1));
				if (new_op2 == NULL)
					new_op2 = transform_zext(op2, op2);
			} else {
				new_op1 = (op1 == NULL ? NULL : be_transform_node(op1));
				if (new_op2 == NULL)
					new_op2 = be_transform_node(op2);
				assert(flags & match_mode_neutral);
			}
			mode = mode_Iu;
844
845
846
847
848
		} else {
			new_op1 = (op1 == NULL ? NULL : be_transform_node(op1));
			if (new_op2 == NULL)
				new_op2 = be_transform_node(op2);
		}
849
		am->ls_mode = mode;