ia32_transform.c 167 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
/*
Michael Beck's avatar
Michael Beck committed
2
 * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
Christian Würdig's avatar
Christian Würdig committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * This file is part of libFirm.
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU General Public License version 2 as published by the Free Software
 * Foundation and appearing in the file LICENSE.GPL included in the
 * packaging of this file.
 *
 * Licensees holding valid libFirm Professional Edition licenses may use
 * this file in accordance with the libFirm Commercial License.
 * Agreement provided with the Software.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE.
 */

Christian Würdig's avatar
Christian Würdig committed
20
/**
Christian Würdig's avatar
Christian Würdig committed
21
 * @file
22
23
 * @brief       This file implements the IR transformation from firm into
 *              ia32-Firm.
Christian Würdig's avatar
Christian Würdig committed
24
25
 * @author      Christian Wuerdig, Matthias Braun
 * @version     $Id$
Christian Würdig's avatar
Christian Würdig committed
26
 */
27
#include "config.h"
28

Christian Würdig's avatar
Christian Würdig committed
29
#include <limits.h>
30
#include <stdbool.h>
Christian Würdig's avatar
Christian Würdig committed
31

Christian Würdig's avatar
Christian Würdig committed
32
#include "irargs_t.h"
33
34
35
#include "irnode_t.h"
#include "irgraph_t.h"
#include "irmode_t.h"
Christian Würdig's avatar
Christian Würdig committed
36
37
38
#include "iropt_t.h"
#include "irop_t.h"
#include "irprog_t.h"
Christian Würdig's avatar
Christian Würdig committed
39
#include "iredges_t.h"
40
#include "irgmod.h"
Christian Würdig's avatar
Christian Würdig committed
41
#include "irvrfy.h"
42
#include "ircons.h"
43
#include "irgwalk.h"
44
#include "irprintf.h"
45
#include "debug.h"
46
#include "irdom.h"
47
#include "error.h"
48
#include "array_t.h"
49
#include "height.h"
50

51
#include "../benode.h"
Christian Würdig's avatar
Christian Würdig committed
52
#include "../besched.h"
Christian Würdig's avatar
Christian Würdig committed
53
#include "../beabi.h"
54
#include "../beutil.h"
55
#include "../beirg.h"
Michael Beck's avatar
Michael Beck committed
56
#include "../betranshlp.h"
Matthias Braun's avatar
Matthias Braun committed
57
#include "../be_t.h"
Christian Würdig's avatar
Christian Würdig committed
58

59
#include "bearch_ia32_t.h"
60
#include "ia32_common_transform.h"
61
62
63
#include "ia32_nodes_attr.h"
#include "ia32_transform.h"
#include "ia32_new_nodes.h"
Christian Würdig's avatar
Christian Würdig committed
64
#include "ia32_map_regs.h"
Christian Würdig's avatar
Christian Würdig committed
65
#include "ia32_dbg_stat.h"
66
#include "ia32_optimize.h"
67
#include "ia32_util.h"
68
#include "ia32_address_mode.h"
69
#include "ia32_architecture.h"
70

Christian Würdig's avatar
Christian Würdig committed
71
72
#include "gen_ia32_regalloc_if.h"

73
74
75
76
/* define this to construct SSE constants instead of load them */
#undef CONSTRUCT_SSE_CONST


77
78
79
80
81
#define SFP_SIGN   "0x80000000"
#define DFP_SIGN   "0x8000000000000000"
#define SFP_ABS    "0x7FFFFFFF"
#define DFP_ABS    "0x7FFFFFFFFFFFFFFF"
#define DFP_INTMAX "9223372036854775807"
82
#define ULL_BIAS   "18446744073709551616"
83

84
85
86
87
88
#define ENT_SFP_SIGN "C_ia32_sfp_sign"
#define ENT_DFP_SIGN "C_ia32_dfp_sign"
#define ENT_SFP_ABS  "C_ia32_sfp_abs"
#define ENT_DFP_ABS  "C_ia32_dfp_abs"
#define ENT_ULL_BIAS "C_ia32_ull_bias"
89

90
91
92
#define mode_vfp	(ia32_reg_classes[CLASS_ia32_vfp].mode)
#define mode_xmm    (ia32_reg_classes[CLASS_ia32_xmm].mode)

93
94
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

95
static ir_node         *initial_fpcw = NULL;
96
int                     no_pic_adjust;
97

98
99
100
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
101

102
103
104
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);
105

106
107
typedef ir_node *construct_shift_func(dbg_info *db, ir_node *block,
        ir_node *op1, ir_node *op2);
108

109
110
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);
111

112
113
typedef ir_node *construct_unop_dest_func(dbg_info *db, ir_node *block,
        ir_node *base, ir_node *index, ir_node *mem);
114

115
116
117
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
118

119
typedef ir_node *construct_unop_func(dbg_info *db, ir_node *block, ir_node *op);
120

121
122
123
static ir_node *create_immediate_or_transform(ir_node *node,
                                              char immediate_constraint_type);

124
static ir_node *create_I2I_Conv(ir_mode *src_mode, ir_mode *tgt_mode,
125
126
                                dbg_info *dbgi, ir_node *block,
                                ir_node *op, ir_node *orig_node);
127

128
129
130
/* its enough to have those once */
static ir_node *nomem, *noreg_GP;

131
132
133
134
/** a list to postprocess all calls */
static ir_node **call_list;
static ir_type **call_types;

Michael Beck's avatar
Michael Beck committed
135
/** Return non-zero is a node represents the 0 constant. */
Christoph Mallon's avatar
Christoph Mallon committed
136
137
static bool is_Const_0(ir_node *node)
{
138
	return is_Const(node) && is_Const_null(node);
139
140
}

Michael Beck's avatar
Michael Beck committed
141
/** Return non-zero is a node represents the 1 constant. */
Christoph Mallon's avatar
Christoph Mallon committed
142
143
static bool is_Const_1(ir_node *node)
{
144
	return is_Const(node) && is_Const_one(node);
145
146
}

Michael Beck's avatar
Michael Beck committed
147
/** Return non-zero is a node represents the -1 constant. */
Christoph Mallon's avatar
Christoph Mallon committed
148
149
static bool is_Const_Minus_1(ir_node *node)
{
150
	return is_Const(node) && is_Const_all_one(node);
151
152
}

153
154
155
/**
 * returns true if constant can be created with a simple float command
 */
156
static bool is_simple_x87_Const(ir_node *node)
157
158
{
	tarval *tv = get_Const_tarval(node);
159
	if (tarval_is_null(tv) || tarval_is_one(tv))
160
		return true;
161
162

	/* TODO: match all the other float constants */
163
	return false;
164
165
166
167
168
}

/**
 * returns true if constant can be created with a simple float command
 */
169
static bool is_simple_sse_Const(ir_node *node)
170
{
Michael Beck's avatar
Michael Beck committed
171
	tarval  *tv   = get_Const_tarval(node);
172
	ir_mode *mode = get_tarval_mode(tv);
173

174
	if (mode == mode_F)
175
		return true;
176

177
178
179
180
181
	if (tarval_is_null(tv)
#ifdef CONSTRUCT_SSE_CONST
	    || tarval_is_one(tv)
#endif
	   )
182
		return true;
183
#ifdef CONSTRUCT_SSE_CONST
184
185
186
187
188
189
	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)
190
			/* lower 32bit are zero, really a 32bit constant */
191
			return true;
192
	}
193
#endif /* CONSTRUCT_SSE_CONST */
194
	/* TODO: match all the other float constants */
195
	return false;
196
197
}

198
199
200
201
202
203
/**
 * 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)
{
204
	if (be_get_irg_options(env_cg->irg)->pic) {
205
206
207
208
209
210
		return arch_code_generator_get_pic_base(env_cg);
	}

	return noreg_GP;
}

211
212
213
/**
 * Transforms a Const.
 */
Christoph Mallon's avatar
Christoph Mallon committed
214
215
static ir_node *gen_Const(ir_node *node)
{
216
217
218
219
	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);
220

221
222
	assert(is_Const(node));

223
	if (mode_is_float(mode)) {
224
225
		ir_node   *res   = NULL;
		ir_node   *load;
226
		ir_node   *base;
227
228
		ir_entity *floatent;

229
		if (ia32_cg_config.use_sse2) {
230
231
			tarval *tv = get_Const_tarval(node);
			if (tarval_is_null(tv)) {
232
				load = new_bd_ia32_xZero(dbgi, block);
233
234
				set_ia32_ls_mode(load, mode);
				res  = load;
235
#ifdef CONSTRUCT_SSE_CONST
236
237
			} else if (tarval_is_one(tv)) {
				int     cnst  = mode == mode_F ? 26 : 55;
238
239
				ir_node *imm1 = ia32_create_Immediate(NULL, 0, cnst);
				ir_node *imm2 = ia32_create_Immediate(NULL, 0, 2);
240
241
				ir_node *pslld, *psrld;

242
				load = new_bd_ia32_xAllOnes(dbgi, block);
243
				set_ia32_ls_mode(load, mode);
244
				pslld = new_bd_ia32_xPslld(dbgi, block, load, imm1);
245
				set_ia32_ls_mode(pslld, mode);
246
				psrld = new_bd_ia32_xPsrld(dbgi, block, pslld, imm2);
247
248
				set_ia32_ls_mode(psrld, mode);
				res = psrld;
249
#endif /* CONSTRUCT_SSE_CONST */
250
251
252
253
254
255
			} 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);
256
				ir_node *cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, 0, val);
257
				load = new_bd_ia32_xMovd(dbgi, block, cnst);
258
259
				set_ia32_ls_mode(load, mode);
				res = load;
260
			} else {
261
#ifdef CONSTRUCT_SSE_CONST
262
263
264
265
266
267
				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) {
268
						ir_node *imm32 = ia32_create_Immediate(NULL, 0, 32);
269
270
271
272
273
274
275
						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);
276
						cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, 0, val);
277
						load = new_bd_ia32_xMovd(dbgi, block, cnst);
278
						set_ia32_ls_mode(load, mode);
279
						psllq = new_bd_ia32_xPsllq(dbgi, block, load, imm32);
280
281
282
283
284
						set_ia32_ls_mode(psllq, mode);
						res = psllq;
						goto end;
					}
				}
285
#endif /* CONSTRUCT_SSE_CONST */
286
				floatent = create_float_const_entity(node);
287

288
289
290
				base     = get_symconst_base();
				load     = new_bd_ia32_xLoad(dbgi, block, base, noreg_GP, nomem,
				                             mode);
291
292
				set_ia32_op_type(load, ia32_AddrModeS);
				set_ia32_am_sc(load, floatent);
293
				arch_irn_add_flags(load, arch_irn_flags_rematerializable);
294
				res = new_r_Proj(load, mode_xmm, pn_ia32_xLoad_res);
295
296
			}
		} else {
297
			if (is_Const_null(node)) {
298
				load = new_bd_ia32_vfldz(dbgi, block);
299
				res  = load;
300
				set_ia32_ls_mode(load, mode);
301
			} else if (is_Const_one(node)) {
302
				load = new_bd_ia32_vfld1(dbgi, block);
303
				res  = load;
304
				set_ia32_ls_mode(load, mode);
305
			} else {
306
				ir_mode *ls_mode;
307
				ir_node *base;
308

309
				floatent = create_float_const_entity(node);
310
311
312
				/* create_float_const_ent is smart and sometimes creates
				   smaller entities */
				ls_mode  = get_type_mode(get_entity_type(floatent));
313
				base     = get_symconst_base();
314
				load     = new_bd_ia32_vfld(dbgi, block, base, noreg_GP, nomem,
315
				                            ls_mode);
316
				set_ia32_op_type(load, ia32_AddrModeS);
317
				set_ia32_am_sc(load, floatent);
318
				arch_irn_add_flags(load, arch_irn_flags_rematerializable);
319
				res = new_r_Proj(load, mode_vfp, pn_ia32_vfld_res);
320
321
			}
		}
322
#ifdef CONSTRUCT_SSE_CONST
323
end:
324
#endif /* CONSTRUCT_SSE_CONST */
325
		SET_IA32_ORIG_NODE(load, node);
326
327

		be_dep_on_frame(load);
328
		return res;
329
	} else { /* non-float mode */
330
331
332
333
334
335
		ir_node *cnst;
		tarval  *tv = get_Const_tarval(node);
		long     val;

		tv = tarval_convert_to(tv, mode_Iu);

336
337
		if (tv == get_tarval_bad() || tv == get_tarval_undefined() ||
		    tv == NULL) {
338
339
340
341
			panic("couldn't convert constant tarval (%+F)", node);
		}
		val = get_tarval_long(tv);

342
		cnst = new_bd_ia32_Const(dbgi, block, NULL, 0, 0, val);
343
		SET_IA32_ORIG_NODE(cnst, node);
344

345
		be_dep_on_frame(cnst);
346
347
348
349
350
351
352
		return cnst;
	}
}

/**
 * Transforms a SymConst.
 */
Christoph Mallon's avatar
Christoph Mallon committed
353
354
static ir_node *gen_SymConst(ir_node *node)
{
355
356
	ir_node  *old_block = get_nodes_block(node);
	ir_node  *block = be_transform_node(old_block);
357
358
	dbg_info *dbgi  = get_irn_dbg_info(node);
	ir_mode  *mode  = get_irn_mode(node);
359
360
361
	ir_node  *cnst;

	if (mode_is_float(mode)) {
362
		if (ia32_cg_config.use_sse2)
363
			cnst = new_bd_ia32_xLoad(dbgi, block, noreg_GP, noreg_GP, nomem, mode_E);
364
		else
365
			cnst = new_bd_ia32_vfld(dbgi, block, noreg_GP, noreg_GP, nomem, mode_E);
366
		set_ia32_am_sc(cnst, get_SymConst_entity(node));
367
		set_ia32_use_frame(cnst);
368
	} else {
Michael Beck's avatar
Michael Beck committed
369
370
		ir_entity *entity;

Christoph Mallon's avatar
Christoph Mallon committed
371
		if (get_SymConst_kind(node) != symconst_addr_ent) {
372
373
			panic("backend only support symconst_addr_ent (at %+F)", node);
		}
Michael Beck's avatar
Michael Beck committed
374
		entity = get_SymConst_entity(node);
375
		cnst = new_bd_ia32_Const(dbgi, block, entity, 0, 0, 0);
376
377
	}

378
	SET_IA32_ORIG_NODE(cnst, node);
379

380
	be_dep_on_frame(cnst);
381
382
383
	return cnst;
}

Michael Beck's avatar
Michael Beck committed
384
385
386
387
388
389
/**
 * Create a float type for the given mode and cache it.
 *
 * @param mode   the mode for the float type (might be integer mode for SSE2 types)
 * @param align  alignment
 */
390
391
static ir_type *ia32_create_float_type(ir_mode *mode, unsigned align)
{
Michael Beck's avatar
Michael Beck committed
392
393
394
395
396
397
398
399
	ir_type *tp;

	assert(align <= 16);

	if (mode == mode_Iu) {
		static ir_type *int_Iu[16] = {NULL, };

		if (int_Iu[align] == NULL) {
400
			int_Iu[align] = tp = new_type_primitive(mode);
Michael Beck's avatar
Michael Beck committed
401
402
403
404
405
406
407
408
			/* set the specified alignment */
			set_type_alignment_bytes(tp, align);
		}
		return int_Iu[align];
	} else if (mode == mode_Lu) {
		static ir_type *int_Lu[16] = {NULL, };

		if (int_Lu[align] == NULL) {
409
			int_Lu[align] = tp = new_type_primitive(mode);
Michael Beck's avatar
Michael Beck committed
410
411
412
413
414
415
416
417
			/* set the specified alignment */
			set_type_alignment_bytes(tp, align);
		}
		return int_Lu[align];
	} else if (mode == mode_F) {
		static ir_type *float_F[16] = {NULL, };

		if (float_F[align] == NULL) {
418
			float_F[align] = tp = new_type_primitive(mode);
Michael Beck's avatar
Michael Beck committed
419
420
421
422
423
424
425
426
			/* set the specified alignment */
			set_type_alignment_bytes(tp, align);
		}
		return float_F[align];
	} else if (mode == mode_D) {
		static ir_type *float_D[16] = {NULL, };

		if (float_D[align] == NULL) {
427
			float_D[align] = tp = new_type_primitive(mode);
Michael Beck's avatar
Michael Beck committed
428
429
430
431
432
433
434
435
			/* set the specified alignment */
			set_type_alignment_bytes(tp, align);
		}
		return float_D[align];
	} else {
		static ir_type *float_E[16] = {NULL, };

		if (float_E[align] == NULL) {
436
			float_E[align] = tp = new_type_primitive(mode);
Michael Beck's avatar
Michael Beck committed
437
438
439
440
441
442
443
444
445
446
447
448
			/* set the specified alignment */
			set_type_alignment_bytes(tp, align);
		}
		return float_E[align];
	}
}

/**
 * Create a float[2] array type for the given atomic type.
 *
 * @param tp  the atomic type
 */
449
450
static ir_type *ia32_create_float_array(ir_type *tp)
{
Michael Beck's avatar
Michael Beck committed
451
452
453
454
455
456
457
458
459
460
461
	ir_mode  *mode = get_type_mode(tp);
	unsigned align = get_type_alignment_bytes(tp);
	ir_type  *arr;

	assert(align <= 16);

	if (mode == mode_F) {
		static ir_type *float_F[16] = {NULL, };

		if (float_F[align] != NULL)
			return float_F[align];
462
		arr = float_F[align] = new_type_array(1, tp);
Michael Beck's avatar
Michael Beck committed
463
464
465
466
467
	} else if (mode == mode_D) {
		static ir_type *float_D[16] = {NULL, };

		if (float_D[align] != NULL)
			return float_D[align];
468
		arr = float_D[align] = new_type_array(1, tp);
Michael Beck's avatar
Michael Beck committed
469
470
471
472
473
	} else {
		static ir_type *float_E[16] = {NULL, };

		if (float_E[align] != NULL)
			return float_E[align];
474
		arr = float_E[align] = new_type_array(1, tp);
Michael Beck's avatar
Michael Beck committed
475
476
477
478
479
480
481
	}
	set_type_alignment_bytes(arr, align);
	set_type_size_bytes(arr, 2 * get_type_size_bytes(tp));
	set_type_state(arr, layout_fixed);
	return arr;
}

482
/* Generates an entity for a known FP const (used for FP Neg + Abs) */
Christoph Mallon's avatar
Christoph Mallon committed
483
484
ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct)
{
485
486
487
	static const struct {
		const char *ent_name;
		const char *cnst_str;
488
		char mode;
Michael Beck's avatar
Michael Beck committed
489
		unsigned char align;
490
	} names [ia32_known_const_max] = {
Michael Beck's avatar
Michael Beck committed
491
492
493
494
495
		{ ENT_SFP_SIGN, SFP_SIGN,   0, 16 }, /* ia32_SSIGN */
		{ ENT_DFP_SIGN, DFP_SIGN,   1, 16 }, /* ia32_DSIGN */
		{ ENT_SFP_ABS,  SFP_ABS,    0, 16 }, /* ia32_SABS */
		{ ENT_DFP_ABS,  DFP_ABS,    1, 16 }, /* ia32_DABS */
		{ ENT_ULL_BIAS, ULL_BIAS,   2, 4 }   /* ia32_ULLBIAS */
496
	};
497
	static ir_entity *ent_cache[ia32_known_const_max];
498

Michael Beck's avatar
Michael Beck committed
499
	const char    *ent_name, *cnst_str;
500
	ir_type       *tp;
501
	ir_entity     *ent;
502
	tarval        *tv;
Michael Beck's avatar
BugFix:    
Michael Beck committed
503
	ir_mode       *mode;
504

Christian Würdig's avatar
Christian Würdig committed
505
	ent_name = names[kct].ent_name;
506
507
	if (! ent_cache[kct]) {
		cnst_str = names[kct].cnst_str;
508

509
510
511
		switch (names[kct].mode) {
		case 0:  mode = mode_Iu; break;
		case 1:  mode = mode_Lu; break;
Michael Beck's avatar
Michael Beck committed
512
		default: mode = mode_F;  break;
513
		}
514
		tv  = new_tarval_from_str(cnst_str, strlen(cnst_str), mode);
Michael Beck's avatar
Michael Beck committed
515
		tp  = ia32_create_float_type(mode, names[kct].align);
516

Michael Beck's avatar
Michael Beck committed
517
518
		if (kct == ia32_ULLBIAS)
			tp = ia32_create_float_array(tp);
519
520
521
		ent = new_entity(get_glob_type(), new_id_from_str(ent_name), tp);

		set_entity_ld_ident(ent, get_entity_ident(ent));
522
		add_entity_linkage(ent, IR_LINKAGE_CONSTANT);
523
		set_entity_visibility(ent, ir_visibility_private);
524

525
526
527
528
		if (kct == ia32_ULLBIAS) {
			ir_initializer_t *initializer = create_initializer_compound(2);

			set_initializer_compound_value(initializer, 0,
529
				create_initializer_tarval(get_mode_null(mode)));
530
531
			set_initializer_compound_value(initializer, 1,
				create_initializer_tarval(tv));
532

533
534
535
536
			set_entity_initializer(ent, initializer);
		} else {
			set_entity_initializer(ent, create_initializer_tarval(tv));
		}
537

538
539
		/* cache the entry */
		ent_cache[kct] = ent;
540
	}
541

542
	return ent_cache[kct];
543
544
}

545
546
547
548
549
550
551
/**
 * 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).
 */
static int ia32_use_source_address_mode(ir_node *block, ir_node *node,
552
                                        ir_node *other, ir_node *other2, match_flags_t flags)
553
554
555
556
{
	ir_node *load;
	long     pn;

557
	/* float constants are always available */
Michael Beck's avatar
Michael Beck committed
558
559
560
561
562
563
564
565
566
567
568
	if (is_Const(node)) {
		ir_mode *mode = get_irn_mode(node);
		if (mode_is_float(mode)) {
			if (ia32_cg_config.use_sse2) {
				if (is_simple_sse_Const(node))
					return 0;
			} else {
				if (is_simple_x87_Const(node))
					return 0;
			}
			if (get_irn_n_edges(node) > 1)
569
				return 0;
Michael Beck's avatar
Michael Beck committed
570
			return 1;
571
		}
572
573
	}

Michael Beck's avatar
Michael Beck committed
574
	if (!is_Proj(node))
575
576
577
		return 0;
	load = get_Proj_pred(node);
	pn   = get_Proj_proj(node);
Michael Beck's avatar
Michael Beck committed
578
	if (!is_Load(load) || pn != pn_Load_res)
579
		return 0;
Michael Beck's avatar
Michael Beck committed
580
	if (get_nodes_block(load) != block)
581
582
		return 0;
	/* we only use address mode if we're the only user of the load */
583
	if (get_irn_n_edges(node) != (flags & match_two_users ? 2 : 1))
584
		return 0;
585
586
587
	/* 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
588
	if (be_is_transformed(node))
589
		return 0;
590
591

	/* don't do AM if other node inputs depend on the load (via mem-proj) */
592
	if (other != NULL && prevents_AM(block, load, other))
593
		return 0;
594
595

	if (other2 != NULL && prevents_AM(block, load, other2))
596
		return 0;
597
598
599
600
601
602
603
604
605

	return 1;
}

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;
606
	ir_node        *am_node;
607
608
609
	ia32_op_type_t  op_type;
	ir_node        *new_op1;
	ir_node        *new_op2;
610
	op_pin_state    pinned;
Matthias Braun's avatar
Matthias Braun committed
611
612
	unsigned        commutative  : 1;
	unsigned        ins_permuted : 1;
613
614
};

Matthias Braun's avatar
Matthias Braun committed
615
616
617
618
static void build_address_ptr(ia32_address_t *addr, ir_node *ptr, ir_node *mem)
{
	/* construct load address */
	memset(addr, 0, sizeof(addr[0]));
Christoph Mallon's avatar
Christoph Mallon committed
619
	ia32_create_address_mode(addr, ptr, 0);
Matthias Braun's avatar
Matthias Braun committed
620

621
622
	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
623
624
625
	addr->mem   = be_transform_node(mem);
}

626
627
static void build_address(ia32_address_mode_t *am, ir_node *node,
                          ia32_create_am_flags_t flags)
628
{
629
	ia32_address_t *addr = &am->addr;
630
631
632
633
	ir_node        *load;
	ir_node        *ptr;
	ir_node        *mem;
	ir_node        *new_mem;
634

635
	/* floating point immediates */
636
	if (is_Const(node)) {
637
		ir_entity *entity  = create_float_const_entity(node);
638
		addr->base         = get_symconst_base();
639
640
		addr->index        = noreg_GP;
		addr->mem          = nomem;
641
642
		addr->symconst_ent = entity;
		addr->use_frame    = 1;
643
		am->ls_mode        = get_type_mode(get_entity_type(entity));
644
		am->pinned         = op_pin_state_floats;
645
646
647
648
649
650
651
		return;
	}

	load         = get_Proj_pred(node);
	ptr          = get_Load_ptr(load);
	mem          = get_Load_mem(load);
	new_mem      = be_transform_node(mem);
652
	am->pinned   = get_irn_pinned(load);
653
654
	am->ls_mode  = get_Load_mode(load);
	am->mem_proj = be_get_Proj_for_pn(load, pn_Load_M);
655
	am->am_node  = node;
656
657

	/* construct load address */
658
	ia32_create_address_mode(addr, ptr, flags);
659

660
661
	addr->base  = addr->base  ? be_transform_node(addr->base)  : noreg_GP;
	addr->index = addr->index ? be_transform_node(addr->index) : noreg_GP;
662
	addr->mem   = new_mem;
663
664
}

665
static void set_address(ir_node *node, const ia32_address_t *addr)
666
667
668
669
{
	set_ia32_am_scale(node, addr->scale);
	set_ia32_am_sc(node, addr->symconst_ent);
	set_ia32_am_offs_int(node, addr->offset);
Christoph Mallon's avatar
Christoph Mallon committed
670
	if (addr->symconst_sign)
671
		set_ia32_am_sc_sign(node);
Christoph Mallon's avatar
Christoph Mallon committed
672
	if (addr->use_frame)
673
674
		set_ia32_use_frame(node);
	set_ia32_frame_ent(node, addr->frame_entity);
675
676
}

Michael Beck's avatar
Michael Beck committed
677
678
679
/**
 * Apply attributes of a given address mode to a node.
 */
680
static void set_am_attributes(ir_node *node, const ia32_address_mode_t *am)
681
682
{
	set_address(node, &am->addr);
683

684
685
	set_ia32_op_type(node, am->op_type);
	set_ia32_ls_mode(node, am->ls_mode);
Michael Beck's avatar
Michael Beck committed
686
	if (am->pinned == op_pin_state_pinned) {
687
688
689
		/* 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);
690
	}
Michael Beck's avatar
Michael Beck committed
691
	if (am->commutative)
692
693
		set_ia32_commutative(node);
}
694

695
696
697
698
699
700
701
702
/**
 * Check, if a given node is a Down-Conv, ie. a integer Conv
 * 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
 */
703
704
705
706
707
static int is_downconv(const ir_node *node)
{
	ir_mode *src_mode;
	ir_mode *dest_mode;

Christoph Mallon's avatar
Christoph Mallon committed
708
	if (!is_Conv(node))
709
710
711
		return 0;

	/* we only want to skip the conv when we're the only user
712
713
	 * (because this test is used in the context of address-mode selection
	 *  and we don't want to use address mode for multiple users) */
Christoph Mallon's avatar
Christoph Mallon committed
714
	if (get_irn_n_edges(node) > 1)
715
716
717
718
		return 0;

	src_mode  = get_irn_mode(get_Conv_op(node));
	dest_mode = get_irn_mode(node);
719
720
721
722
	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);
723
724
}

725
/** Skip all Down-Conv's on a given node and return the resulting node. */
Christoph Mallon's avatar
Christoph Mallon committed
726
727
ir_node *ia32_skip_downconv(ir_node *node)
{
728
729
730
731
732
733
	while (is_downconv(node))
		node = get_Conv_op(node);

	return node;
}

734
735
736
737
738
739
740
741
static bool is_sameconv(ir_node *node)
{
	ir_mode *src_mode;
	ir_mode *dest_mode;

	if (!is_Conv(node))
		return 0;

742
743
744
745
746
747
	/* 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)
		return 0;

748
749
750
751
752
753
754
755
756
757
758
	src_mode  = get_irn_mode(get_Conv_op(node));
	dest_mode = get_irn_mode(node);
	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)
{
Matthias Braun's avatar
Matthias Braun committed
759
	while (is_sameconv(node))
760
761
762
763
764
		node = get_Conv_op(node);

	return node;
}

765
766
767
768
769
770
static ir_node *create_upconv(ir_node *node, ir_node *orig_node)
{
	ir_mode  *mode = get_irn_mode(node);
	ir_node  *block;
	ir_mode  *tgt_mode;
	dbg_info *dbgi;
771

Christoph Mallon's avatar
Christoph Mallon committed
772
	if (mode_is_signed(mode)) {
773
774
775
776
777
778
779
780
781
		tgt_mode = mode_Is;
	} else {
		tgt_mode = mode_Iu;
	}
	block = get_nodes_block(node);
	dbgi  = get_irn_dbg_info(node);

	return create_I2I_Conv(mode, tgt_mode, dbgi, block, node, orig_node);
}
782

783
784
785
786
787
788
789
790
791
792
793
/**
 * 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.
 */
794
static void match_arguments(ia32_address_mode_t *am, ir_node *block,
795
796
                            ir_node *op1, ir_node *op2, ir_node *other_op,
                            match_flags_t flags)
797
{
Michael Beck's avatar
Michael Beck committed
798
799
800
	ia32_address_t *addr      = &am->addr;
	ir_mode        *mode      = get_irn_mode(op2);
	int             mode_bits = get_mode_size_bits(mode);
801
	ir_node        *new_op1, *new_op2;
802
	int             use_am;
Michael Beck's avatar
Michael Beck committed
803
	unsigned        commutative;
804
	int             use_am_and_immediates;
805
	int             use_immediate;
806
807
808

	memset(am, 0, sizeof(am[0]));

809
810
	commutative           = (flags & match_commutative) != 0;
	use_am_and_immediates = (flags & match_am_and_immediates) != 0;
811
812
813
	use_am                = (flags & match_am) != 0;
	use_immediate         = (flags & match_immediate) != 0;
	assert(!use_am_and_immediates || use_immediate);
814
815
816

	assert(op2 != NULL);
	assert(!commutative || op1 != NULL);
817
818
	assert(use_am || !(flags & match_8bit_am));
	assert(use_am || !(flags & match_16bit_am));
819

820
	if ((mode_bits ==  8 && !(flags & match_8bit_am)) ||
821
	    (mode_bits == 16 && !(flags & match_16bit_am))) {
822
		use_am = 0;
823
	}
824

825
826
	/* we can simply skip downconvs for mode neutral nodes: the upper bits
	 * can be random for these operations */
827
	if (flags & match_mode_neutral) {
828
		op2 = ia32_skip_downconv(op2);
829
		if (op1 != NULL) {
830
831
			op1 = ia32_skip_downconv(op1);
		}
832
833
834
835
836
	} else {
		op2 = ia32_skip_sameconv(op2);
		if (op1 != NULL) {
			op1 = ia32_skip_sameconv(op1);
		}
837
838
	}

839
840
841
	/* match immediates. firm nodes are normalized: constants are always on the
	 * op2 input */
	new_op2 = NULL;
842
	if (!(flags & match_try_am) && use_immediate) {
843
		new_op2 = try_create_Immediate(op2, 0);
844
	}
845

846
	if (new_op2 == NULL &&
847
	    use_am && ia32_use_source_address_mode(block, op2, op1, other_op, flags)) {
848
		build_address(am, op2, 0);
849
		new_op1     = (op1 == NULL ? NULL : be_transform_node(op1));
Michael Beck's avatar
Michael Beck committed
850
		if (mode_is_float(mode)) {
851
852
			new_op2 = ia32_new_NoReg_vfp(env_cg);
		} else {
853
			new_op2 = noreg_GP;
854
		}
855
		am->op_type = ia32_AddrModeS;
856
857
	} else if (commutative && (new_op2 == NULL || use_am_and_immediates) &&
		       use_am &&
858
		       ia32_use_source_address_mode(block, op1, op2, other_op, flags)) {
859
		ir_node *noreg;
860
		build_address(am, op1, 0);
861

862
		if (mode_is_float(mode)) {
863
864
			noreg = ia32_new_NoReg_vfp(env_cg);
		} else {
865
			noreg = noreg_GP;
866
867
		}

Michael Beck's avatar
Michael Beck committed
868
		if (new_op2 != NULL) {
869
			new_op1 = noreg;
870
871
		} else {
			new_op1 = be_transform_node(op2);
872
			new_op2 = noreg;
873
			am->ins_permuted = 1;
874
875
		}
		am->op_type = ia32_AddrModeS;
876
	} else {
877
		ir_mode *mode;
Christoph Mallon's avatar
Christoph Mallon committed
878
879
		am->op_type = ia32_Normal;

Michael Beck's avatar
Michael Beck committed
880
		if (flags & match_try_am) {
881
882
883
884
885
			am->new_op1 = NULL;
			am->new_op2 = NULL;
			return;
		}

886
887
888
889
890
891
892
893
894
895
896
897
		mode = get_irn_mode(op2);
		if (flags & match_upconv_32 && get_mode_size_bits(mode) != 32) {
			new_op1 = (op1 == NULL ? NULL : create_upconv(op1, NULL));