ia32_transform.c 130 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
76
77
78
79
80
81
82
83
84
85
#define SFP_SIGN "0x80000000"
#define DFP_SIGN "0x8000000000000000"
#define SFP_ABS  "0x7FFFFFFF"
#define DFP_ABS  "0x7FFFFFFFFFFFFFFF"

#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"

#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"

86
87
88
#define mode_vfp	(ia32_reg_classes[CLASS_ia32_vfp].mode)
#define mode_xmm    (ia32_reg_classes[CLASS_ia32_xmm].mode)

89
90
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

91
/** hold the current code generator during transformation */
92
93
static ia32_code_gen_t *env_cg       = NULL;
static ir_node         *initial_fpcw = NULL;
94
static heights_t       *heights      = NULL;
95

96
97
extern ir_op *get_op_Mulh(void);

98
99
100
typedef ir_node *construct_binop_func(dbg_info *db, ir_graph *irg,
        ir_node *block, ir_node *base, ir_node *index, ir_node *op1,
        ir_node *op2, ir_node *mem);
Christian Würdig's avatar
Christian Würdig committed
101

102
103
104
105
106
107
108
109
110
111
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,
        ir_node *block, ir_node *base, ir_node *index, ir_node *op,
        ir_node *mem);

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
112
113
114
115
typedef ir_node *construct_binop_float_func(dbg_info *db, ir_graph *irg,
        ir_node *block, ir_node *base, ir_node *index, ir_node *op1,
        ir_node *op2, ir_node *mem, ir_node *fpcw);

116
typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg,
117
        ir_node *block, ir_node *op);
118

Christian Würdig's avatar
Christian Würdig committed
119
120
121
122
123
124
125
126
127
128
/****************************************************************************************************
 *                  _        _                        __                           _   _
 *                 | |      | |                      / _|                         | | (_)
 *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
 * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
 * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
 * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
 *
 ****************************************************************************************************/

129
130
static ir_node *try_create_Immediate(ir_node *node,
                                     char immediate_constraint_type);
131

132
133
134
static ir_node *create_immediate_or_transform(ir_node *node,
                                              char immediate_constraint_type);

135
136
137
138
static ir_node *create_I2I_Conv(ir_mode *src_mode, ir_mode *tgt_mode,
                                dbg_info *dbgi, ir_node *new_block,
                                ir_node *new_op);

139
140
141
142
/**
 * Return true if a mode can be stored in the GP register set
 */
static INLINE int mode_needs_gp_reg(ir_mode *mode) {
143
144
	if(mode == mode_fpcw)
		return 0;
145
	return mode_is_int(mode) || mode_is_reference(mode) || mode == mode_b;
146
147
}

148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
/**
 * 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);
175
		set_type_alignment_bytes(res, 16);
176
177
178
179
180
181
182
183
		pmap_insert(types, mode, res);
	}
	else
		res = e->value;
	return res;
}

/**
184
 * Get an atomic entity that is initialized with a tarval
185
 */
186
static ir_entity *ia32_get_entity_for_tv(ia32_isa_t *isa, ir_node *cnst)
187
188
{
	tarval *tv    = get_Const_tarval(cnst);
189
	pmap_entry *e = pmap_find(isa->tv_ent, tv);
190
191
192
193
194
195
196
	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)
197
			tp = get_prim_type(isa->types, mode);
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212

		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;

213
		pmap_insert(isa->tv_ent, tv, res);
214
	} else {
215
		res = e->value;
216
217
	}

218
219
220
	return res;
}

221
222
223
224
225
226
227
228
229
230
231
232
233
234
static int is_Const_0(ir_node *node) {
	if(!is_Const(node))
		return 0;

	return classify_Const(node) == CNST_NULL;
}

static int is_Const_1(ir_node *node) {
	if(!is_Const(node))
		return 0;

	return classify_Const(node) == CNST_ONE;
}

235
static int is_Const_Minus_1(ir_node *node) {
Matthias Braun's avatar
Matthias Braun committed
236
237
	tarval  *tv;
	ir_mode *mode;
238
239
240
	if(!is_Const(node))
		return 0;

Matthias Braun's avatar
Matthias Braun committed
241
242
243
244
	mode = get_irn_mode(node);
	if(!mode_is_signed(mode))
		return 0;

245
246
247
248
249
250
	tv = get_Const_tarval(node);
	tv = tarval_neg(tv);

	return classify_tarval(tv) == CNST_ONE;
}

251
252
253
/**
 * Transforms a Const.
 */
254
static ir_node *gen_Const(ir_node *node) {
255
256
257
258
259
	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);
260
261

	if (mode_is_float(mode)) {
262
		ir_node   *res   = NULL;
Michael Beck's avatar
Michael Beck committed
263
		ir_node   *noreg = ia32_new_NoReg_gp(env_cg);
264
265
		ir_node   *nomem = new_NoMem();
		ir_node   *load;
266
		ir_entity *floatent;
267
		cnst_classify_t clss = classify_Const(node);
268

269
270
271
272
273
274
275
		if (USE_SSE2(env_cg)) {
			if (clss == CNST_NULL) {
				load = new_rd_ia32_xZero(dbgi, irg, block);
				set_ia32_ls_mode(load, mode);
				res  = load;
			} else {
				floatent = ia32_get_entity_for_tv(env_cg->isa, node);
276

277
278
279
280
281
282
283
284
				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 {
285
			if (clss == CNST_NULL) {
286
				load = new_rd_ia32_vfldz(dbgi, irg, block);
287
				res  = load;
288
			} else if (clss == CNST_ONE) {
289
				load = new_rd_ia32_vfld1(dbgi, irg, block);
290
				res  = load;
291
			} else {
292
				floatent = ia32_get_entity_for_tv(env_cg->isa, node);
293

Matthias Braun's avatar
Matthias Braun committed
294
				load     = new_rd_ia32_vfld(dbgi, irg, block, noreg, noreg, nomem, mode);
295
				set_ia32_op_type(load, ia32_AddrModeS);
296
				set_ia32_am_sc(load, floatent);
297
298
				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);
299
			}
300
			set_ia32_ls_mode(load, mode);
301
302
		}

Michael Beck's avatar
Michael Beck committed
303
		SET_IA32_ORIG_NODE(load, ia32_get_old_node_name(env_cg, node));
304
305

		/* Const Nodes before the initial IncSP are a bad idea, because
306
307
308
		 * 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.
309
310
311
312
313
		 */
		if (get_irg_start_block(irg) == block) {
			add_irn_dep(load, get_irg_frame(irg));
		}

Michael Beck's avatar
Michael Beck committed
314
		SET_IA32_ORIG_NODE(load, ia32_get_old_node_name(env_cg, node));
315
316
		return res;
	} else {
317
318
319
320
321
322
323
324
325
326
327
328
329
330
		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));
331
332
333
334
335
336
337
338
339
340
341
342
343

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

		return cnst;
	}
}

/**
 * Transforms a SymConst.
 */
344
static ir_node *gen_SymConst(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
345
	ir_graph *irg   = current_ir_graph;
346
347
	ir_node  *old_block = get_nodes_block(node);
	ir_node  *block = be_transform_node(old_block);
348
349
	dbg_info *dbgi  = get_irn_dbg_info(node);
	ir_mode  *mode  = get_irn_mode(node);
350
351
352
	ir_node  *cnst;

	if (mode_is_float(mode)) {
353
354
355
		ir_node *noreg = ia32_new_NoReg_gp(env_cg);
		ir_node *nomem = new_NoMem();

Michael Beck's avatar
Michael Beck committed
356
		if (USE_SSE2(env_cg))
357
			cnst = new_rd_ia32_xLoad(dbgi, irg, block, noreg, noreg, nomem, mode_E);
358
		else
359
360
			cnst = new_rd_ia32_vfld(dbgi, irg, block, noreg, noreg, nomem, mode_E);
		set_ia32_am_sc(cnst, get_SymConst_entity(node));
361
	} else {
Michael Beck's avatar
Michael Beck committed
362
363
		ir_entity *entity;

364
365
366
		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
367
		entity = get_SymConst_entity(node);
368
		cnst = new_rd_ia32_Const(dbgi, irg, block, entity, 0, 0);
369
370
371
372
373
374
375
376
377
	}

	/* 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
378
	SET_IA32_ORIG_NODE(cnst, ia32_get_old_node_name(env_cg, node));
379
380
381
382

	return cnst;
}

383
/* Generates an entity for a known FP const (used for FP Neg + Abs) */
384
ir_entity *ia32_gen_fp_known_const(ia32_known_const_t kct) {
385
386
387
388
389
390
391
392
393
394
	static const struct {
		const char *tp_name;
		const char *ent_name;
		const char *cnst_str;
	} names [ia32_known_const_max] = {
		{ TP_SFP_SIGN, ENT_SFP_SIGN, SFP_SIGN },	/* ia32_SSIGN */
		{ TP_DFP_SIGN, ENT_DFP_SIGN, DFP_SIGN },	/* ia32_DSIGN */
		{ TP_SFP_ABS,  ENT_SFP_ABS,  SFP_ABS },		/* ia32_SABS */
		{ TP_DFP_ABS,  ENT_DFP_ABS,  DFP_ABS }		/* ia32_DABS */
	};
395
	static ir_entity *ent_cache[ia32_known_const_max];
396
397

	const char    *tp_name, *ent_name, *cnst_str;
398
399
400
	ir_type       *tp;
	ir_node       *cnst;
	ir_graph      *rem;
401
	ir_entity     *ent;
402
	tarval        *tv;
Michael Beck's avatar
BugFix:    
Michael Beck committed
403
	ir_mode       *mode;
404

Christian Würdig's avatar
Christian Würdig committed
405
	ent_name = names[kct].ent_name;
406
407
408
	if (! ent_cache[kct]) {
		tp_name  = names[kct].tp_name;
		cnst_str = names[kct].cnst_str;
409

410
411
		mode = kct == ia32_SSIGN || kct == ia32_SABS ? mode_Iu : mode_Lu;
		//mode = mode_xmm;
412
		tv  = new_tarval_from_str(cnst_str, strlen(cnst_str), mode);
413
		tp  = new_type_primitive(new_id_from_str(tp_name), mode);
414
415
416
		/* these constants are loaded as part of an instruction, so they must be aligned
		   to 128 bit. */
		set_type_alignment_bytes(tp, 16);
417
418
419
420
421
422
423
424
425
426
427
		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();
428
		cnst = new_Const(mode, tv);
429
430
431
432
		current_ir_graph = rem;

		set_atomic_ent_value(ent, cnst);

433
434
		/* cache the entry */
		ent_cache[kct] = ent;
435
	}
436

437
	return ent_cache[kct];
438
439
}

Christian Würdig's avatar
Christian Würdig committed
440
441
442
443
#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
444
445
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;
446

Christian Würdig's avatar
Christian Würdig committed
447
	lc_eoprintf(firm_get_arg_env(), isa->name_obst, "%+F", irn);
Christian Würdig's avatar
Christian Würdig committed
448
449
450
451
	obstack_1grow(isa->name_obst, 0);
 	return obstack_finish(isa->name_obst);
}
#endif /* NDEBUG */
Christian Würdig's avatar
Christian Würdig committed
452

453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
static int use_source_address_mode(ir_node *block, ir_node *node,
                                   ir_node *other)
{
	ir_mode *mode;
	ir_node *load;
	long     pn;

	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;

	mode = get_irn_mode(node);
	if(!mode_needs_gp_reg(mode))
		return 0;
	if(get_mode_size_bits(mode) != 32)
		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;
	int             flipped;
};

static void build_address(ia32_address_mode_t *am, ir_node *node)
{
	ia32_address_t *addr    = &am->addr;
	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);
	ir_node        *base;
	ir_node        *index;

	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) {
		base = ia32_new_NoReg_gp(env_cg);
	} else {
		base = be_transform_node(base);
	}

	if(index == NULL) {
		index = ia32_new_NoReg_gp(env_cg);
524
	} else {
525
		index = be_transform_node(index);
526
	}
527
528
529
530

	addr->base  = base;
	addr->index = index;
	addr->mem   = new_mem;
531
532
}

533
534
535
536
537
538
539
540
541
542
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);
543
544
}

545
546
547
static void set_am_attributes(ir_node *node, ia32_address_mode_t *am)
{
	set_address(node, &am->addr);
548

549
550
551
552
553
	set_ia32_op_type(node, am->op_type);
	set_ia32_ls_mode(node, am->ls_mode);
	if(am->commutative)
		set_ia32_commutative(node);
}
554

555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
static void match_arguments(ia32_address_mode_t *am, ir_node *block,
                            ir_node *op1, ir_node *op2, int commutative,
                            int use_am_and_immediates)
{
	ia32_address_t *addr     = &am->addr;
	ir_node        *noreg_gp = ia32_new_NoReg_gp(env_cg);
	ir_node        *new_op1;
	ir_node        *new_op2;

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

	new_op2 = try_create_Immediate(op2, 0);
	if(new_op2 == NULL && use_source_address_mode(block, op2, op1)) {
		build_address(am, op2);
		new_op1     = be_transform_node(op1);
		new_op2     = noreg_gp;
		am->op_type = ia32_AddrModeS;
	} else if(commutative && (new_op2 == NULL || use_am_and_immediates) &&
		      use_source_address_mode(block, op1, op2)) {
		build_address(am, op1);
		if(new_op2 != NULL) {
			new_op1 = noreg_gp;
		} else {
			new_op1 = be_transform_node(op2);
			new_op2 = noreg_gp;
			am->flipped = 1;
		}
		am->op_type = ia32_AddrModeS;
583
	} else {
584
585
586
587
		new_op1 = be_transform_node(op1);
		if(new_op2 == NULL)
			new_op2 = be_transform_node(op2);
		am->op_type = ia32_Normal;
588
	}
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
	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;
606

607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
	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);
		return new_rd_Proj(NULL, irg, get_nodes_block(node), node, mode, 0);
	} else {
		return node;
	}
623
}
624
625
626
627
628
629
630
631
632

/**
 * 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.
 */
633
static ir_node *gen_binop(ir_node *node, ir_node *op1, ir_node *op2,
634
                          construct_binop_func *func, int commutative)
635
{
636
637
638
639
	ir_node  *src_block = get_nodes_block(node);
	ir_node  *block     = be_transform_node(src_block);
	ir_graph *irg       = current_ir_graph;
	dbg_info *dbgi      = get_irn_dbg_info(node);
640
	ir_node  *new_node;
641
642
	ia32_address_mode_t  am;
	ia32_address_t      *addr = &am.addr;
643

644
	match_arguments(&am, src_block, op1, op2, commutative, 0);
645

646
647
648
649
650
651
	new_node = func(dbgi, irg, block, addr->base, addr->index, am.new_op1,
	                am.new_op2, addr->mem);
	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
652
	SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
653
654

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

656
	return new_node;
657
658
}

659
660
661
662
663
664
665
666
/**
 * 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
667
668
static ir_node *gen_binop_sse_float(ir_node *node, ir_node *op1, ir_node *op2,
                                    construct_binop_func *func)
669
{
Michael Beck's avatar
Michael Beck committed
670
671
672
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *new_op1  = be_transform_node(op1);
	ir_node  *new_op2  = be_transform_node(op2);
673
	ir_node  *new_node = NULL;
674
	dbg_info *dbgi     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
675
	ir_graph *irg      = current_ir_graph;
676
	ir_mode  *mode     = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
677
	ir_node  *noreg_gp = ia32_new_NoReg_gp(env_cg);
678
679
	ir_node  *nomem    = new_NoMem();

Matthias Braun's avatar
Matthias Braun committed
680
681
	new_node = func(dbgi, irg, block, noreg_gp, noreg_gp, new_op1, new_op2,
	                nomem);
682
683
684
	if (is_op_commutative(get_irn_op(node))) {
		set_ia32_commutative(new_node);
	}
685
	set_ia32_ls_mode(new_node, mode);
686

Michael Beck's avatar
Michael Beck committed
687
	SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
688
689
690

	return new_node;
}
691

692
693
694
695
696
697
698
699
700
701
702
703
704
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
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
/**
 * 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,
                                    construct_binop_float_func *func)
{
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *new_op1  = be_transform_node(op1);
	ir_node  *new_op2  = be_transform_node(op2);
	ir_node  *new_node = NULL;
	dbg_info *dbgi     = get_irn_dbg_info(node);
	ir_graph *irg      = current_ir_graph;
	ir_node  *noreg_gp = ia32_new_NoReg_gp(env_cg);
	ir_node  *nomem    = new_NoMem();

	new_node = func(dbgi, irg, block, noreg_gp, noreg_gp, new_op1, new_op2,
726
	                nomem, get_fpcw());
Matthias Braun's avatar
Matthias Braun committed
727
728
729
730
731
732
733
734
	if (is_op_commutative(get_irn_op(node))) {
		set_ia32_commutative(new_node);
	}

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

	return new_node;
}
735
736
737
738
739
740
741
742
743

/**
 * 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.
 */
744
static ir_node *gen_shift_binop(ir_node *node, ir_node *op1, ir_node *op2,
745
                                construct_shift_func *func)
746
{
747
748
749
750
751
752
753
	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;
754

755
756
	assert(! mode_is_float(get_irn_mode(node))
	         && "Shift/Rotate with float not supported");
757

758
759
	res = func(dbgi, irg, new_block, new_op1, new_op2);
	SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
760

761
762
763
764
	/* 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));
765
		add_irn_dep(res, new_dep);
766
767
	}

768
	return res;
769
770
771
772
773
774
775
776
777
778
}


/**
 * 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.
 */
779
static ir_node *gen_unop(ir_node *node, ir_node *op, construct_unop_func *func)
780
{
Michael Beck's avatar
Michael Beck committed
781
782
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *new_op   = be_transform_node(op);
783
	ir_node  *new_node = NULL;
Michael Beck's avatar
Michael Beck committed
784
	ir_graph *irg      = current_ir_graph;
785
	dbg_info *dbgi     = get_irn_dbg_info(node);
786

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

Michael Beck's avatar
Michael Beck committed
789
	SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
790

791
	return new_node;
792
793
}

794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
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;
}

826
827
828
829
830
/**
 * Creates an ia32 Add.
 *
 * @return the created ia32 Add node
 */
831
static ir_node *gen_Add(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
832
	ir_node  *block   = be_transform_node(get_nodes_block(node));
833
834
	ir_node  *op1     = get_Add_left(node);
	ir_node  *op2     = get_Add_right(node);
835
836
	ir_node  *new_op;
	ir_node  *new_op1;
Michael Beck's avatar
Michael Beck committed
837
	ir_graph *irg     = current_ir_graph;
838
839
	dbg_info *dbgi    = get_irn_dbg_info(node);
	ir_mode  *mode    = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
840
	ir_node  *noreg   = ia32_new_NoReg_gp(env_cg);
841
842
843
844
	ir_node  *src_block = get_nodes_block(node);
	ir_node  *add_immediate_op;
	ia32_address_t       addr;
	ia32_address_mode_t  am;
Christian Würdig's avatar
Christian Würdig committed
845
846

	if (mode_is_float(mode)) {
Michael Beck's avatar
Michael Beck committed
847
		if (USE_SSE2(env_cg))
Matthias Braun's avatar
Matthias Braun committed
848
			return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xAdd);
849
		else
Matthias Braun's avatar
Matthias Braun committed
850
			return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfadd);
Christian Würdig's avatar
Christian Würdig committed
851
	}
Christian Würdig's avatar
Christian Würdig committed
852

853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
	/**
	 * 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) {
		new_op = new_rd_ia32_Const(dbgi, irg, block, addr.symconst_ent,
								   addr.symconst_sign, addr.offset);
		add_irn_dep(new_op, get_irg_frame(irg));
Michael Beck's avatar
Michael Beck committed
868
		SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
869
		return new_op;
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
	}
	/* add with immediate? */
	if(addr.index == NULL) {
		add_immediate_op = addr.base;
	} else if(addr.base == NULL && addr.scale == 0) {
		add_immediate_op = addr.index;
	}

	if(add_immediate_op != NULL) {
		if(!am_has_immediates(&addr)) {
#ifdef DEBUG_libfirm
			ir_fprintf(stderr, "Optimisation warning Add x,0 (%+F) found\n",
					   node);
#endif
			return be_transform_node(add_immediate_op);
		}

		new_op = create_lea_from_address(dbgi, block, &addr);
		SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
		return new_op;
Christian Würdig's avatar
Christian Würdig committed
890
891
	}

892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
	/* test if we can use source address mode */
	memset(&am, 0, sizeof(am));
	new_op1 = NULL;
	if(use_source_address_mode(src_block, op2, op1)) {
		build_address(&am, op2);
		new_op1 = be_transform_node(op1);
	} else if(use_source_address_mode(src_block, op1, op2)) {
		build_address(&am, op1);
		new_op1 = be_transform_node(op2);
	}
	/* construct an Add with source address mode */
	if(new_op1 != NULL) {
		ia32_address_t *am_addr = &am.addr;
		new_op = new_rd_ia32_Add(dbgi, irg, block, am_addr->base,
		                         am_addr->index, new_op1, noreg, am_addr->mem);
		set_address(new_op, am_addr);
		set_ia32_op_type(new_op, ia32_AddrModeS);
		set_ia32_ls_mode(new_op, am.ls_mode);
		set_ia32_commutative(new_op);
		SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
912

913
		new_op = fix_mem_proj(new_op, &am);
914

915
916
		return new_op;
	}
917

918
919
	/* otherwise construct a lea */
	new_op = create_lea_from_address(dbgi, block, &addr);
Michael Beck's avatar
Michael Beck committed
920
	SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
921
	return new_op;
Christian Würdig's avatar
Christian Würdig committed
922
923
}

924
925
926
927
928
/**
 * Creates an ia32 Mul.
 *
 * @return the created ia32 Mul node
 */
929
static ir_node *gen_Mul(ir_node *node) {
930
931
	ir_node *op1  = get_Mul_left(node);
	ir_node *op2  = get_Mul_right(node);
932
	ir_mode *mode = get_irn_mode(node);
933

934
	if (mode_is_float(mode)) {
Michael Beck's avatar
Michael Beck committed
935
		if (USE_SSE2(env_cg))
Matthias Braun's avatar
Matthias Braun committed
936
			return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xMul);
937
		else
Matthias Braun's avatar
Matthias Braun committed
938
			return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfmul);
Christian Würdig's avatar
Christian Würdig committed
939
	}
940

941
942
943
944
945
	/*
		for the lower 32bit of the result it doesn't matter whether we use
		signed or unsigned multiplication so we use IMul as it has fewer
		constraints
	*/
946
	return gen_binop(node, op1, op2, new_rd_ia32_IMul, 1);
947
}
948
949
950
951
952
953
954
955

/**
 * Creates an ia32 Mulh.
 * Note: Mul produces a 64Bit result and Mulh returns the upper 32 bit of
 * this result while Mul returns the lower 32 bit.
 *
 * @return the created ia32 Mulh node
 */
956
static ir_node *gen_Mulh(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
957
	ir_node  *block   = be_transform_node(get_nodes_block(node));
958
	ir_node  *op1     = get_irn_n(node, 0);
Michael Beck's avatar
Michael Beck committed
959
	ir_node  *new_op1 = be_transform_node(op1);
960
	ir_node  *op2     = get_irn_n(node, 1);
Michael Beck's avatar
Michael Beck committed
961
962
	ir_node  *new_op2 = be_transform_node(op2);
	ir_graph *irg     = current_ir_graph;
963
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
964
	ir_node  *noreg   = ia32_new_NoReg_gp(env_cg);
965
	ir_mode  *mode    = get_irn_mode(node);
Matthias Braun's avatar
Matthias Braun committed
966
	ir_node  *proj_EDX, *res;
967

968
	assert(!mode_is_float(mode) && "Mulh with float not supported");
969
	if (mode_is_signed(mode)) {
Matthias Braun's avatar
Matthias Braun committed
970
971
		res = new_rd_ia32_IMul1OP(dbgi, irg, block, noreg, noreg, new_op1,
		                          new_op2, new_NoMem());
Matthias Braun's avatar
Matthias Braun committed
972
	} else {
Matthias Braun's avatar
Matthias Braun committed
973
974
		res = new_rd_ia32_Mul(dbgi, irg, block, noreg, noreg, new_op1, new_op2,
		                      new_NoMem());
Matthias Braun's avatar
Matthias Braun committed
975
	}
976

Matthias Braun's avatar
Matthias Braun committed
977
978
	set_ia32_commutative(res);

979
	proj_EDX = new_rd_Proj(dbgi, irg, block, res, mode_Iu, pn_EDX);
980
981

	return proj_EDX;
982
983
}

984
985


986
987
988
/**
 * Creates an ia32 And.
 *
989
 * @return The created ia32 And node
990
 */
991
static ir_node *gen_And(ir_node *node) {
992
993
	ir_node *op1 = get_And_left(node);
	ir_node *op2 = get_And_right(node);
994
995
	assert(! mode_is_float(get_irn_mode(node)));

996
	/* is it a zero extension? */
Michael Beck's avatar
Michael Beck committed
997
	if (is_Const(op2)) {
998
999
1000
		tarval   *tv    = get_Const_tarval(op2);
		long      v     = get_tarval_long(tv);

For faster browsing, not all history is shown. View entire blame