ia32_transform.c 128 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
22
23
24
 * @file
 * @brief       This file implements the IR transformation from firm into ia32-Firm.
 * @author      Christian Wuerdig, Matthias Braun
 * @version     $Id$
Christian Würdig's avatar
Christian Würdig committed
25
 */
26
#ifdef HAVE_CONFIG_H
27
#include "config.h"
28
29
#endif

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

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 "archop.h"
48
#include "error.h"
49

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

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

Christian Würdig's avatar
Christian Würdig committed
66
67
#include "gen_ia32_regalloc_if.h"

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#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"

83
84
85
#define mode_vfp	(ia32_reg_classes[CLASS_ia32_vfp].mode)
#define mode_xmm    (ia32_reg_classes[CLASS_ia32_xmm].mode)

86
87
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

88
/** hold the current code generator during transformation */
89
90
static ia32_code_gen_t *env_cg       = NULL;
static ir_node         *initial_fpcw = NULL;
91

92
93
extern ir_op *get_op_Mulh(void);

94
95
96
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
97

Matthias Braun's avatar
Matthias Braun committed
98
99
100
101
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);

102
103
104
typedef ir_node *construct_unop_func(dbg_info *db, ir_graph *irg,
        ir_node *block, ir_node *base, ir_node *index, ir_node *op,
        ir_node *mem);
105

Christian Würdig's avatar
Christian Würdig committed
106
107
108
109
110
111
112
113
114
115
/****************************************************************************************************
 *                  _        _                        __                           _   _
 *                 | |      | |                      / _|                         | | (_)
 *  _ __   ___   __| | ___  | |_ _ __ __ _ _ __  ___| |_ ___  _ __ _ __ ___   __ _| |_ _  ___  _ __
 * | '_ \ / _ \ / _` |/ _ \ | __| '__/ _` | '_ \/ __|  _/ _ \| '__| '_ ` _ \ / _` | __| |/ _ \| '_ \
 * | | | | (_) | (_| |  __/ | |_| | | (_| | | | \__ \ || (_) | |  | | | | | | (_| | |_| | (_) | | | |
 * |_| |_|\___/ \__,_|\___|  \__|_|  \__,_|_| |_|___/_| \___/|_|  |_| |_| |_|\__,_|\__|_|\___/|_| |_|
 *
 ****************************************************************************************************/

116
117
static ir_node *try_create_Immediate(ir_node *node,
                                     char immediate_constraint_type);
118

119
120
121
static ir_node *create_immediate_or_transform(ir_node *node,
                                              char immediate_constraint_type);

122
123
124
125
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);

126
127
128
129
/**
 * Return true if a mode can be stored in the GP register set
 */
static INLINE int mode_needs_gp_reg(ir_mode *mode) {
130
131
	if(mode == mode_fpcw)
		return 0;
132
	return mode_is_int(mode) || mode_is_reference(mode) || mode == mode_b;
133
134
}

Christian Würdig's avatar
Christian Würdig committed
135
136
137
138
/**
 * Returns 1 if irn is a Const representing 0, 0 otherwise
 */
static INLINE int is_ia32_Const_0(ir_node *irn) {
139
140
	return is_ia32_irn(irn) && is_ia32_Const(irn) && get_ia32_immop_type(irn) == ia32_ImmConst
	       && tarval_is_null(get_ia32_Immop_tarval(irn));
Christian Würdig's avatar
Christian Würdig committed
141
142
143
144
145
146
}

/**
 * Returns 1 if irn is a Const representing 1, 0 otherwise
 */
static INLINE int is_ia32_Const_1(ir_node *irn) {
147
148
	return is_ia32_irn(irn) && is_ia32_Const(irn) && get_ia32_immop_type(irn) == ia32_ImmConst
	       && tarval_is_one(get_ia32_Immop_tarval(irn));
Christian Würdig's avatar
Christian Würdig committed
149
150
}

151
/**
Christian Würdig's avatar
Christian Würdig committed
152
153
 * Collects all Projs of a node into the node array. Index is the projnum.
 * BEWARE: The caller has to assure the appropriate array size!
154
 */
Christian Würdig's avatar
Christian Würdig committed
155
156
157
158
159
static void ia32_collect_Projs(ir_node *irn, ir_node **projs, int size) {
	const ir_edge_t *edge;
	assert(get_irn_mode(irn) == mode_T && "need mode_T");

	memset(projs, 0, size * sizeof(projs[0]));
160

Christian Würdig's avatar
Christian Würdig committed
161
	foreach_out_edge(irn, edge) {
162
163
164
165
		ir_node *proj = get_edge_src_irn(edge);
		int proj_proj = get_Proj_proj(proj);
		assert(proj_proj < size);
		projs[proj_proj] = proj;
Christian Würdig's avatar
Christian Würdig committed
166
167
168
169
170
171
172
173
	}
}

/**
 * Renumbers the proj having pn_old in the array tp pn_new
 * and removes the proj from the array.
 */
static INLINE void ia32_renumber_Proj(ir_node **projs, long pn_old, long pn_new) {
174
	fprintf(stderr, "Warning: renumber_Proj used!\n");
Christian Würdig's avatar
Christian Würdig committed
175
176
177
178
	if (projs[pn_old]) {
		set_Proj_proj(projs[pn_old], pn_new);
		projs[pn_old] = NULL;
	}
179
180
}

181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/**
 * 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);
208
		set_type_alignment_bytes(res, 16);
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
		pmap_insert(types, mode, res);
	}
	else
		res = e->value;
	return res;
}

/**
 * Get an entity that is initialized with a tarval
 */
static ir_entity *get_entity_for_tv(ia32_code_gen_t *cg, ir_node *cnst)
{
	tarval *tv    = get_Const_tarval(cnst);
	pmap_entry *e = pmap_find(cg->isa->tv_ent, tv);
	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)
			tp = get_prim_type(cg->isa->types, mode);

		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;

		pmap_insert(cg->isa->tv_ent, tv, res);
247
	} else {
248
		res = e->value;
249
250
	}

251
252
253
	return res;
}

254
255
256
257
258
259
260
261
262
263
264
265
266
267
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;
}

268
269
270
/**
 * Transforms a Const.
 */
271
static ir_node *gen_Const(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
272
	ir_graph        *irg   = current_ir_graph;
273
274
	ir_node         *old_block = get_nodes_block(node);
	ir_node         *block = be_transform_node(old_block);
275
276
	dbg_info        *dbgi  = get_irn_dbg_info(node);
	ir_mode         *mode  = get_irn_mode(node);
277
278

	if (mode_is_float(mode)) {
279
		ir_node   *res   = NULL;
Michael Beck's avatar
Michael Beck committed
280
		ir_node   *noreg = ia32_new_NoReg_gp(env_cg);
281
282
		ir_node   *nomem = new_NoMem();
		ir_node   *load;
283
284
		ir_entity *floatent;

Michael Beck's avatar
Michael Beck committed
285
		if (! USE_SSE2(env_cg)) {
286
287
288
			cnst_classify_t clss = classify_Const(node);

			if (clss == CNST_NULL) {
289
				load = new_rd_ia32_vfldz(dbgi, irg, block);
290
				res  = load;
291
			} else if (clss == CNST_ONE) {
292
				load = new_rd_ia32_vfld1(dbgi, irg, block);
293
				res  = load;
294
			} else {
Michael Beck's avatar
Michael Beck committed
295
				floatent = get_entity_for_tv(env_cg, node);
296

Matthias Braun's avatar
Matthias Braun committed
297
				load     = new_rd_ia32_vfld(dbgi, irg, block, noreg, noreg, nomem, mode);
298
299
				set_ia32_op_type(load, ia32_AddrModeS);
				set_ia32_am_flavour(load, ia32_am_N);
300
				set_ia32_am_sc(load, floatent);
301
302
				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);
303
			}
304
			set_ia32_ls_mode(load, mode);
305
		} else {
Michael Beck's avatar
Michael Beck committed
306
			floatent = get_entity_for_tv(env_cg, node);
307

308
			load     = new_rd_ia32_xLoad(dbgi, irg, block, noreg, noreg, nomem);
309
310
			set_ia32_op_type(load, ia32_AddrModeS);
			set_ia32_am_flavour(load, ia32_am_N);
311
			set_ia32_am_sc(load, floatent);
312
			set_ia32_ls_mode(load, mode);
313
			set_ia32_flags(load, get_ia32_flags(load) | arch_irn_flags_rematerializable);
314
315

			res = new_r_Proj(irg, block, load, mode_xmm, pn_ia32_xLoad_res);
316
317
		}

Michael Beck's avatar
Michael Beck committed
318
		SET_IA32_ORIG_NODE(load, ia32_get_old_node_name(env_cg, node));
319
320

		/* Const Nodes before the initial IncSP are a bad idea, because
321
322
323
		 * 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.
324
325
326
327
328
		 */
		if (get_irg_start_block(irg) == block) {
			add_irn_dep(load, get_irg_frame(irg));
		}

Michael Beck's avatar
Michael Beck committed
329
		SET_IA32_ORIG_NODE(load, ia32_get_old_node_name(env_cg, node));
330
331
		return res;
	} else {
332
		ir_node *cnst = new_rd_ia32_Const(dbgi, irg, block);
333
334
335
336
337
338
339

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

		set_ia32_Const_attr(cnst, node);
Michael Beck's avatar
Michael Beck committed
340
		SET_IA32_ORIG_NODE(cnst, ia32_get_old_node_name(env_cg, node));
341
342
343
344
345
346
347
348
349
350
		return cnst;
	}

	assert(0);
	return new_r_Bad(irg);
}

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

	if (mode_is_float(mode)) {
Michael Beck's avatar
Michael Beck committed
360
		if (USE_SSE2(env_cg))
361
			cnst = new_rd_ia32_xConst(dbgi, irg, block);
362
		else
363
			cnst = new_rd_ia32_vfConst(dbgi, irg, block);
364
365
		//set_ia32_ls_mode(cnst, mode);
		set_ia32_ls_mode(cnst, mode_E);
366
	} else {
367
		cnst = new_rd_ia32_Const(dbgi, irg, block);
368
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));
	}

	set_ia32_Const_attr(cnst, node);
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
414
415
416
417
418
419
420
421
422
423
424
		tp  = new_type_primitive(new_id_from_str(tp_name), mode);
		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();
425
		cnst = new_Const(mode, tv);
426
427
428
429
		current_ir_graph = rem;

		set_atomic_ent_value(ent, cnst);

430
431
		/* cache the entry */
		ent_cache[kct] = ent;
432
	}
433

434
	return ent_cache[kct];
435
436
}

Christian Würdig's avatar
Christian Würdig committed
437
438
439
440
#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
441
442
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;
443

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

450
451
/* determine if one operator is an Imm */
static ir_node *get_immediate_op(ir_node *op1, ir_node *op2) {
452
	if (op1) {
Christian Würdig's avatar
Christian Würdig committed
453
		return is_ia32_Cnst(op1) ? op1 : (is_ia32_Cnst(op2) ? op2 : NULL);
454
455
456
	} else {
		return is_ia32_Cnst(op2) ? op2 : NULL;
	}
457
458
459
460
}

/* determine if one operator is not an Imm */
static ir_node *get_expr_op(ir_node *op1, ir_node *op2) {
Christian Würdig's avatar
Christian Würdig committed
461
	return !is_ia32_Cnst(op1) ? op1 : (!is_ia32_Cnst(op2) ? op2 : NULL);
462
463
}

464
static void fold_immediate(ir_node *node, int in1, int in2) {
465
466
467
	ir_node *left;
	ir_node *right;

Michael Beck's avatar
Michael Beck committed
468
	if (!(env_cg->opt & IA32_OPT_IMMOPS))
469
470
471
472
		return;

	left = get_irn_n(node, in1);
	right = get_irn_n(node, in2);
473
	if (! is_ia32_Cnst(right) && is_ia32_Cnst(left)) {
474
475
476
477
478
		/* we can only set right operand to immediate */
		if(!is_ia32_commutative(node))
			return;
		/* exchange left/right */
		set_irn_n(node, in1, right);
Michael Beck's avatar
Michael Beck committed
479
		set_irn_n(node, in2, ia32_get_admissible_noreg(env_cg, node, in2));
480
		copy_ia32_Immop_attr(node, left);
481
	} else if(is_ia32_Cnst(right)) {
Michael Beck's avatar
Michael Beck committed
482
		set_irn_n(node, in2, ia32_get_admissible_noreg(env_cg, node, in2));
483
		copy_ia32_Immop_attr(node, right);
484
485
486
487
	} else {
		return;
	}

488
	clear_ia32_commutative(node);
Matthias Braun's avatar
Matthias Braun committed
489
490
	set_ia32_am_support(node, get_ia32_am_support(node) & ~ia32_am_Source,
	                    get_ia32_am_arity(node));
491
}
492
493
494
495
496
497
498
499
500

/**
 * 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.
 */
501
static ir_node *gen_binop(ir_node *node, ir_node *op1, ir_node *op2,
502
                          construct_binop_func *func, int commutative)
503
{
Michael Beck's avatar
Michael Beck committed
504
505
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_graph *irg      = current_ir_graph;
506
	dbg_info *dbgi     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
507
	ir_node  *noreg_gp = ia32_new_NoReg_gp(env_cg);
508
	ir_node  *nomem    = new_NoMem();
509
	ir_node  *new_node;
510

511
	ir_node *new_op1 = be_transform_node(op1);
512
513
	ir_node *new_op2 = create_immediate_or_transform(op2, 0);
	if (is_ia32_Immediate(new_op2)) {
514
		commutative = 0;
515
516
	}

517
	new_node = func(dbgi, irg, block, noreg_gp, noreg_gp, new_op1, new_op2, nomem);
518
	if (func == new_rd_ia32_IMul) {
Matthias Braun's avatar
Matthias Braun committed
519
		set_ia32_am_support(new_node, ia32_am_Source, ia32_am_binary);
520
	} else {
Matthias Braun's avatar
Matthias Braun committed
521
		set_ia32_am_support(new_node, ia32_am_Full, ia32_am_binary);
522
523
	}

Michael Beck's avatar
Michael Beck committed
524
	SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
525
	if (commutative) {
526
		set_ia32_commutative(new_node);
527
	}
Christian Würdig's avatar
Christian Würdig committed
528

529
	return new_node;
530
531
}

532
533
534
535
536
537
538
539
/**
 * 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
540
541
static ir_node *gen_binop_sse_float(ir_node *node, ir_node *op1, ir_node *op2,
                                    construct_binop_func *func)
542
{
Michael Beck's avatar
Michael Beck committed
543
544
545
	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);
546
	ir_node  *new_node = NULL;
547
	dbg_info *dbgi     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
548
	ir_graph *irg      = current_ir_graph;
549
	ir_mode  *mode     = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
550
	ir_node  *noreg_gp = ia32_new_NoReg_gp(env_cg);
551
552
	ir_node  *nomem    = new_NoMem();

Matthias Braun's avatar
Matthias Braun committed
553
554
555
	new_node = func(dbgi, irg, block, noreg_gp, noreg_gp, new_op1, new_op2,
	                nomem);
	set_ia32_am_support(new_node, ia32_am_Source, ia32_am_binary);
556
557
558
	if (is_op_commutative(get_irn_op(node))) {
		set_ia32_commutative(new_node);
	}
559
	set_ia32_ls_mode(new_node, mode);
560

Michael Beck's avatar
Michael Beck committed
561
	SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
562
563
564

	return new_node;
}
565

566
567
568
569
570
571
572
573
574
575
576
577
578
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
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
/**
 * 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,
600
	                nomem, get_fpcw());
Matthias Braun's avatar
Matthias Braun committed
601
602
603
604
605
606
607
608
609
	set_ia32_am_support(new_node, ia32_am_Source, ia32_am_binary);
	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;
}
610
611
612
613
614
615
616
617
618

/**
 * 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.
 */
619
static ir_node *gen_shift_binop(ir_node *node, ir_node *op1, ir_node *op2,
620
621
                                construct_binop_func *func)
{
Michael Beck's avatar
Michael Beck committed
622
623
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *new_op1 = be_transform_node(op1);
624
	ir_node  *new_op2;
625
626
	ir_node  *new_op  = NULL;
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
627
628
	ir_graph *irg     = current_ir_graph;
	ir_node  *noreg   = ia32_new_NoReg_gp(env_cg);
629
	ir_node  *nomem   = new_NoMem();
630

631
632
	assert(! mode_is_float(get_irn_mode(node))
	         && "Shift/Rotate with float not supported");
633

634
	new_op2 = create_immediate_or_transform(op2, 'N');
635

636
	new_op = func(dbgi, irg, block, noreg, noreg, new_op1, new_op2, nomem);
637
638

	/* set AM support */
Matthias Braun's avatar
Matthias Braun committed
639
	set_ia32_am_support(new_op, ia32_am_Dest, ia32_am_binary);
640

Michael Beck's avatar
Michael Beck committed
641
	SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
Christian Würdig's avatar
Christian Würdig committed
642

Christian Würdig's avatar
Christian Würdig committed
643
	set_ia32_emit_cl(new_op);
644

645
	return new_op;
646
647
648
649
650
651
652
653
654
655
}


/**
 * 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.
 */
656
static ir_node *gen_unop(ir_node *node, ir_node *op, construct_unop_func *func)
657
{
Michael Beck's avatar
Michael Beck committed
658
659
	ir_node  *block    = be_transform_node(get_nodes_block(node));
	ir_node  *new_op   = be_transform_node(op);
660
	ir_node  *new_node = NULL;
Michael Beck's avatar
Michael Beck committed
661
	ir_graph *irg      = current_ir_graph;
662
	dbg_info *dbgi     = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
663
	ir_node  *noreg    = ia32_new_NoReg_gp(env_cg);
664
	ir_node  *nomem    = new_NoMem();
665

666
667
	new_node = func(dbgi, irg, block, noreg, noreg, new_op, nomem);
	DB((dbg, LEVEL_1, "INT unop ..."));
Matthias Braun's avatar
Matthias Braun committed
668
	set_ia32_am_support(new_node, ia32_am_Dest, ia32_am_unary);
Christian Würdig's avatar
Christian Würdig committed
669

Michael Beck's avatar
Michael Beck committed
670
	SET_IA32_ORIG_NODE(new_node, ia32_get_old_node_name(env_cg, node));
671

672
	return new_node;
673
674
675
676
677
678
679
}

/**
 * Creates an ia32 Add.
 *
 * @return the created ia32 Add node
 */
680
static ir_node *gen_Add(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
681
	ir_node  *block   = be_transform_node(get_nodes_block(node));
682
	ir_node  *op1     = get_Add_left(node);
Michael Beck's avatar
Michael Beck committed
683
	ir_node  *new_op1 = be_transform_node(op1);
684
	ir_node  *op2     = get_Add_right(node);
Michael Beck's avatar
Michael Beck committed
685
	ir_node  *new_op2 = be_transform_node(op2);
686
	ir_node  *new_op  = NULL;
Michael Beck's avatar
Michael Beck committed
687
	ir_graph *irg     = current_ir_graph;
688
689
	dbg_info *dbgi    = get_irn_dbg_info(node);
	ir_mode  *mode    = get_irn_mode(node);
Michael Beck's avatar
Michael Beck committed
690
	ir_node  *noreg   = ia32_new_NoReg_gp(env_cg);
691
692
	ir_node  *nomem   = new_NoMem();
	ir_node  *expr_op, *imm_op;
693

694
695
	/* Check if immediate optimization is on and */
	/* if it's an operation with immediate.      */
Michael Beck's avatar
Michael Beck committed
696
	imm_op  = (env_cg->opt & IA32_OPT_IMMOPS) ? get_immediate_op(new_op1, new_op2) : NULL;
697
	expr_op = get_expr_op(new_op1, new_op2);
698
699

	assert((expr_op || imm_op) && "invalid operands");
Christian Würdig's avatar
Christian Würdig committed
700
701

	if (mode_is_float(mode)) {
Michael Beck's avatar
Michael Beck committed
702
		if (USE_SSE2(env_cg))
Matthias Braun's avatar
Matthias Braun committed
703
			return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xAdd);
704
		else
Matthias Braun's avatar
Matthias Braun committed
705
			return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfadd);
Christian Würdig's avatar
Christian Würdig committed
706
	}
Christian Würdig's avatar
Christian Würdig committed
707

708
	/* integer ADD */
709
	if (! expr_op) {
710
711
712
713
714
715
716
717
718
719
720
721
722
		ia32_immop_type_t tp1 = get_ia32_immop_type(new_op1);
		ia32_immop_type_t tp2 = get_ia32_immop_type(new_op2);

		/* No expr_op means, that we have two const - one symconst and */
		/* one tarval or another symconst - because this case is not   */
		/* covered by constant folding                                 */
		/* We need to check for:                                       */
		/*  1) symconst + const    -> becomes a LEA                    */
		/*  2) symconst + symconst -> becomes a const + LEA as the elf */
		/*        linker doesn't support two symconsts                 */

		if (tp1 == ia32_ImmSymConst && tp2 == ia32_ImmSymConst) {
			/* this is the 2nd case */
723
			new_op = new_rd_ia32_Lea(dbgi, irg, block, new_op1, noreg);
724
			set_ia32_am_sc(new_op, get_ia32_Immop_symconst(new_op2));
Matthias Braun's avatar
Matthias Braun committed
725
			set_ia32_am_flavour(new_op, ia32_am_B);
726
			set_ia32_op_type(new_op, ia32_AddrModeS);
727

728
729
730
731
			DBG_OPT_LEA3(new_op1, new_op2, node, new_op);
		} else if (tp1 == ia32_ImmSymConst) {
			tarval *tv = get_ia32_Immop_tarval(new_op2);
			long offs = get_tarval_long(tv);
Christian Würdig's avatar
Christian Würdig committed
732

733
			new_op = new_rd_ia32_Lea(dbgi, irg, block, noreg, noreg);
Matthias Braun's avatar
Matthias Braun committed
734
			add_irn_dep(new_op, get_irg_frame(irg));
735
			DBG_OPT_LEA3(new_op1, new_op2, node, new_op);
736

737
738
			set_ia32_am_sc(new_op, get_ia32_Immop_symconst(new_op1));
			add_ia32_am_offs_int(new_op, offs);
Matthias Braun's avatar
Matthias Braun committed
739
			set_ia32_am_flavour(new_op, ia32_am_OB);
740
741
742
743
744
			set_ia32_op_type(new_op, ia32_AddrModeS);
		} else if (tp2 == ia32_ImmSymConst) {
			tarval *tv = get_ia32_Immop_tarval(new_op1);
			long offs = get_tarval_long(tv);

745
			new_op = new_rd_ia32_Lea(dbgi, irg, block, noreg, noreg);
Matthias Braun's avatar
Matthias Braun committed
746
			add_irn_dep(new_op, get_irg_frame(irg));
747
			DBG_OPT_LEA3(new_op1, new_op2, node, new_op);
Christian Würdig's avatar
Christian Würdig committed
748

749
750
			add_ia32_am_offs_int(new_op, offs);
			set_ia32_am_sc(new_op, get_ia32_Immop_symconst(new_op2));
Matthias Braun's avatar
Matthias Braun committed
751
			set_ia32_am_flavour(new_op, ia32_am_OB);
752
753
754
755
756
757
758
759
			set_ia32_op_type(new_op, ia32_AddrModeS);
		} else {
			tarval *tv1 = get_ia32_Immop_tarval(new_op1);
			tarval *tv2 = get_ia32_Immop_tarval(new_op2);
			tarval *restv = tarval_add(tv1, tv2);

			DEBUG_ONLY(ir_fprintf(stderr, "Warning: add with 2 consts not folded: %+F\n", node));

760
			new_op = new_rd_ia32_Const(dbgi, irg, block);
761
762
			set_ia32_Const_tarval(new_op, restv);
			DBG_OPT_LEA3(new_op1, new_op2, node, new_op);
763
		}
Christian Würdig's avatar
Christian Würdig committed
764

Michael Beck's avatar
Michael Beck committed
765
		SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
766
767
		return new_op;
	} else if (imm_op) {
Michael Beck's avatar
Michael Beck committed
768
		if ((env_cg->opt & IA32_OPT_INCDEC) && get_ia32_immop_type(imm_op) == ia32_ImmConst) {
769
770
771
772
773
774
775
776
			tarval_classification_t class_tv, class_negtv;
			tarval *tv = get_ia32_Immop_tarval(imm_op);

			/* optimize tarvals */
			class_tv    = classify_tarval(tv);
			class_negtv = classify_tarval(tarval_neg(tv));

			if (class_tv == TV_CLASSIFY_ONE) { /* + 1 == INC */
777
778
				DB((dbg, LEVEL_2, "Add(1) to Inc ... "));
				new_op     = new_rd_ia32_Inc(dbgi, irg, block, noreg, noreg, expr_op, nomem);
Michael Beck's avatar
Michael Beck committed
779
				SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
780
781
				return new_op;
			} else if (class_tv == TV_CLASSIFY_ALL_ONE || class_negtv == TV_CLASSIFY_ONE) { /* + (-1) == DEC */
782
783
				DB((dbg, LEVEL_2, "Add(-1) to Dec ... "));
				new_op     = new_rd_ia32_Dec(dbgi, irg, block, noreg, noreg, expr_op, nomem);
Michael Beck's avatar
Michael Beck committed
784
				SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
785
786
				return new_op;
			}
787
		}
Christian Würdig's avatar
Christian Würdig committed
788
789
	}

790
	/* This is a normal add */
791
	new_op = new_rd_ia32_Add(dbgi, irg, block, noreg, noreg, new_op1, new_op2, nomem);
792
793

	/* set AM support */
Matthias Braun's avatar
Matthias Braun committed
794
	set_ia32_am_support(new_op, ia32_am_Full, ia32_am_binary);
795
796
	set_ia32_commutative(new_op);

797
	fold_immediate(new_op, 2, 3);
798

Michael Beck's avatar
Michael Beck committed
799
	SET_IA32_ORIG_NODE(new_op, ia32_get_old_node_name(env_cg, node));
800

801
	return new_op;
Christian Würdig's avatar
Christian Würdig committed
802
803
}

804
805
806
807
808
/**
 * Creates an ia32 Mul.
 *
 * @return the created ia32 Mul node
 */
809
static ir_node *gen_Mul(ir_node *node) {
810
811
	ir_node *op1  = get_Mul_left(node);
	ir_node *op2  = get_Mul_right(node);
812
	ir_mode *mode = get_irn_mode(node);
813

814
	if (mode_is_float(mode)) {
Michael Beck's avatar
Michael Beck committed
815
		if (USE_SSE2(env_cg))
Matthias Braun's avatar
Matthias Braun committed
816
			return gen_binop_sse_float(node, op1, op2, new_rd_ia32_xMul);
817
		else
Matthias Braun's avatar
Matthias Braun committed
818
			return gen_binop_x87_float(node, op1, op2, new_rd_ia32_vfmul);
Christian Würdig's avatar
Christian Würdig committed
819
	}
820

821
822
823
824
825
	/*
		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
	*/
826
	return gen_binop(node, op1, op2, new_rd_ia32_IMul, 1);
827
}
828
829
830
831
832
833
834
835

/**
 * 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
 */
836
static ir_node *gen_Mulh(ir_node *node) {
Michael Beck's avatar
Michael Beck committed
837
	ir_node  *block   = be_transform_node(get_nodes_block(node));
838
	ir_node  *op1     = get_irn_n(node, 0);
Michael Beck's avatar
Michael Beck committed
839
	ir_node  *new_op1 = be_transform_node(op1);
840
	ir_node  *op2     = get_irn_n(node, 1);
Michael Beck's avatar
Michael Beck committed
841
842
	ir_node  *new_op2 = be_transform_node(op2);
	ir_graph *irg     = current_ir_graph;
843
	dbg_info *dbgi    = get_irn_dbg_info(node);
Michael Beck's avatar
Michael Beck committed
844
	ir_node  *noreg   = ia32_new_NoReg_gp(env_cg);
845
	ir_mode  *mode    = get_irn_mode(node);
Matthias Braun's avatar
Matthias Braun committed
846
	ir_node  *proj_EDX, *res;
847

848
	assert(!mode_is_float(mode) && "Mulh with float not supported");
849
	if (mode_is_signed(mode)) {
Matthias Braun's avatar
Matthias Braun committed
850
851
		res = new_rd_ia32_IMul1OP(dbgi, irg, block, noreg, noreg, new_op1,
		                          new_op2, new_NoMem());
Matthias Braun's avatar
Matthias Braun committed
852
	} else {
Matthias Braun's avatar
Matthias Braun committed
853
854
		res = new_rd_ia32_Mul(dbgi, irg, block, noreg, noreg, new_op1, new_op2,
		                      new_NoMem());
Matthias Braun's avatar
Matthias Braun committed
855
	}
856

Matthias Braun's avatar
Matthias Braun committed
857
	set_ia32_commutative(res);
Matthias Braun's avatar
Matthias Braun committed
858
	set_ia32_am_support(res, ia32_am_Source, ia32_am_binary);
Matthias Braun's avatar
Matthias Braun committed
859

860
	proj_EDX = new_rd_Proj(dbgi, irg, block, res, mode_Iu, pn_EDX);
861
862

	return proj_EDX;
863
864
}

865
866


867
868
869
/**
 * Creates an ia32 And.
 *
870
 * @return The created ia32 And node
871
 */
872
static ir_node *gen_And(ir_node *node) {
873
874
	ir_node *op1 = get_And_left(node);
	ir_node *op2 = get_And_right(node);
875
876
	assert(! mode_is_float(get_irn_mode(node)));

Michael Beck's avatar
Michael Beck committed
877
878
	/* check for zero extension first */
	if (is_Const(op2)) {
879
880
881
882
883
884
885
886
887
888
889
890
		tarval   *tv    = get_Const_tarval(op2);
		long      v     = get_tarval_long(tv);

		if (v == 0xFF || v == 0xFFFF) {
			dbg_info *dbgi   = get_irn_dbg_info(node);
			ir_node  *block  = be_transform_node(get_nodes_block(node));
			ir_node  *new_op = be_transform_node(op1);
			ir_mode  *src_mode;
			ir_node  *res;

			if(v == 0xFF) {
				src_mode = mode_Bu;
Michael Beck's avatar
Michael Beck committed
891
			} else {
892
893
				assert(v == 0xFFFF);
				src_mode = mode_Hu;
Michael Beck's avatar
Michael Beck committed
894
			}
895
896
			res = create_I2I_Conv(src_mode, mode_Iu, dbgi, block, new_op);
			SET_IA32_ORIG_NODE(res, ia32_get_old_node_name(env_cg, node));
Michael Beck's avatar
Michael Beck committed
897

898
			return res;
899
900
		}
	}
901

902
	return gen_binop(node, op1, op2, new_rd_ia32_And, 1);
903
904
905
906
907
908
909
}



/**
 * Creates an ia32 Or.
 *
910
 * @return The created ia32 Or node
911
 */
912
static ir_node *gen_Or(ir_node *node) {
913
914
	ir_node *op1 = get_Or_left(node);
	ir_node *op2 = get_Or_right(node);
915

916
	assert (! mode_is_float(get_irn_mode(node)));
917
	return gen_binop(node, op1, op2, new_rd_ia32_Or, 1);
918
919
920
921
922
923
924
}



/**
 * Creates an ia32 Eor.
 *
925
 * @return The created ia32 Eor node
926
 */
927
static ir_node *gen_Eor(ir_node *node) {
928
929
	ir_node *op1 = get_Eor_left(node);
	ir_node *op2 = get_Eor_right(node);
930

931
	assert(! mode_is_float(get_irn_mode(node)));
932
	return gen_binop(node, op1, op2, new_rd_ia32_Xor, 1);
933
934
935
936
937
938
}


/**
 * Creates an ia32 Sub.
 *
939
 * @return The created ia32 Sub node
940
 */
941
static ir_node *gen_Sub(ir_node *node) {