ia32_transform.c 135 KB
Newer Older
Christian Würdig's avatar
Christian Würdig committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
 * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
 *
 * 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
#ifdef HAVE_CONFIG_H
28
#include "config.h"
29
30
#endif

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

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

Christian Würdig's avatar
Christian Würdig committed
52
#include "../benode_t.h"
Christian Würdig's avatar
Christian Würdig committed
53
#include "../besched.h"
Christian Würdig's avatar
Christian Würdig committed
54
#include "../beabi.h"
55
#include "../beutil.h"
56
#include "../beirg_t.h"
Michael Beck's avatar
Michael Beck committed
57
#include "../betranshlp.h"
Christian Würdig's avatar
Christian Würdig committed
58

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

Christian Würdig's avatar
Christian Würdig committed
69
70
#include "gen_ia32_regalloc_if.h"

71
72
73
74
75
#define SFP_SIGN   "0x80000000"
#define DFP_SIGN   "0x8000000000000000"
#define SFP_ABS    "0x7FFFFFFF"
#define DFP_ABS    "0x7FFFFFFFFFFFFFFF"
#define DFP_INTMAX "9223372036854775807"
76
77
78
79
80

#define TP_SFP_SIGN "ia32_sfp_sign"
#define TP_DFP_SIGN "ia32_dfp_sign"
#define TP_SFP_ABS  "ia32_sfp_abs"
#define TP_DFP_ABS  "ia32_dfp_abs"
81
#define TP_INT_MAX  "ia32_int_max"
82
83
84
85
86

#define ENT_SFP_SIGN "IA32_SFP_SIGN"
#define ENT_DFP_SIGN "IA32_DFP_SIGN"
#define ENT_SFP_ABS  "IA32_SFP_ABS"
#define ENT_DFP_ABS  "IA32_DFP_ABS"
87
#define ENT_INT_MAX  "IA32_INT_MAX"
88

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

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

94
/** hold the current code generator during transformation */
95
96
static ia32_code_gen_t *env_cg       = NULL;
static ir_node         *initial_fpcw = NULL;
97
static heights_t       *heights      = NULL;
98
static transform_config_t transform_config;
99

100
101
extern ir_op *get_op_Mulh(void);

102
typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg,
103
104
        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
105

106
107
108
109
typedef ir_node *construct_binop_flags_func(dbg_info *db, ir_graph *irg,
        ir_node *block, ir_node *base, ir_node *index, ir_node *mem,
        ir_node *op1, ir_node *op2, ir_node *flags);

110
111
112
113
typedef ir_node *construct_shift_func(dbg_info *db, ir_graph *irg,
        ir_node *block, ir_node *op1, ir_node *op2);

typedef ir_node *construct_binop_dest_func(dbg_info *db, ir_graph *irg,
114
115
        ir_node *block, ir_node *base, ir_node *index, ir_node *mem,
        ir_node *op);
116
117
118
119

typedef ir_node *construct_unop_dest_func(dbg_info *db, ir_graph *irg,
        ir_node *block, ir_node *base, ir_node *index, ir_node *mem);

Matthias Braun's avatar
Matthias Braun committed
120
typedef ir_node *construct_binop_float_func(dbg_info *db, ir_graph *irg,
121
122
        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
123

124
typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg,
125
        ir_node *block, ir_node *op);
126

Christian Würdig's avatar
Christian Würdig committed
127
128
129
130
131
132
133
134
135
136
/****************************************************************************************************
 *                  _        _                        __                           _   _
 *                 | |      | |                      / _|                         | | (_)
 *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
 * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
 * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
 * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
 *
 ****************************************************************************************************/

137
138
static ir_node *try_create_Immediate(ir_node *node,
                                     char immediate_constraint_type);
139

140
141
142
static ir_node *create_immediate_or_transform(ir_node *node,
                                              char immediate_constraint_type);

143
static ir_node *create_I2I_Conv(ir_mode *src_mode, ir_mode *tgt_mode,
144
145
                                dbg_info *dbgi, ir_node *block,
                                ir_node *op, ir_node *orig_node);
146

147
148
149
150
/**
 * Return true if a mode can be stored in the GP register set
 */
static INLINE int mode_needs_gp_reg(ir_mode *mode) {
151
152
	if(mode == mode_fpcw)
		return 0;
153
154
	if(get_mode_size_bits(mode) > 32)
		return 0;
155
	return mode_is_int(mode) || mode_is_reference(mode) || mode == mode_b;
156
157
}

158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/**
 * creates a unique ident by adding a number to a tag
 *
 * @param tag   the tag string, must contain a %d if a number
 *              should be added
 */
static ident *unique_id(const char *tag)
{
	static unsigned id = 0;
	char str[256];

	snprintf(str, sizeof(str), tag, ++id);
	return new_id_from_str(str);
}

/**
 * Get a primitive type for a mode.
 */
static ir_type *get_prim_type(pmap *types, ir_mode *mode)
{
	pmap_entry *e = pmap_find(types, mode);
	ir_type *res;

	if (! e) {
		char buf[64];
		snprintf(buf, sizeof(buf), "prim_type_%s", get_mode_name(mode));
		res = new_type_primitive(new_id_from_str(buf), mode);
185
		set_type_alignment_bytes(res, 16);
186
187
188
189
190
191
192
193
		pmap_insert(types, mode, res);
	}
	else
		res = e->value;
	return res;
}

/**
194
 * Get an atomic entity that is initialized with a tarval
195
 */
196
static ir_entity *create_float_const_entity(ir_node *cnst)
197
{
198
199
200
	ia32_isa_t *isa = env_cg->isa;
	tarval *tv      = get_Const_tarval(cnst);
	pmap_entry *e   = pmap_find(isa->tv_ent, tv);
201
202
203
204
205
206
207
	ir_entity *res;
	ir_graph *rem;

	if (! e) {
		ir_mode *mode = get_irn_mode(cnst);
		ir_type *tp = get_Const_type(cnst);
		if (tp == firm_unknown_type)
208
			tp = get_prim_type(isa->types, mode);
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

		res = new_entity(get_glob_type(), unique_id(".LC%u"), tp);

		set_entity_ld_ident(res, get_entity_ident(res));
		set_entity_visibility(res, visibility_local);
		set_entity_variability(res, variability_constant);
		set_entity_allocation(res, allocation_static);

		 /* we create a new entity here: It's initialization must resist on the
		    const code irg */
		rem = current_ir_graph;
		current_ir_graph = get_const_code_irg();
		set_atomic_ent_value(res, new_Const_type(tv, tp));
		current_ir_graph = rem;

224
		pmap_insert(isa->tv_ent, tv, res);
225
	} else {
226
		res = e->value;
227
228
	}

229
230
231
	return res;
}

232
static int is_Const_0(ir_node *node) {
233
	return is_Const(node) && is_Const_null(node);
234
235
236
}

static int is_Const_1(ir_node *node) {
237
	return is_Const(node) && is_Const_one(node);
238
239
}

240
static int is_Const_Minus_1(ir_node *node) {
241
	return is_Const(node) && is_Const_all_one(node);
242
243
}

244
245
246
247
248
249
250
251
252
253
254
255
256
257
/**
 * returns true if constant can be created with a simple float command
 */
static int is_simple_x87_Const(ir_node *node)
{
	tarval *tv = get_Const_tarval(node);

	if(tarval_is_null(tv) || tarval_is_one(tv))
		return 1;

	/* TODO: match all the other float constants */
	return 0;
}

258
259
260
/**
 * Transforms a Const.
 */
261
static ir_node *gen_Const(ir_node *node) {
262
263
264
265
266
	ir_graph        *irg   = current_ir_graph;
	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);
267
268

	if (mode_is_float(mode)) {
269
		ir_node   *res   = NULL;
Michael Beck's avatar
Michael Beck committed
270
		ir_node   *noreg = ia32_new_NoReg_gp(env_cg);
271
272
		ir_node   *nomem = new_NoMem();
		ir_node   *load;
273
274
		ir_entity *floatent;

275
		if (USE_SSE2(env_cg)) {
276
			if (is_Const_null(node)) {
277
278
279
280
				load = new_rd_ia32_xZero(dbgi, irg, block);
				set_ia32_ls_mode(load, mode);
				res  = load;
			} else {
281
				floatent = create_float_const_entity(node);
282

283
284
285
286
287
288
289
290
				load     = new_rd_ia32_xLoad(dbgi, irg, block, noreg, noreg, nomem,
											 mode);
				set_ia32_op_type(load, ia32_AddrModeS);
				set_ia32_am_sc(load, floatent);
				set_ia32_flags(load, get_ia32_flags(load) | arch_irn_flags_rematerializable);
				res = new_r_Proj(irg, block, load, mode_xmm, pn_ia32_xLoad_res);
			}
		} else {
291
			if (is_Const_null(node)) {
292
				load = new_rd_ia32_vfldz(dbgi, irg, block);
293
				res  = load;
294
			} else if (is_Const_one(node)) {
295
				load = new_rd_ia32_vfld1(dbgi, irg, block);
296
				res  = load;
297
			} else {
298
				floatent = create_float_const_entity(node);
299

Matthias Braun's avatar
Matthias Braun committed
300
				load     = new_rd_ia32_vfld(dbgi, irg, block, noreg, noreg, nomem, mode);
301
				set_ia32_op_type(load, ia32_AddrModeS);
302
				set_ia32_am_sc(load, floatent);
303
304
				set_ia32_flags(load, get_ia32_flags(load) | arch_irn_flags_rematerializable);
				res = new_r_Proj(irg, block, load, mode_vfp, pn_ia32_vfld_res);
305
			}
306
			set_ia32_ls_mode(load, mode);
307
308
		}

Michael Beck's avatar
Michael Beck committed
309
		SET_IA32_ORIG_NODE(load, ia32_get_old_node_name(env_cg, node));
310
311

		/* Const Nodes before the initial IncSP are a bad idea, because
312
313
314
		 * they could be spilled and we have no SP ready at that point yet.
		 * So add a dependency to the initial frame pointer calculation to
		 * avoid that situation.
315
316
317
318
319
		 */
		if (get_irg_start_block(irg) == block) {
			add_irn_dep(load, get_irg_frame(irg));
		}

Michael Beck's avatar
Michael Beck committed
320
		SET_IA32_ORIG_NODE(load, ia32_get_old_node_name(env_cg, node));
321
322
		return res;
	} else {
323
324
325
326
327
328
329
330
331
332
333
334
335
336
		ir_node *cnst;
		tarval  *tv = get_Const_tarval(node);
		long     val;

		tv = tarval_convert_to(tv, mode_Iu);

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

		cnst = new_rd_ia32_Const(dbgi, irg, block, NULL, 0, val);
		SET_IA32_ORIG_NODE(cnst, ia32_get_old_node_name(env_cg, node));
337
338
339
340
341
342
343
344
345
346
347
348
349

		/* see above */
		if (get_irg_start_block(irg) == block) {
			add_irn_dep(cnst, get_irg_frame(irg));
		}

		return cnst;
	}
}

/**
 * Transforms a SymConst.
 */
350
static ir_node *gen_SymConst(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
351
	ir_graph *irg   = current_ir_graph;
352
353
	ir_node  *old_block = get_nodes_block(node);
	ir_node  *block = be_transform_node(old_block);
354
355
	dbg_info *dbgi  = get_irn_dbg_info(node);
	ir_mode  *mode  = get_irn_mode(node);
356
357
358
	ir_node  *cnst;

	if (mode_is_float(mode)) {
359
360
361
		ir_node *noreg = ia32_new_NoReg_gp(env_cg);
		ir_node *nomem = new_NoMem();

Michael Beck's avatar
Michael Beck committed
362
		if (USE_SSE2(env_cg))
363
			cnst = new_rd_ia32_xLoad(dbgi, irg, block, noreg, noreg, nomem, mode_E);
364
		else
365
366
			cnst = new_rd_ia32_vfld(dbgi, irg, block, noreg, noreg, nomem, mode_E);
		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;

371
372
373
		if(get_SymConst_kind(node) != symconst_addr_ent) {
			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_rd_ia32_Const(dbgi, irg, block, entity, 0, 0);
376
377
378
379
380
381
382
383
384
	}

	/* Const Nodes before the initial IncSP are a bad idea, because
	 * they could be spilled and we have no SP ready at that point yet
	 */
	if (get_irg_start_block(irg) == block) {
		add_irn_dep(cnst, get_irg_frame(irg));
	}

Michael Beck's avatar
Michael Beck committed
385
	SET_IA32_ORIG_NODE(cnst, ia32_get_old_node_name(env_cg, node));
386
387
388
389

	return cnst;
}

390
/* Generates an entity for a known FP const (used for FP Neg + Abs) */
391
ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct) {
392
393
394
395
	static const struct {
		const char *tp_name;
		const char *ent_name;
		const char *cnst_str;
396
397
		char mode;
		char align;
398
	} names [ia32_known_const_max] = {
399
400
401
402
403
		{ TP_SFP_SIGN, ENT_SFP_SIGN, SFP_SIGN,   0, 16 },	/* ia32_SSIGN */
		{ TP_DFP_SIGN, ENT_DFP_SIGN, DFP_SIGN,   1, 16 },	/* ia32_DSIGN */
		{ TP_SFP_ABS,  ENT_SFP_ABS,  SFP_ABS,    0, 16 },	/* ia32_SABS */
		{ TP_DFP_ABS,  ENT_DFP_ABS,  DFP_ABS,    1, 16 },	/* ia32_DABS */
		{ TP_INT_MAX,  ENT_INT_MAX,  DFP_INTMAX, 2, 4 }		/* ia32_INTMAX */
404
	};
405
	static ir_entity *ent_cache[ia32_known_const_max];
406
407

	const char    *tp_name, *ent_name, *cnst_str;
408
409
410
	ir_type       *tp;
	ir_node       *cnst;
	ir_graph      *rem;
411
	ir_entity     *ent;
412
	tarval        *tv;
Michael Beck's avatar
BugFix:    
Michael Beck committed
413
	ir_mode       *mode;
414

Christian Würdig's avatar
Christian Würdig committed
415
	ent_name = names[kct].ent_name;
416
417
418
	if (! ent_cache[kct]) {
		tp_name  = names[kct].tp_name;
		cnst_str = names[kct].cnst_str;
419

420
421
422
423
424
		switch (names[kct].mode) {
		case 0:  mode = mode_Iu; break;
		case 1:  mode = mode_Lu; break;
		default: mode = mode_F; break;
		}
425
		tv  = new_tarval_from_str(cnst_str, strlen(cnst_str), mode);
426
		tp  = new_type_primitive(new_id_from_str(tp_name), mode);
427
428
429
		/* set the specified alignment */
		set_type_alignment_bytes(tp, names[kct].align);

430
431
432
433
434
435
436
437
438
439
440
		ent = new_entity(get_glob_type(), new_id_from_str(ent_name), tp);

		set_entity_ld_ident(ent, get_entity_ident(ent));
		set_entity_visibility(ent, visibility_local);
		set_entity_variability(ent, variability_constant);
		set_entity_allocation(ent, allocation_static);

		/* we create a new entity here: It's initialization must resist on the
		    const code irg */
		rem = current_ir_graph;
		current_ir_graph = get_const_code_irg();
441
		cnst = new_Const(mode, tv);
442
443
444
445
		current_ir_graph = rem;

		set_atomic_ent_value(ent, cnst);

446
447
		/* cache the entry */
		ent_cache[kct] = ent;
448
	}
449

450
	return ent_cache[kct];
451
452
}

Christian Würdig's avatar
Christian Würdig committed
453
454
455
456
#ifndef NDEBUG
/**
 * Prints the old node name on cg obst and returns a pointer to it.
 */
Christian Würdig's avatar
Christian Würdig committed
457
458
const char *ia32_get_old_node_name(ia32_code_gen_t *cg, ir_node *irn) {
	ia32_isa_t *isa = (ia32_isa_t *)cg->arch_env->isa;
459

Christian Würdig's avatar
Christian Würdig committed
460
	lc_eoprintf(firm_get_arg_env(), isa->name_obst, "%+F", irn);
Christian Würdig's avatar
Christian Würdig committed
461
462
463
464
	obstack_1grow(isa->name_obst, 0);
 	return obstack_finish(isa->name_obst);
}
#endif /* NDEBUG */
Christian Würdig's avatar
Christian Würdig committed
465

466
int use_source_address_mode(ir_node *block, ir_node *node, ir_node *other)
467
{
468
	ir_mode *mode = get_irn_mode(node);
469
470
471
	ir_node *load;
	long     pn;

472
473
474
475
476
477
	/* float constants are always available */
	if(is_Const(node) && mode_is_float(mode)
			&& !is_simple_x87_Const(node) && get_irn_n_edges(node) == 1) {
		return 1;
	}

478
479
480
481
482
483
484
485
486
487
488
489
	if(!is_Proj(node))
		return 0;
	load = get_Proj_pred(node);
	pn   = get_Proj_proj(node);
	if(!is_Load(load) || pn != pn_Load_res)
		return 0;
	if(get_nodes_block(load) != block)
		return 0;
	/* we only use address mode if we're the only user of the load */
	if(get_irn_n_edges(node) > 1)
		return 0;

490
	if(other != NULL && get_Load_mode(load) != get_irn_mode(other))
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
		return 0;

	/* don't do AM if other node inputs depend on the load (via mem-proj) */
	if(other != NULL && get_nodes_block(other) == block
			&& heights_reachable_in_block(heights, other, load))
		return 0;

	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;
	ia32_op_type_t  op_type;
	ir_node        *new_op1;
	ir_node        *new_op2;
	int             commutative;
510
	int             ins_permuted;
511
512
513
514
};

static void build_address(ia32_address_mode_t *am, ir_node *node)
{
515
516
517
518
519
520
	ir_node        *noreg_gp = ia32_new_NoReg_gp(env_cg);
	ia32_address_t *addr     = &am->addr;
	ir_node        *load;
	ir_node        *ptr;
	ir_node        *mem;
	ir_node        *new_mem;
521
522
523
	ir_node        *base;
	ir_node        *index;

524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
	if(is_Const(node)) {
		ir_entity *entity  = create_float_const_entity(node);
		addr->base         = noreg_gp;
		addr->index        = noreg_gp;
		addr->mem          = new_NoMem();
		addr->symconst_ent = entity;
		addr->use_frame    = 1;
		am->ls_mode        = get_irn_mode(node);
		return;
	}

	load         = get_Proj_pred(node);
	ptr          = get_Load_ptr(load);
	mem          = get_Load_mem(load);
	new_mem      = be_transform_node(mem);
539
540
541
542
543
544
545
546
547
	am->ls_mode  = get_Load_mode(load);
	am->mem_proj = be_get_Proj_for_pn(load, pn_Load_M);

	/* construct load address */
	ia32_create_address_mode(addr, ptr, 0);
	base  = addr->base;
	index = addr->index;

	if(base == NULL) {
548
		base = noreg_gp;
549
550
551
552
553
	} else {
		base = be_transform_node(base);
	}

	if(index == NULL) {
554
		index = noreg_gp;
555
	} else {
556
		index = be_transform_node(index);
557
	}
558
559
560
561

	addr->base  = base;
	addr->index = index;
	addr->mem   = new_mem;
562
563
}

564
565
566
567
568
569
570
571
572
573
static void set_address(ir_node *node, ia32_address_t *addr)
{
	set_ia32_am_scale(node, addr->scale);
	set_ia32_am_sc(node, addr->symconst_ent);
	set_ia32_am_offs_int(node, addr->offset);
	if(addr->symconst_sign)
		set_ia32_am_sc_sign(node);
	if(addr->use_frame)
		set_ia32_use_frame(node);
	set_ia32_frame_ent(node, addr->frame_entity);
574
575
}

576
577
578
static void set_am_attributes(ir_node *node, ia32_address_mode_t *am)
{
	set_address(node, &am->addr);
579

580
581
582
583
584
	set_ia32_op_type(node, am->op_type);
	set_ia32_ls_mode(node, am->ls_mode);
	if(am->commutative)
		set_ia32_commutative(node);
}
585

586
587
588
589
typedef enum {
	match_commutative       = 1 << 0,
	match_am_and_immediates = 1 << 1,
	match_no_am             = 1 << 2,
590
591
	match_8_bit_am          = 1 << 3,
	match_16_bit_am         = 1 << 4,
592
593
	match_no_immediate      = 1 << 5,
	match_force_32bit_op    = 1 << 6
594
595
} match_flags_t;

596
static void match_arguments(ia32_address_mode_t *am, ir_node *block,
597
                            ir_node *op1, ir_node *op2, match_flags_t flags)
598
599
600
601
602
{
	ia32_address_t *addr     = &am->addr;
	ir_node        *noreg_gp = ia32_new_NoReg_gp(env_cg);
	ir_node        *new_op1;
	ir_node        *new_op2;
603
	ir_mode        *mode = get_irn_mode(op2);
604
605
606
	int             use_am;
	int             commutative;
	int             use_am_and_immediates;
607
	int             use_immediate;
608
	int             mode_bits = get_mode_size_bits(mode);
609
610
611

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

612
613
614
	commutative           = (flags & match_commutative) != 0;
	use_am_and_immediates = (flags & match_am_and_immediates) != 0;
	use_am                = ! (flags & match_no_am);
615
616
617
618
619
	use_immediate         = !(flags & match_no_immediate);

	assert(op2 != NULL);
	assert(!commutative || op1 != NULL);

620
	if(mode_bits == 8 && !(flags & match_8_bit_am)) {
621
		use_am = 0;
622
623
624
	} else if(mode_bits == 16 && !(flags & match_16_bit_am)) {
		use_am = 0;
	}
625

626
	new_op2 = (use_immediate ? try_create_Immediate(op2, 0) : NULL);
627
	if(new_op2 == NULL && use_am && use_source_address_mode(block, op2, op1)) {
628
		build_address(am, op2);
629
		new_op1     = (op1 == NULL ? NULL : be_transform_node(op1));
630
631
632
633
634
		if(mode_is_float(mode)) {
			new_op2 = ia32_new_NoReg_vfp(env_cg);
		} else {
			new_op2 = noreg_gp;
		}
635
636
		am->op_type = ia32_AddrModeS;
	} else if(commutative && (new_op2 == NULL || use_am_and_immediates) &&
637
		      use_am && use_source_address_mode(block, op1, op2)) {
638
		ir_node *noreg;
639
		build_address(am, op1);
640
641
642
643
644
645
646

		if(mode_is_float(mode)) {
			noreg = ia32_new_NoReg_vfp(env_cg);
		} else {
			noreg = noreg_gp;
		}

647
		if(new_op2 != NULL) {
648
			new_op1 = noreg;
649
650
		} else {
			new_op1 = be_transform_node(op2);
651
			new_op2 = noreg;
652
			am->ins_permuted = 1;
653
654
		}
		am->op_type = ia32_AddrModeS;
655
	} else {
656
		new_op1 = (op1 == NULL ? NULL : be_transform_node(op1));
657
658
659
		if(new_op2 == NULL)
			new_op2 = be_transform_node(op2);
		am->op_type = ia32_Normal;
660
661
662
663
664
		if(flags & match_force_32bit_op) {
			am->ls_mode = mode_Iu;
		} else {
			am->ls_mode = get_irn_mode(op2);
		}
665
	}
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
	if(addr->base == NULL)
		addr->base = noreg_gp;
	if(addr->index == NULL)
		addr->index = noreg_gp;
	if(addr->mem == NULL)
		addr->mem = new_NoMem();

	am->new_op1     = new_op1;
	am->new_op2     = new_op2;
	am->commutative = commutative;
}

static ir_node *fix_mem_proj(ir_node *node, ia32_address_mode_t *am)
{
	ir_graph *irg = current_ir_graph;
	ir_mode  *mode;
	ir_node  *load;
683

684
685
686
687
688
689
690
691
692
693
694
695
	if(am->mem_proj == NULL)
		return node;

	/* we have to create a mode_T so the old MemProj can attach to us */
	mode = get_irn_mode(node);
	load = get_Proj_pred(am->mem_proj);

	mark_irn_visited(load);
	be_set_transformed_node(load, node);

	if(mode != mode_T) {
		set_irn_mode(node, mode_T);
696
		return new_rd_Proj(NULL, irg, get_nodes_block(node), node, mode, pn_ia32_res);
697
698
699
	} else {
		return node;
	}
700
}
701
702
703
704
705
706
707
708
709

/**
 * Construct a standard binary operation, set AM and immediate if required.
 *
 * @param op1   The first operand
 * @param op2   The second operand
 * @param func  The node constructor function
 * @return The constructed ia32 node.
 */
710
static ir_node *gen_binop(ir_node *node, ir_node *op1, ir_node *op2,
711
                          construct_binop_func *func, match_flags_t flags)
712
{
713
714
	ir_node  *block     = get_nodes_block(node);
	ir_node  *new_block = be_transform_node(block);
715
716
	ir_graph *irg       = current_ir_graph;
	dbg_info *dbgi      = get_irn_dbg_info(node);
717
	ir_node  *new_node;
718
719
	ia32_address_mode_t  am;
	ia32_address_t      *addr = &am.addr;
720

721
	flags |= match_force_32bit_op;
722

723
	match_arguments(&am, block, op1, op2, flags);
724

725
	new_node = func(dbgi, irg, new_block, addr->base, addr->index, addr->mem,
726
	                am.new_op1, am.new_op2);
727
728
729
730
	set_am_attributes(new_node, &am);
	/* we can't use source address mode anymore when using immediates */
	if(is_ia32_Immediate(am.new_op1) || is_ia32_Immediate(am.new_op2))
		set_ia32_am_support(new_node, ia32_am_None, ia32_am_arity_none);
Michael Beck's avatar
Michael Beck committed
731
	SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
732
733

	new_node = fix_mem_proj(new_node, &am);
Christian Würdig's avatar
Christian Würdig committed
734

735
	return new_node;
736
737
}

738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
enum {
	n_ia32_l_binop_left,
	n_ia32_l_binop_right,
	n_ia32_l_binop_eflags
};
COMPILETIME_ASSERT(n_ia32_l_binop_left   == n_ia32_l_Adc_left,   n_Adc_left)
COMPILETIME_ASSERT(n_ia32_l_binop_right  == n_ia32_l_Adc_right,  n_Adc_right)
COMPILETIME_ASSERT(n_ia32_l_binop_eflags == n_ia32_l_Adc_eflags, n_Adc_eflags)
COMPILETIME_ASSERT(n_ia32_l_binop_left   == n_ia32_l_Sbb_left,   n_Sbb_left)
COMPILETIME_ASSERT(n_ia32_l_binop_right  == n_ia32_l_Sbb_right,  n_Sbb_right)
COMPILETIME_ASSERT(n_ia32_l_binop_eflags == n_ia32_l_Sbb_eflags, n_Sbb_eflags)

/**
 * Construct a binary operation which also consumes the eflags.
 *
 * @param node  The node to transform
 * @param func  The node constructor function
 * @param flags The match flags
 * @return      The constructor ia32 node
 */
static ir_node *gen_binop_flags(ir_node *node, construct_binop_flags_func *func,
                                match_flags_t flags)
{
	ir_node             *src_block  = get_nodes_block(node);
	ir_node             *block      = be_transform_node(src_block);
	ir_node             *op1        = get_irn_n(node, n_ia32_l_binop_left);
	ir_node             *op2        = get_irn_n(node, n_ia32_l_binop_right);
	ir_node             *eflags     = get_irn_n(node, n_ia32_l_binop_eflags);
	ir_node             *new_eflags = be_transform_node(eflags);
	ir_graph            *irg        = current_ir_graph;
	dbg_info            *dbgi       = get_irn_dbg_info(node);
	ir_node             *new_node;
	ia32_address_mode_t  am;
	ia32_address_t      *addr       = &am.addr;

	match_arguments(&am, src_block, op1, op2, flags);

	new_node = func(dbgi, irg, block, addr->base, addr->index,
	                           addr->mem, am.new_op1, am.new_op2, new_eflags);
	set_am_attributes(new_node, &am);
	/* we can't use source address mode anymore when using immediates */
	if(is_ia32_Immediate(am.new_op1) || is_ia32_Immediate(am.new_op2))
		set_ia32_am_support(new_node, ia32_am_None, ia32_am_arity_none);
	SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));

	new_node = fix_mem_proj(new_node, &am);

	return new_node;
}

788
789
790
791
792
793
794
795
/**
 * Construct a standard binary operation, set AM and immediate if required.
 *
 * @param op1   The first operand
 * @param op2   The second operand
 * @param func  The node constructor function
 * @return The constructed ia32 node.
 */
Matthias Braun's avatar
Matthias Braun committed
796
static ir_node *gen_binop_sse_float(ir_node *node, ir_node *op1, ir_node *op2,
797
                                    construct_binop_func *func,
798
                                    match_flags_t flags)
799
{
800
801
802
803
804
805
806
807
808
809
810
811
812
	ir_node  *block     = get_nodes_block(node);
	ir_node  *new_block = be_transform_node(block);
	dbg_info *dbgi      = get_irn_dbg_info(node);
	ir_graph *irg       = current_ir_graph;
	ir_node  *new_node;
	ia32_address_mode_t  am;
	ia32_address_t      *addr = &am.addr;

	match_arguments(&am, block, op1, op2, flags);

	new_node = func(dbgi, irg, new_block, addr->base, addr->index, addr->mem,
	                am.new_op1, am.new_op2);
	set_am_attributes(new_node, &am);
813

Michael Beck's avatar
Michael Beck committed
814
	SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
815

816
817
	new_node = fix_mem_proj(new_node, &am);

818
819
	return new_node;
}
820

821
822
823
824
825
826
827
828
829
830
831
832
833
static ir_node *get_fpcw(void)
{
	ir_node *fpcw;
	if(initial_fpcw != NULL)
		return initial_fpcw;

	fpcw         = be_abi_get_ignore_irn(env_cg->birg->abi,
	                                     &ia32_fp_cw_regs[REG_FPCW]);
	initial_fpcw = be_transform_node(fpcw);

	return initial_fpcw;
}

Matthias Braun's avatar
Matthias Braun committed
834
835
836
837
838
839
840
841
842
/**
 * Construct a standard binary operation, set AM and immediate if required.
 *
 * @param op1   The first operand
 * @param op2   The second operand
 * @param func  The node constructor function
 * @return The constructed ia32 node.
 */
static ir_node *gen_binop_x87_float(ir_node *node, ir_node *op1, ir_node *op2,
843
                                    construct_binop_float_func *func,
844
                                    match_flags_t flags)
Matthias Braun's avatar
Matthias Braun committed
845
{
846
847
	ir_graph *irg       = current_ir_graph;
	dbg_info *dbgi      = get_irn_dbg_info(node);
848
849
	ir_node  *block     = get_nodes_block(node);
	ir_node  *new_block = be_transform_node(block);
850
851
852
853
	ir_node  *new_node;
	ia32_address_mode_t  am;
	ia32_address_t      *addr = &am.addr;

854
	match_arguments(&am, block, op1, op2, flags);
855
856
857
858

	new_node = func(dbgi, irg, new_block, addr->base, addr->index, addr->mem,
	                am.new_op1, am.new_op2, get_fpcw());
	set_am_attributes(new_node, &am);
Matthias Braun's avatar
Matthias Braun committed
859
860
861

	SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));

862
863
	new_node = fix_mem_proj(new_node, &am);

Matthias Braun's avatar
Matthias Braun committed
864
865
	return new_node;
}
866
867
868
869
870
871
872
873
874

/**
 * Construct a shift/rotate binary operation, sets AM and immediate if required.
 *
 * @param op1   The first operand
 * @param op2   The second operand
 * @param func  The node constructor function
 * @return The constructed ia32 node.
 */
875
static ir_node *gen_shift_binop(ir_node *node, ir_node *op1, ir_node *op2,
876
                                construct_shift_func *func)
877
{
878
879
880
881
882
883
884
	dbg_info *dbgi      = get_irn_dbg_info(node);
	ir_graph *irg       = current_ir_graph;
	ir_node  *block     = get_nodes_block(node);
	ir_node  *new_block = be_transform_node(block);
	ir_node  *new_op1   = be_transform_node(op1);
	ir_node  *new_op2   = create_immediate_or_transform(op2, 0);
	ir_node  *res;
885

886
887
	assert(! mode_is_float(get_irn_mode(node))
	         && "Shift/Rotate with float not supported");
888

889
890
	res = func(dbgi, irg, new_block, new_op1, new_op2);
	SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
891

892
893
894
895
	/* lowered shift instruction may have a dependency operand, handle it here */
	if (get_irn_arity(node) == 3) {
		/* we have a dependency */
		ir_node *new_dep = be_transform_node(get_irn_n(node, 2));
896
		add_irn_dep(res, new_dep);
897
898
	}

899
	return res;
900
901
902
903
904
905
906
907
908
909
}


/**
 * Construct a standard unary operation, set AM and immediate if required.
 *
 * @param op    The operand
 * @param func  The node constructor function
 * @return The constructed ia32 node.
 */
910
static ir_node *gen_unop(ir_node *node, ir_node *op, construct_unop_func *func)
911
{
Michael Beck's avatar
Michael Beck committed
912
913
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *new_op   = be_transform_node(op);
914
	ir_node  *new_node = NULL;
Michael Beck's avatar
Michael Beck committed
915
	ir_graph *irg      = current_ir_graph;
916
	dbg_info *dbgi     = get_irn_dbg_info(node);
917

918
	new_node = func(dbgi, irg, block, new_op);
Christian Würdig's avatar
Christian Würdig committed
919

Michael Beck's avatar
Michael Beck committed
920
	SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
921

922
	return new_node;
923
924
}

925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
static ir_node *create_lea_from_address(dbg_info *dbgi,	ir_node *block,
                                        ia32_address_t *addr)
{
	ir_graph *irg   = current_ir_graph;
	ir_node  *base  = addr->base;
	ir_node  *index = addr->index;
	ir_node  *res;

	if(base == NULL) {
		base = ia32_new_NoReg_gp(env_cg);
	} else {
		base = be_transform_node(base);
	}

	if(index == NULL) {
		index = ia32_new_NoReg_gp(env_cg);
	} else {
		index = be_transform_node(index);
	}

	res = new_rd_ia32_Lea(dbgi, irg, block, base, index);
	set_address(res, addr);

	return res;
}

static int am_has_immediates(const ia32_address_t *addr)
{
	return addr->offset != 0 || addr->symconst_ent != NULL
		|| addr->frame_entity || addr->use_frame;
}

957
958
959
960
961
/**
 * Creates an ia32 Add.
 *
 * @return the created ia32 Add node
 */
962
static ir_node *gen_Add(ir_node *node) {
963
964
965
966
967
968
969
970
971
	ir_graph *irg       = current_ir_graph;
	dbg_info *dbgi      = get_irn_dbg_info(node);
	ir_node  *block     = get_nodes_block(node);
	ir_node  *new_block = be_transform_node(block);
	ir_node  *op1       = get_Add_left(node);
	ir_node  *op2       = get_Add_right(node);
	ir_mode  *mode      = get_irn_mode(node);
	ir_node  *noreg     = ia32_new_NoReg_gp(env_cg);
	ir_node  *new_node;
972
973
974
975
	ir_node  *new_op1;
	ir_node  *add_immediate_op;
	ia32_address_t       addr;
	ia32_address_mode_t  am;
Christian Würdig's avatar
Christian Würdig committed
976
977

	if (mode_is_float(mode)) {
Michael Beck's avatar
Michael Beck committed
978
		if (USE_SSE2(env_cg))
979
			return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xAdd, match_commutative);
980
		else
981
			return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfadd, match_commutative);
Christian Würdig's avatar
Christian Würdig committed
982
	}
Christian Würdig's avatar
Christian Würdig committed
983

984
985
986
987
988
989
990
991
992
993
994
995
	/**
	 * Rules for an Add:
	 *   0. Immediate Trees (example Add(Symconst, Const) -> Const)
	 *   1. Add with immediate -> Lea
	 *   2. Add with possible source address mode -> Add
	 *   3. Otherwise -> Lea
	 */
	memset(&addr, 0, sizeof(addr));
	ia32_create_address_mode(&addr, node, 1);
	add_immediate_op = NULL;
	/* a constant? */
	if(addr.base == NULL && addr.index == NULL) {
996
997
998
999
1000
		new_node = new_rd_ia32_Const(dbgi, irg, new_block, addr.symconst_ent,
		                             addr.symconst_sign, addr.offset);
		add_irn_dep(new_node, get_irg_frame(irg));
		SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
		return new_node;
For faster browsing, not all history is shown. View entire blame