ia32_transform.c 183 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
Christian Würdig's avatar
Christian Würdig committed
4
5
 */

Christian Würdig's avatar
Christian Würdig committed
6
/**
Christian Würdig's avatar
Christian Würdig committed
7
 * @file
8
9
 * @brief       This file implements the IR transformation from firm into
 *              ia32-Firm.
Christian Würdig's avatar
Christian Würdig committed
10
 * @author      Christian Wuerdig, Matthias Braun
Christian Würdig's avatar
Christian Würdig committed
11
 */
Christian Würdig's avatar
Christian Würdig committed
12
#include <limits.h>
13
#include <stdbool.h>
Christian Würdig's avatar
Christian Würdig committed
14

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

35
36
37
38
39
40
#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
41

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

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

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

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

60
DEBUG_ONLY(static firm_dbg_module_t *dbg;)
61

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

142
	if (mode == ia32_mode_float32)
143
		return true;
144

145
146
147
148
149
	if (tarval_is_null(tv)
#ifdef CONSTRUCT_SSE_CONST
	    || tarval_is_one(tv)
#endif
	   )
150
		return true;
151
#ifdef CONSTRUCT_SSE_CONST
152
	if (mode == ia32_mode_float64) {
153
154
155
156
157
		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)
158
			/* lower 32bit are zero, really a 32bit constant */
159
			return true;
160
	}
161
#endif /* CONSTRUCT_SSE_CONST */
162
	/* TODO: match all the other float constants */
163
	return false;
164
165
}

166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
ir_node *ia32_get_pic_base(ir_graph *irg)
{
	ia32_irg_data_t *irg_data = ia32_get_irg_data(irg);
	ir_node         *block;
	ir_node         *get_eip = irg_data->get_eip;
	if (get_eip != NULL)
		return get_eip;

	block             = get_irg_start_block(irg);
	get_eip           = new_bd_ia32_GetEIP(NULL, block);
	irg_data->get_eip = get_eip;

	return get_eip;
}

181
182
183
184
/**
 * return NoREG or pic_base in case of PIC.
 * This is necessary as base address for newly created symbols
 */
185
static ir_node *get_global_base(ir_graph *const irg)
186
{
187
	if (be_options.pic) {
188
		return ia32_get_pic_base(irg);
189
190
191
192
193
	}

	return noreg_GP;
}

194
195
196
/**
 * Transforms a Const.
 */
Christoph Mallon's avatar
Christoph Mallon committed
197
198
static ir_node *gen_Const(ir_node *node)
{
199
200
201
202
203
	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);
204
205

	if (mode_is_float(mode)) {
206
207
208
209
210
		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;
211

212
		if (ia32_cg_config.use_sse2) {
213
			if (tarval_is_null(tv)) {
214
				load = new_bd_ia32_xZero(dbgi, block);
215
216
				set_ia32_ls_mode(load, mode);
				res  = load;
217
#ifdef CONSTRUCT_SSE_CONST
218
			} else if (tarval_is_one(tv)) {
219
				int     cnst  = mode == ia32_mode_float32 ? 26 : 55;
220
221
				ir_node *imm1 = ia32_create_Immediate(irg, NULL, 0, cnst);
				ir_node *imm2 = ia32_create_Immediate(irg, NULL, 0, 2);
222
223
				ir_node *pslld, *psrld;

224
				load = new_bd_ia32_xAllOnes(dbgi, block);
225
				set_ia32_ls_mode(load, mode);
226
				pslld = new_bd_ia32_xPslld(dbgi, block, load, imm1);
227
				set_ia32_ls_mode(pslld, mode);
228
				psrld = new_bd_ia32_xPsrld(dbgi, block, pslld, imm2);
229
230
				set_ia32_ls_mode(psrld, mode);
				res = psrld;
231
#endif /* CONSTRUCT_SSE_CONST */
232
			} else if (mode == ia32_mode_float32) {
233
234
235
236
237
				/* 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);
238
				ir_node *cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, val);
239
				load = new_bd_ia32_xMovd(dbgi, block, cnst);
240
241
				set_ia32_ls_mode(load, mode);
				res = load;
242
			} else {
243
#ifdef CONSTRUCT_SSE_CONST
244
				if (mode == ia32_mode_float64) {
245
246
247
248
249
					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) {
250
						ir_node *imm32 = ia32_create_Immediate(irg, NULL, 0, 32);
251
252
253
254
255
256
257
						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);
258
						cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, 0, val);
259
						load = new_bd_ia32_xMovd(dbgi, block, cnst);
260
						set_ia32_ls_mode(load, mode);
261
						psllq = new_bd_ia32_xPsllq(dbgi, block, load, imm32);
262
263
264
265
266
						set_ia32_ls_mode(psllq, mode);
						res = psllq;
						goto end;
					}
				}
267
#endif /* CONSTRUCT_SSE_CONST */
268
269
				ir_entity *floatent
					= ia32_create_float_const_entity(isa, tv, NULL);
270

271
				ir_node *base = get_global_base(irg);
272
273
				load = new_bd_ia32_xLoad(dbgi, block, base, noreg_GP, nomem,
				                         mode);
274
				set_irn_pinned(load, op_pin_state_floats);
275
				set_ia32_op_type(load, ia32_AddrModeS);
276
				set_ia32_am_ent(load, floatent);
277
				arch_add_irn_flags(load, arch_irn_flag_rematerializable);
278
				res = new_r_Proj(load, mode_xmm, pn_ia32_xLoad_res);
279
280
			}
		} else {
281
			if (tarval_is_null(tv)) {
282
				load = new_bd_ia32_fldz(dbgi, block);
283
				res  = load;
284
			} else if (tarval_is_one(tv)) {
285
				load = new_bd_ia32_fld1(dbgi, block);
286
				res  = load;
287
			} else {
288
289
				ir_entity *floatent
					= ia32_create_float_const_entity(isa, tv, NULL);
290
291
				/* create_float_const_ent is smart and sometimes creates
				   smaller entities */
292
				ir_mode *ls_mode  = get_type_mode(get_entity_type(floatent));
293
				ir_node *base     = get_global_base(irg);
294
295
				load = new_bd_ia32_fld(dbgi, block, base, noreg_GP, nomem,
				                       ls_mode);
296
				set_irn_pinned(load, op_pin_state_floats);
297
				set_ia32_op_type(load, ia32_AddrModeS);
298
				set_ia32_am_ent(load, floatent);
299
				arch_add_irn_flags(load, arch_irn_flag_rematerializable);
300
				res = new_r_Proj(load, mode_fp, pn_ia32_fld_res);
301
302
			}
		}
303
#ifdef CONSTRUCT_SSE_CONST
304
end:
305
#endif /* CONSTRUCT_SSE_CONST */
306
		SET_IA32_ORIG_NODE(load, node);
307
		return res;
308
	} else { /* non-float mode */
309
		tv = tarval_convert_to(tv, ia32_mode_gp);
310

311
		if (tv == get_tarval_bad() || tv == get_tarval_unknown() ||
312
		    tv == NULL) {
313
314
			panic("couldn't convert constant tarval (%+F)", node);
		}
315
		long val = get_tarval_long(tv);
316

317
		ir_node *cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, val);
318
		SET_IA32_ORIG_NODE(cnst, node);
319
320
321
322
323
324

		return cnst;
	}
}

/**
325
 * Transforms an Address.
326
 */
327
static ir_node *gen_Address(ir_node *node)
Christoph Mallon's avatar
Christoph Mallon committed
328
{
329
	ir_node  *old_block = get_nodes_block(node);
330
331
332
	ir_node  *block     = be_transform_node(old_block);
	dbg_info *dbgi      = get_irn_dbg_info(node);
	ir_mode  *mode      = get_irn_mode(node);
333

334
	if (!ia32_mode_needs_gp_reg(mode))
335
		panic("unexpected mode for Address");
336

337
	ir_entity *entity = get_Address_entity(node);
338
	ir_node   *cnst;
339
	if (is_tls_entity(entity)) {
340
341
		ir_node *tls_base = new_bd_ia32_LdTls(NULL, block);
		ir_node *lea      = new_bd_ia32_Lea(dbgi, block, tls_base, noreg_GP);
342
		set_ia32_am_ent(lea, entity);
343
		cnst = lea;
344
	} else {
345
		cnst = new_bd_ia32_Const(dbgi, block, entity, 0, 0);
346
	}
347
	SET_IA32_ORIG_NODE(cnst, node);
348
349
350
	return cnst;
}

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

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

375
	if (mode == ia32_mode_float32) {
376
		static ir_type *float_F;
Michael Beck's avatar
Michael Beck committed
377

378
379
380
		arr = float_F;
		if (arr == NULL)
			arr = float_F = make_array_type(tp);
381
	} else if (mode == ia32_mode_float64) {
382
		static ir_type *float_D;
Michael Beck's avatar
Michael Beck committed
383

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

390
391
392
		arr = float_E;
		if (arr == NULL)
			arr = float_E = make_array_type(tp);
Michael Beck's avatar
Michael Beck committed
393
394
395
396
	}
	return arr;
}

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

413
	ir_entity *ent = ent_cache[kct];
414

415
416
417
418
419
420
	if (ent == NULL) {
		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;
421
		switch (names[kct].mode) {
422
		case 0:  mode = ia32_mode_gp; break;
423
		case 1:  mode = mode_Lu; break;
424
		case 2:  mode = ia32_mode_float32;  break;
425
		default: panic("internal compiler error");
426
		}
427
		ir_tarval *tv = new_tarval_from_str(cnst_str, strlen(cnst_str), mode);
428

429
		if (kct == ia32_ULLBIAS) {
430
			ir_type *type  = ia32_get_prim_type(ia32_mode_float32);
431
			ir_type *atype = ia32_create_float_array(type);
432

433
			ent = new_entity(get_glob_type(), name, atype);
434

435
436
437
			set_entity_ld_ident(ent, name);
			set_entity_visibility(ent, ir_visibility_private);
			add_entity_linkage(ent, IR_LINKAGE_CONSTANT);
438

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

452
	return ent_cache[kct];
453
454
}

455
456
457
458
459
460
461
/**
 * 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)
{
462
463
	ir_node *first     = NULL;
	ir_node *block     = NULL;
464
465
466
467
468
469
470
	ir_node *left      = NULL;
	ir_node *right     = NULL;
	bool     found_sub = false;

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

471
		if (first == NULL) {
472
473
474
			if (is_Cmp(user) || is_Sub(user)) {
				// Take the first user as a sample to compare
				// the next ones to.
475
				first     = user;
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
				block     = get_nodes_block(user);
				left      = get_binop_left(user);
				right     = get_binop_right(user);
				found_sub = is_Sub(user);
			} else {
				return false;
			}
		} else {
			if (get_nodes_block(user) != block) {
				return false;
			}

			if (is_Cmp(user) || is_Sub(user)) {
				ir_node *user_left  = get_binop_left(user);
				ir_node *user_right = get_binop_right(user);

				if (found_sub && is_Sub(user)) {
					// Two subs will not be merged
					return false;
				}
496
497
498
499
500
501
				found_sub |= is_Sub(user);

				if ((is_Sub(user) || is_Sub(first)) &&
				    user_left == right && user_right == left) {
					continue;
				}
502
503
504
505
506
507
508
509
510
511
512
				if (user_left != left || user_right != right) {
					return false;
				}
			} else {
				return false;
			}
		}
	}
	return true;
}

513
514
515
516
517
518
/**
 * 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).
 */
519
520
521
static bool ia32_use_source_address_mode(ir_node *block, ir_node *node,
                                         ir_node *other, ir_node *other2,
                                         match_flags_t flags)
522
{
523
	/* float constants are always available */
Michael Beck's avatar
Michael Beck committed
524
	if (is_Const(node)) {
525
		ir_mode *mode = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
526
		if (mode_is_float(mode)) {
527
			ir_tarval *tv = get_Const_tarval(node);
528
			if (!tarval_ieee754_can_conv_lossless(tv, ia32_mode_float64))
529
				return false;
Michael Beck's avatar
Michael Beck committed
530
531
			if (ia32_cg_config.use_sse2) {
				if (is_simple_sse_Const(node))
532
					return false;
Michael Beck's avatar
Michael Beck committed
533
534
			} else {
				if (is_simple_x87_Const(node))
535
					return false;
Michael Beck's avatar
Michael Beck committed
536
537
			}
			if (get_irn_n_edges(node) > 1)
538
539
				return false;
			return true;
540
		}
541
		return false;
542
543
	}

Michael Beck's avatar
Michael Beck committed
544
	if (!is_Proj(node))
545
546
		return false;
	ir_node *load = get_Proj_pred(node);
547
	if (!is_Load(load))
548
		return false;
549
	assert(get_Proj_proj(node) == pn_Load_res);
Michael Beck's avatar
Michael Beck committed
550
	if (get_nodes_block(load) != block)
551
552
		return false;
	ir_mode *mode = get_irn_mode(node);
553
554
	/* we can't fold mode_E AM */
	if (mode == ia32_mode_E)
555
		return false;
556
557
558
559
	/* 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))
560
		return false;
561
562
563
	/* 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
564
	if (be_is_transformed(node))
565
		return false;
566
567

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

571
	if (other2 != NULL && ia32_prevents_AM(block, load, other2))
572
		return false;
573

574
	return true;
575
576
577
578
}

typedef struct ia32_address_mode_t ia32_address_mode_t;
struct ia32_address_mode_t {
579
	x86_address_t   addr;
580
581
	ir_mode        *ls_mode;
	ir_node        *mem_proj;
582
	ir_node        *am_node;
583
584
585
	ia32_op_type_t  op_type;
	ir_node        *new_op1;
	ir_node        *new_op2;
586
	op_pin_state    pinned;
Matthias Braun's avatar
Matthias Braun committed
587
588
	unsigned        commutative  : 1;
	unsigned        ins_permuted : 1;
589
590
};

591
static void build_address_ptr(x86_address_t *addr, ir_node *ptr, ir_node *mem)
Matthias Braun's avatar
Matthias Braun committed
592
593
594
{
	/* construct load address */
	memset(addr, 0, sizeof(addr[0]));
595
	x86_create_address_mode(addr, ptr, x86_create_am_normal);
Matthias Braun's avatar
Matthias Braun committed
596

597
598
	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
599
600
601
	addr->mem   = be_transform_node(mem);
}

602
static void build_address(ia32_address_mode_t *am, ir_node *node,
603
                          x86_create_am_flags_t flags)
604
{
605
	x86_address_t *addr = &am->addr;
606

607
	/* floating point immediates */
608
	if (is_Const(node)) {
609
610
611
612
		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);
613
		ir_entity *entity = ia32_create_float_const_entity(isa, tv, NULL);
614
		addr->base        = get_global_base(irg);
615
616
617
618
		addr->index       = noreg_GP;
		addr->mem         = nomem;
		addr->entity      = entity;
		addr->tls_segment = false;
619
		addr->use_frame   = false;
620
621
		am->ls_mode       = get_type_mode(get_entity_type(entity));
		am->pinned        = op_pin_state_floats;
622
623
624
		return;
	}

625
626
627
628
629
630
631
632
	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;
633
634

	/* construct load address */
635
	x86_create_address_mode(addr, ptr, flags);
636

637
638
	addr->base  = addr->base  ? be_transform_node(addr->base)  : noreg_GP;
	addr->index = addr->index ? be_transform_node(addr->index) : noreg_GP;
639
	addr->mem   = new_mem;
640
641
}

642
static void set_address(ir_node *node, const x86_address_t *addr)
643
644
{
	set_ia32_am_scale(node, addr->scale);
645
	set_ia32_am_ent(node, addr->entity);
646
	set_ia32_am_offs_int(node, addr->offset);
647
	set_ia32_am_tls_segment(node, addr->tls_segment);
648
	set_ia32_frame_ent(node, addr->frame_entity);
Christoph Mallon's avatar
Christoph Mallon committed
649
	if (addr->use_frame)
650
		set_ia32_use_frame(node);
651
652
}

Michael Beck's avatar
Michael Beck committed
653
654
655
/**
 * Apply attributes of a given address mode to a node.
 */
656
static void set_am_attributes(ir_node *node, const ia32_address_mode_t *am)
657
658
{
	set_address(node, &am->addr);
659

660
661
	set_ia32_op_type(node, am->op_type);
	set_ia32_ls_mode(node, am->ls_mode);
Michael Beck's avatar
Michael Beck committed
662
	if (am->pinned == op_pin_state_pinned) {
663
664
665
		/* 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);
666
	}
Michael Beck's avatar
Michael Beck committed
667
	if (am->commutative)
668
669
		set_ia32_commutative(node);
}
670

671
/**
yb9976's avatar
yb9976 committed
672
673
 * Check, if a given node is a Down-Conv, i.e. an integer Conv
 * from a mode with more bits to a mode with fewer bits.
674
675
676
677
 *
 * @param node   the node
 * @return non-zero if node is a Down-Conv
 */
678
static bool is_downconv(const ir_node *node)
679
{
Christoph Mallon's avatar
Christoph Mallon committed
680
	if (!is_Conv(node))
681
		return false;
682

683
684
	ir_mode *src_mode  = get_irn_mode(get_Conv_op(node));
	ir_mode *dest_mode = get_irn_mode(node);
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);
689
690
}

yb9976's avatar
yb9976 committed
691
692
693
694
695
/**
 * Skip all Down-Conv's on a given node and return the resulting node.
 *
 * Moreover, we only skip Conv nodes that has at most one user.
 */
Christoph Mallon's avatar
Christoph Mallon committed
696
697
ir_node *ia32_skip_downconv(ir_node *node)
{
698
699
700
701
702
703
704
	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;

705
		node = get_Conv_op(node);
706
	}
707
708
709
710

	return node;
}

711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
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;
}

730
731
732
static bool is_sameconv(ir_node *node)
{
	if (!is_Conv(node))
733
		return false;
734

735
736
737
738
	/* 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)
739
		return false;
740

741
742
	ir_mode *src_mode  = get_irn_mode(get_Conv_op(node));
	ir_mode *dest_mode = get_irn_mode(node);
743
744
745
746
747
748
749
750
751
	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)
{
752
	while (is_sameconv(node)) {
753
		node = get_Conv_op(node);
754
	}
755
756
757
758

	return node;
}

759
static ir_node *transform_sext(ir_node *node, ir_node *orig_node)
760
{
761
762
763
	ir_mode  *mode  = get_irn_mode(node);
	ir_node  *block = get_nodes_block(node);
	dbg_info *dbgi  = get_irn_dbg_info(node);
Christoph Mallon's avatar
Christoph Mallon committed
764
	/* normalize to a signed mode */
765
766
767
768
769
770
	switch (get_mode_size_bits(mode)) {
	case 8:  mode = mode_Bs; break;
	case 16: mode = mode_Hs; break;
	default:
		panic("ia32: invalid mode in sest: %+F", node);
	}
771
	return create_I2I_Conv(mode, ia32_mode_gp, dbgi, block, node, orig_node);
772
}
773

774
775
776
777
778
779
780
781
782
783
784
785
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);
	}
786
	return create_I2I_Conv(mode, ia32_mode_gp, dbgi, block, node, orig_node);
787
788
789
790
791
}

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
792
	if (mode_is_signed(mode)) {
793
		return transform_sext(node, orig_node);
794
	} else {
795
		return transform_zext(node, orig_node);
796
797
	}
}
798

799
static ir_node *get_noreg(ir_graph *const irg, ir_mode *const mode)
800
801
802
803
{
	if (!mode_is_float(mode)) {
		return noreg_GP;
	} else if (ia32_cg_config.use_sse2) {
804
		return ia32_new_NoReg_xmm(irg);
805
	} else {
806
		return ia32_new_NoReg_fp(irg);
807
808
809
	}
}

810
811
812
813
814
815
816
817
818
819
820
/**
 * 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.
 */
821
static void match_arguments(ia32_address_mode_t *am, ir_node *block,
822
823
                            ir_node *op1, ir_node *op2, ir_node *other_op,
                            match_flags_t flags)
824
825
826
{
	memset(am, 0, sizeof(am[0]));

827
828
829
830
	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;
831
	assert(!use_am_and_immediates || use_immediate);
832
833
834

	assert(op2 != NULL);
	assert(!commutative || op1 != NULL);
835
836
	assert(use_am || !(flags & match_8bit_am));
	assert(use_am || !(flags & match_16bit_am));
837

838
839
	ir_mode *mode      = get_irn_mode(op2);
	int      mode_bits = get_mode_size_bits(mode);
840
	if ((mode_bits ==  8 && !(flags & match_8bit_am)) ||
841
	    (mode_bits == 16 && !(flags & match_16bit_am))) {