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

Michael Beck's avatar
Michael Beck committed
20
21
22
23
24
25
/**
 * @file
 * @brief   Lower Double word operations, ie 64bit -> 32bit, 32bit -> 16bit etc.
 * @date    8.10.2004
 * @author  Michael Beck
 * @version $Id$
26
 */
Matthias Braun's avatar
Matthias Braun committed
27
#include "config.h"
28

29
#include <string.h>
30
#include <stdlib.h>
31
32
#include <assert.h>

33
#include "error.h"
34
#include "lowering.h"
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include "irnode_t.h"
#include "irgraph_t.h"
#include "irmode_t.h"
#include "iropt_t.h"
#include "irgmod.h"
#include "tv_t.h"
#include "dbginfo_t.h"
#include "iropt_dbg.h"
#include "irflag_t.h"
#include "firmstat.h"
#include "irgwalk.h"
#include "ircons.h"
#include "irflag.h"
#include "irtools.h"
#include "debug.h"
#include "set.h"
#include "pmap.h"
#include "pdeq.h"
Christian Würdig's avatar
Christian Würdig committed
53
#include "irdump.h"
54
#include "array_t.h"
Michael Beck's avatar
Michael Beck committed
55
#include "irpass_t.h"
56

Michael Beck's avatar
Michael Beck committed
57
/** A map from (op, imode, omode) to Intrinsic functions entities. */
58
59
static set *intrinsic_fkt;

Michael Beck's avatar
Michael Beck committed
60
61
62
/** A map from (imode, omode) to conv function types. */
static set *conv_types;

63
64
65
66
/** A map from a method type to its lowered type. */
static pmap *lowered_type;

/** The types for the binop and unop intrinsics. */
Christian Würdig's avatar
Christian Würdig committed
67
static ir_type *binop_tp_u, *binop_tp_s, *unop_tp_u, *unop_tp_s, *shiftop_tp_u, *shiftop_tp_s, *tp_s, *tp_u;
68
69
70
71
72

/** the debug handle */
DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)

/**
Michael Beck's avatar
Michael Beck committed
73
 * An entry in the (op, imode, omode) -> entity map.
74
 */
75
typedef struct op_mode_entry {
76
	const ir_op   *op;    /**< the op */
Michael Beck's avatar
Michael Beck committed
77
78
	const ir_mode *imode; /**< the input mode */
	const ir_mode *omode; /**< the output mode */
79
	ir_entity     *ent;   /**< the associated entity of this (op, imode, omode) triple */
80
81
} op_mode_entry_t;

Michael Beck's avatar
Michael Beck committed
82
83
84
/**
 * An entry in the (imode, omode) -> tp map.
 */
85
typedef struct conv_tp_entry {
Michael Beck's avatar
Michael Beck committed
86
87
88
89
90
	const ir_mode *imode; /**< the input mode */
	const ir_mode *omode; /**< the output mode */
	ir_type       *mtd;   /**< the associated method type of this (imode, omode) pair */
} conv_tp_entry_t;

91
92
93
94
/**
 * Every double word node will be replaced,
 * we need some store to hold the replacement:
 */
95
typedef struct node_entry_t {
96
97
	ir_node *low_word;    /**< the low word */
	ir_node *high_word;   /**< the high word */
98
99
100
} node_entry_t;

enum lower_flags {
101
102
	MUST_BE_LOWERED = 1,  /**< graph must be lowered */
	CF_CHANGED      = 2,  /**< control flow was changed */
103
104
105
106
107
};

/**
 * The lower environment.
 */
108
typedef struct lower_env_t {
109
	node_entry_t **entries;       /**< entries per node */
110
	ir_graph      *irg;
111
	struct obstack obst;          /**< an obstack holding the temporary data */
112
	ir_type  *l_mtp;              /**< lowered method type of the current method */
Michael Beck's avatar
BugFix:    
Michael Beck committed
113
114
	tarval   *tv_mode_bytes;      /**< a tarval containing the number of bytes in the lowered modes */
	tarval   *tv_mode_bits;       /**< a tarval containing the number of bits in the lowered modes */
115
116
	pdeq     *waitq;              /**< a wait queue of all nodes that must be handled later */
	pmap     *proj_2_block;       /**< a map from ProjX to its destination blocks */
117
118
119
120
	ir_mode  *high_signed;        /**< doubleword signed type */
	ir_mode  *high_unsigned;      /**< doubleword unsigned type */
	ir_mode  *low_signed;         /**< word signed type */
	ir_mode  *low_unsigned;       /**< word unsigned type */
121
122
	ident    *first_id;           /**< .l for little and .h for big endian */
	ident    *next_id;            /**< .h for little and .l for big endian */
123
124
125
	const lwrdw_param_t *params;  /**< transformation parameter */
	unsigned flags;               /**< some flags */
	int      n_entries;           /**< number of entries */
126
	ir_type  *value_param_tp;     /**< the old value param type */
127
128
} lower_env_t;

Michael Beck's avatar
Michael Beck committed
129
130
131
/**
 * Create a method type for a Conv emulation from imode to omode.
 */
132
133
static ir_type *get_conv_type(ir_mode *imode, ir_mode *omode, lower_env_t *env)
{
Michael Beck's avatar
Michael Beck committed
134
135
136
137
138
139
140
141
142
143
144
	conv_tp_entry_t key, *entry;
	ir_type *mtd;

	key.imode = imode;
	key.omode = omode;
	key.mtd   = NULL;

	entry = set_insert(conv_types, &key, sizeof(key), HASH_PTR(imode) ^ HASH_PTR(omode));
	if (! entry->mtd) {
		int n_param = 1, n_res = 1;

145
		if (imode == env->high_signed || imode == env->high_unsigned)
Michael Beck's avatar
Michael Beck committed
146
			n_param = 2;
147
		if (omode == env->high_signed || omode == env->high_unsigned)
Michael Beck's avatar
Michael Beck committed
148
149
150
			n_res = 2;

		/* create a new one */
151
		mtd = new_type_method(n_param, n_res);
Michael Beck's avatar
Michael Beck committed
152
153
154

		/* set param types and result types */
		n_param = 0;
155
		if (imode == env->high_signed) {
156
			set_method_param_type(mtd, n_param++, tp_u);
Michael Beck's avatar
Michael Beck committed
157
			set_method_param_type(mtd, n_param++, tp_s);
158
		} else if (imode == env->high_unsigned) {
Michael Beck's avatar
Michael Beck committed
159
160
			set_method_param_type(mtd, n_param++, tp_u);
			set_method_param_type(mtd, n_param++, tp_u);
Michael Beck's avatar
BugFix:    
Michael Beck committed
161
		} else {
162
			ir_type *tp = get_type_for_mode(imode);
Michael Beck's avatar
Michael Beck committed
163
			set_method_param_type(mtd, n_param++, tp);
Michael Beck's avatar
BugFix:    
Michael Beck committed
164
		}  /* if */
Michael Beck's avatar
Michael Beck committed
165
166

		n_res = 0;
167
		if (omode == env->high_signed) {
168
			set_method_res_type(mtd, n_res++, tp_u);
Michael Beck's avatar
Michael Beck committed
169
			set_method_res_type(mtd, n_res++, tp_s);
170
		} else if (omode == env->high_unsigned) {
Michael Beck's avatar
Michael Beck committed
171
172
			set_method_res_type(mtd, n_res++, tp_u);
			set_method_res_type(mtd, n_res++, tp_u);
Michael Beck's avatar
BugFix:    
Michael Beck committed
173
		} else {
174
			ir_type *tp = get_type_for_mode(omode);
Michael Beck's avatar
Michael Beck committed
175
			set_method_res_type(mtd, n_res++, tp);
Michael Beck's avatar
BugFix:    
Michael Beck committed
176
		}  /* if */
Michael Beck's avatar
Michael Beck committed
177
		entry->mtd = mtd;
Michael Beck's avatar
BugFix:    
Michael Beck committed
178
	} else {
Michael Beck's avatar
Michael Beck committed
179
		mtd = entry->mtd;
Michael Beck's avatar
BugFix:    
Michael Beck committed
180
	}  /* if */
Michael Beck's avatar
Michael Beck committed
181
	return mtd;
182
}  /* get_conv_type */
Michael Beck's avatar
Michael Beck committed
183

184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/**
 * Add an additional control flow input to a block.
 * Patch all Phi nodes. The new Phi inputs are copied from
 * old input number nr.
 */
static void add_block_cf_input_nr(ir_node *block, int nr, ir_node *cf)
{
	int i, arity = get_irn_arity(block);
	ir_node **in, *phi;

	assert(nr < arity);

	NEW_ARR_A(ir_node *, in, arity + 1);
	for (i = 0; i < arity; ++i)
		in[i] = get_irn_n(block, i);
	in[i] = cf;

	set_irn_in(block, i + 1, in);

203
	for (phi = get_Block_phis(block); phi != NULL; phi = get_Phi_next(phi)) {
204
205
206
207
		for (i = 0; i < arity; ++i)
			in[i] = get_irn_n(phi, i);
		in[i] = in[nr];
		set_irn_in(phi, i + 1, in);
Michael Beck's avatar
BugFix:    
Michael Beck committed
208
	}  /* for */
209
}  /* add_block_cf_input_nr */
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224

/**
 * Add an additional control flow input to a block.
 * Patch all Phi nodes. The new Phi inputs are copied from
 * old input from cf tmpl.
 */
static void add_block_cf_input(ir_node *block, ir_node *tmpl, ir_node *cf)
{
	int i, arity = get_irn_arity(block);
	int nr = 0;

	for (i = 0; i < arity; ++i) {
		if (get_irn_n(block, i) == tmpl) {
			nr = i;
			break;
Michael Beck's avatar
BugFix:    
Michael Beck committed
225
226
		}  /* if */
	}  /* for */
227
228
	assert(i < arity);
	add_block_cf_input_nr(block, nr, cf);
229
}  /* add_block_cf_input */
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250

/**
 * Return the "operational" mode of a Firm node.
 */
static ir_mode *get_irn_op_mode(ir_node *node)
{
	switch (get_irn_opcode(node)) {
	case iro_Load:
		return get_Load_mode(node);
	case iro_Store:
		return get_irn_mode(get_Store_value(node));
	case iro_DivMod:
		return get_irn_mode(get_DivMod_left(node));
	case iro_Div:
		return get_irn_mode(get_Div_left(node));
	case iro_Mod:
		return get_irn_mode(get_Mod_left(node));
	case iro_Cmp:
		return get_irn_mode(get_Cmp_left(node));
	default:
		return get_irn_mode(node);
Michael Beck's avatar
BugFix:    
Michael Beck committed
251
	}  /* switch */
252
}  /* get_irn_op_mode */
253
254

/**
255
 * Walker, prepare the node links.
256
257
258
259
260
261
 */
static void prepare_links(ir_node *node, void *env)
{
	lower_env_t  *lenv = env;
	ir_mode      *mode = get_irn_op_mode(node);
	node_entry_t *link;
Michael Beck's avatar
Michael Beck committed
262
	int          i, idx;
263

264
265
	if (mode == lenv->high_signed ||
		mode == lenv->high_unsigned) {
266
		/* ok, found a node that will be lowered */
267
		link = OALLOCZ(&lenv->obst, node_entry_t);
268

Michael Beck's avatar
Michael Beck committed
269
270
271
272
273
274
275
276
277
278
279
		idx = get_irn_idx(node);
		if (idx >= lenv->n_entries) {
			/* enlarge: this happens only for Rotl nodes which is RARELY */
			int old = lenv->n_entries;
			int n_idx = idx + (idx >> 3);

			ARR_RESIZE(node_entry_t *, lenv->entries, n_idx);
			memset(&lenv->entries[old], 0, (n_idx - old) * sizeof(lenv->entries[0]));
			lenv->n_entries = n_idx;
		}
		lenv->entries[idx] = link;
280
		lenv->flags |= MUST_BE_LOWERED;
281
	} else if (is_Conv(node)) {
282
283
284
285
		/* Conv nodes have two modes */
		ir_node *pred = get_Conv_op(node);
		mode = get_irn_mode(pred);

286
287
		if (mode == lenv->high_signed ||
			mode == lenv->high_unsigned) {
Michael Beck's avatar
BugFix:    
Michael Beck committed
288
			/* must lower this node either but don't need a link */
289
			lenv->flags |= MUST_BE_LOWERED;
Michael Beck's avatar
BugFix:    
Michael Beck committed
290
		}  /* if */
291
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
292
	}  /* if */
293
294
295
296
297
298
299
300

	if (is_Proj(node)) {
		/* link all Proj nodes to its predecessor:
		   Note that Tuple Proj's and its Projs are linked either. */
		ir_node *pred = get_Proj_pred(node);

		set_irn_link(node, get_irn_link(pred));
		set_irn_link(pred, node);
Michael Beck's avatar
BugFix:    
Michael Beck committed
301
	} else if (is_Phi(node)) {
302
303
		/* link all Phi nodes to its block */
		ir_node *block = get_nodes_block(node);
304
		add_Block_phi(block, node);
Michael Beck's avatar
BugFix:    
Michael Beck committed
305
	} else if (is_Block(node)) {
306
307
308
309
310
311
		/* fill the Proj -> Block map */
		for (i = get_Block_n_cfgpreds(node) - 1; i >= 0; --i) {
			ir_node *pred = get_Block_cfgpred(node, i);

			if (is_Proj(pred))
				pmap_insert(lenv->proj_2_block, pred, node);
Michael Beck's avatar
BugFix:    
Michael Beck committed
312
313
		}  /* for */
	}  /* if */
314
}  /* prepare_links */
315
316
317
318

/**
 * Translate a Constant: create two.
 */
319
320
static void lower_Const(ir_node *node, ir_mode *mode, lower_env_t *env)
{
321
322
323
324
	ir_graph *irg      = get_irn_irg(node);
	dbg_info *dbg      = get_irn_dbg_info(node);
	ir_mode  *low_mode = env->low_unsigned;
	int       idx;
325
326
327
328
329
	tarval   *tv, *tv_l, *tv_h;
	ir_node  *low, *high;

	tv   = get_Const_tarval(node);

330
	tv_l = tarval_convert_to(tv, low_mode);
331
	low  = new_rd_Const(dbg, irg, tv_l);
332

Michael Beck's avatar
BugFix:    
Michael Beck committed
333
	tv_h = tarval_convert_to(tarval_shrs(tv, env->tv_mode_bits), mode);
334
	high = new_rd_Const(dbg, irg, tv_h);
335
336
337
338
339

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
	env->entries[idx]->low_word  = low;
	env->entries[idx]->high_word = high;
340
}  /* lower_Const */
341
342
343
344

/**
 * Translate a Load: create two.
 */
345
346
static void lower_Load(ir_node *node, ir_mode *mode, lower_env_t *env)
{
347
	ir_mode    *low_mode = env->low_unsigned;
348
	ir_graph   *irg = get_irn_irg(node);
349
350
351
352
353
354
	ir_node    *adr = get_Load_ptr(node);
	ir_node    *mem = get_Load_mem(node);
	ir_node    *low, *high, *proj;
	dbg_info   *dbg;
	ir_node    *block = get_nodes_block(node);
	int         idx;
355
	ir_cons_flags volatility = get_Load_volatility(node) == volatility_is_volatile
356
	                         ? cons_volatile : 0;
357
358
359

	if (env->params->little_endian) {
		low  = adr;
360
		high = new_r_Add(block, adr, new_r_Const(irg, env->tv_mode_bytes), get_irn_mode(adr));
Michael Beck's avatar
BugFix:    
Michael Beck committed
361
	} else {
362
		low  = new_r_Add(block, adr, new_r_Const(irg, env->tv_mode_bytes), get_irn_mode(adr));
363
		high = adr;
Michael Beck's avatar
BugFix:    
Michael Beck committed
364
	}  /* if */
365
366
367

	/* create two loads */
	dbg  = get_irn_dbg_info(node);
368
	low  = new_rd_Load(dbg, block, mem,  low,  low_mode, volatility);
369
	proj = new_r_Proj(low, mode_M, pn_Load_M);
370
	high = new_rd_Load(dbg, block, proj, high, mode, volatility);
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
	env->entries[idx]->low_word  = low;
	env->entries[idx]->high_word = high;

	for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
		idx = get_irn_idx(proj);

		switch (get_Proj_proj(proj)) {
		case pn_Load_M:         /* Memory result. */
			/* put it to the second one */
			set_Proj_pred(proj, high);
			break;
		case pn_Load_X_except:  /* Execution result if exception occurred. */
			/* put it to the first one */
			set_Proj_pred(proj, low);
			break;
		case pn_Load_res:       /* Result of load operation. */
			assert(idx < env->n_entries);
391
392
			env->entries[idx]->low_word  = new_r_Proj(low,  low_mode, pn_Load_res);
			env->entries[idx]->high_word = new_r_Proj(high, mode,     pn_Load_res);
393
394
395
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
396
		}  /* switch */
397
398
399
		/* mark this proj: we have handled it already, otherwise we might fall into
		 * out new nodes. */
		mark_irn_visited(proj);
Michael Beck's avatar
BugFix:    
Michael Beck committed
400
	}  /* for */
401
}  /* lower_Load */
402
403
404
405

/**
 * Translate a Store: create two.
 */
406
407
static void lower_Store(ir_node *node, ir_mode *mode, lower_env_t *env)
{
408
409
410
411
412
	ir_graph     *irg;
	ir_node      *block, *adr, *mem;
	ir_node      *low, *high, *irn, *proj;
	dbg_info     *dbg;
	int           idx;
413
	node_entry_t *entry;
414
	ir_cons_flags    volatility = get_Store_volatility(node) == volatility_is_volatile
415
	                           ? cons_volatile : 0;
Matthias Braun's avatar
Matthias Braun committed
416
	(void) mode;
417
418
419
420
421
422
423
424
425

	irn = get_Store_value(node);
	entry = env->entries[get_irn_idx(irn)];
	assert(entry);

	if (! entry->low_word) {
		/* not ready yet, wait */
		pdeq_putr(env->waitq, node);
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
426
	}  /* if */
427

428
	irg = get_irn_irg(node);
429
430
431
432
433
434
	adr = get_Store_ptr(node);
	mem = get_Store_mem(node);
	block = get_nodes_block(node);

	if (env->params->little_endian) {
		low  = adr;
435
		high = new_r_Add(block, adr, new_r_Const(irg, env->tv_mode_bytes), get_irn_mode(adr));
Michael Beck's avatar
BugFix:    
Michael Beck committed
436
	} else {
437
		low  = new_r_Add(block, adr, new_r_Const(irg, env->tv_mode_bytes), get_irn_mode(adr));
438
		high = adr;
Michael Beck's avatar
BugFix:    
Michael Beck committed
439
	}  /* if */
440
441
442

	/* create two Stores */
	dbg = get_irn_dbg_info(node);
443
	low  = new_rd_Store(dbg, block, mem, low,  entry->low_word, volatility);
444
	proj = new_r_Proj(low, mode_M, pn_Store_M);
445
	high = new_rd_Store(dbg, block, proj, high, entry->high_word, volatility);
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
	env->entries[idx]->low_word  = low;
	env->entries[idx]->high_word = high;

	for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
		idx = get_irn_idx(proj);

		switch (get_Proj_proj(proj)) {
		case pn_Store_M:         /* Memory result. */
			/* put it to the second one */
			set_Proj_pred(proj, high);
			break;
		case pn_Store_X_except:  /* Execution result if exception occurred. */
			/* put it to the first one */
			set_Proj_pred(proj, low);
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
466
		}  /* switch */
467
468
469
		/* mark this proj: we have handled it already, otherwise we might fall into
		 * out new nodes. */
		mark_irn_visited(proj);
Michael Beck's avatar
BugFix:    
Michael Beck committed
470
	}  /* for */
471
}  /* lower_Store */
472
473
474

/**
 * Return a node containing the address of the intrinsic emulation function.
Michael Beck's avatar
Michael Beck committed
475
476
477
478
479
480
 *
 * @param method  the method type of the emulation function
 * @param op      the emulated ir_op
 * @param imode   the input mode of the emulated opcode
 * @param omode   the output mode of the emulated opcode
 * @param env     the lower environment
481
 */
Michael Beck's avatar
Michael Beck committed
482
483
static ir_node *get_intrinsic_address(ir_type *method, ir_op *op,
                                      ir_mode *imode, ir_mode *omode,
484
485
                                      lower_env_t *env)
{
486
	symconst_symbol sym;
487
	ir_entity *ent;
488
489
	op_mode_entry_t key, *entry;

Michael Beck's avatar
Michael Beck committed
490
491
492
493
	key.op    = op;
	key.imode = imode;
	key.omode = omode;
	key.ent   = NULL;
494

Michael Beck's avatar
Michael Beck committed
495
496
	entry = set_insert(intrinsic_fkt, &key, sizeof(key),
				HASH_PTR(op) ^ HASH_PTR(imode) ^ (HASH_PTR(omode) << 8));
497
498
	if (! entry->ent) {
		/* create a new one */
Michael Beck's avatar
Michael Beck committed
499
		ent = env->params->create_intrinsic(method, op, imode, omode, env->params->ctx);
500
501
502

		assert(ent && "Intrinsic creator must return an entity");
		entry->ent = ent;
Michael Beck's avatar
BugFix:    
Michael Beck committed
503
	} else {
504
		ent = entry->ent;
Michael Beck's avatar
BugFix:    
Michael Beck committed
505
	}  /* if */
506
	sym.entity_p = ent;
507
	return new_r_SymConst(env->irg, mode_P_code, sym, symconst_addr_ent);
508
}  /* get_intrinsic_address */
509
510
511
512
513
514

/**
 * Translate a Div.
 *
 * Create an intrinsic Call.
 */
515
516
static void lower_Div(ir_node *node, ir_mode *mode, lower_env_t *env)
{
517
518
	ir_node  *block, *irn, *call, *proj;
	ir_node  *in[4];
Michael Beck's avatar
Michael Beck committed
519
	ir_mode  *opmode;
520
521
522
523
524
525
526
527
528
529
530
531
532
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
	node_entry_t *entry;

	irn   = get_Div_left(node);
	entry = env->entries[get_irn_idx(irn)];
	assert(entry);

	if (! entry->low_word) {
		/* not ready yet, wait */
		pdeq_putr(env->waitq, node);
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
533
	}  /* if */
534
535
536
537
538
539
540
541
542
543
544
545

	in[0] = entry->low_word;
	in[1] = entry->high_word;

	irn   = get_Div_right(node);
	entry = env->entries[get_irn_idx(irn)];
	assert(entry);

	if (! entry->low_word) {
		/* not ready yet, wait */
		pdeq_putr(env->waitq, node);
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
546
	}  /* if */
547
548
549
550

	in[2] = entry->low_word;
	in[3] = entry->high_word;

551
	dbg   = get_irn_dbg_info(node);
552
553
554
	block = get_nodes_block(node);

	mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
Michael Beck's avatar
Michael Beck committed
555
	opmode = get_irn_op_mode(node);
Matthias Braun's avatar
Matthias Braun committed
556
	irn = get_intrinsic_address(mtp, get_irn_op(node), opmode, opmode, env);
557
	call = new_rd_Call(dbg, block, get_Div_mem(node), irn, 4, in, mtp);
558
	set_irn_pinned(call, get_irn_pinned(node));
559
	irn = new_r_Proj(call, mode_T, pn_Call_T_result);
560
561
562
563
564
565

	for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
		switch (get_Proj_proj(proj)) {
		case pn_Div_M:         /* Memory result. */
			/* reroute to the call */
			set_Proj_pred(proj, call);
566
			set_Proj_proj(proj, pn_Call_M);
567
568
569
570
571
572
573
574
575
			break;
		case pn_Div_X_except:  /* Execution result if exception occurred. */
			/* reroute to the call */
			set_Proj_pred(proj, call);
			set_Proj_proj(proj, pn_Call_X_except);
			break;
		case pn_Div_res:       /* Result of computation. */
			idx = get_irn_idx(proj);
			assert(idx < env->n_entries);
576
			env->entries[idx]->low_word  = new_r_Proj(irn, env->low_unsigned, 0);
577
			env->entries[idx]->high_word = new_r_Proj(irn, mode,                      1);
578
579
580
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
581
		}  /* switch */
582
583
584
		/* mark this proj: we have handled it already, otherwise we might fall into
		 * out new nodes. */
		mark_irn_visited(proj);
Michael Beck's avatar
BugFix:    
Michael Beck committed
585
	}  /* for */
586
}  /* lower_Div */
587
588
589
590
591
592

/**
 * Translate a Mod.
 *
 * Create an intrinsic Call.
 */
593
594
static void lower_Mod(ir_node *node, ir_mode *mode, lower_env_t *env)
{
595
596
	ir_node  *block, *proj, *irn, *call;
	ir_node  *in[4];
Michael Beck's avatar
Michael Beck committed
597
	ir_mode  *opmode;
598
599
600
601
602
603
604
605
606
607
608
609
610
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
	node_entry_t *entry;

	irn   = get_Mod_left(node);
	entry = env->entries[get_irn_idx(irn)];
	assert(entry);

	if (! entry->low_word) {
		/* not ready yet, wait */
		pdeq_putr(env->waitq, node);
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
611
	}  /* if */
612
613
614
615
616
617
618
619
620
621
622
623

	in[0] = entry->low_word;
	in[1] = entry->high_word;

	irn   = get_Mod_right(node);
	entry = env->entries[get_irn_idx(irn)];
	assert(entry);

	if (! entry->low_word) {
		/* not ready yet, wait */
		pdeq_putr(env->waitq, node);
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
624
	}  /* if */
625
626
627
628

	in[2] = entry->low_word;
	in[3] = entry->high_word;

629
	dbg   = get_irn_dbg_info(node);
630
631
632
	block = get_nodes_block(node);

	mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
Michael Beck's avatar
Michael Beck committed
633
	opmode = get_irn_op_mode(node);
Matthias Braun's avatar
Matthias Braun committed
634
	irn = get_intrinsic_address(mtp, get_irn_op(node), opmode, opmode, env);
635
	call = new_rd_Call(dbg, block, get_Mod_mem(node), irn, 4, in, mtp);
636
	set_irn_pinned(call, get_irn_pinned(node));
637
	irn = new_r_Proj(call, mode_T, pn_Call_T_result);
638
639
640
641
642
643

	for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
		switch (get_Proj_proj(proj)) {
		case pn_Mod_M:         /* Memory result. */
			/* reroute to the call */
			set_Proj_pred(proj, call);
644
			set_Proj_proj(proj, pn_Call_M);
645
646
647
648
649
650
651
652
653
			break;
		case pn_Mod_X_except:  /* Execution result if exception occurred. */
			/* reroute to the call */
			set_Proj_pred(proj, call);
			set_Proj_proj(proj, pn_Call_X_except);
			break;
		case pn_Mod_res:       /* Result of computation. */
			idx = get_irn_idx(proj);
			assert(idx < env->n_entries);
654
			env->entries[idx]->low_word  = new_r_Proj(irn, env->low_unsigned, 0);
655
			env->entries[idx]->high_word = new_r_Proj(irn, mode,                      1);
656
657
658
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
659
		}  /* switch */
660
661
662
		/* mark this proj: we have handled it already, otherwise we might fall into
		 * out new nodes. */
		mark_irn_visited(proj);
Michael Beck's avatar
BugFix:    
Michael Beck committed
663
	}  /* for */
664
}  /* lower_Mod */
665
666
667
668
669
670

/**
 * Translate a DivMod.
 *
 * Create two intrinsic Calls.
 */
671
672
static void lower_DivMod(ir_node *node, ir_mode *mode, lower_env_t *env)
{
Matthias Braun's avatar
Matthias Braun committed
673
674
675
	ir_node  *block, *proj, *irn, *mem, *callDiv, *callMod;
	ir_node  *resDiv = NULL;
	ir_node  *resMod = NULL;
676
	ir_node  *in[4];
Michael Beck's avatar
Michael Beck committed
677
	ir_mode  *opmode;
678
679
680
681
682
683
684
685
686
687
688
689
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
	node_entry_t *entry;
	unsigned flags = 0;

	/* check if both results are needed */
	for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
		switch (get_Proj_proj(proj)) {
		case pn_DivMod_res_div: flags |= 1; break;
		case pn_DivMod_res_mod: flags |= 2; break;
		default: break;
Michael Beck's avatar
BugFix:    
Michael Beck committed
690
691
		}  /* switch */
	}  /* for */
692
693
694
695
696
697
698
699
700

	irn   = get_DivMod_left(node);
	entry = env->entries[get_irn_idx(irn)];
	assert(entry);

	if (! entry->low_word) {
		/* not ready yet, wait */
		pdeq_putr(env->waitq, node);
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
701
	}  /* if */
702
703
704
705
706
707
708
709
710
711
712
713

	in[0] = entry->low_word;
	in[1] = entry->high_word;

	irn   = get_DivMod_right(node);
	entry = env->entries[get_irn_idx(irn)];
	assert(entry);

	if (! entry->low_word) {
		/* not ready yet, wait */
		pdeq_putr(env->waitq, node);
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
714
	}  /* if */
715
716
717
718

	in[2] = entry->low_word;
	in[3] = entry->high_word;

719
	dbg   = get_irn_dbg_info(node);
720
721
722
723
724
725
726
	block = get_nodes_block(node);

	mem = get_DivMod_mem(node);

	callDiv = callMod = NULL;
	mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
	if (flags & 1) {
Michael Beck's avatar
Michael Beck committed
727
		opmode = get_irn_op_mode(node);
Matthias Braun's avatar
Matthias Braun committed
728
		irn = get_intrinsic_address(mtp, op_Div, opmode, opmode, env);
729
		callDiv = new_rd_Call(dbg, block, mem, irn, 4, in, mtp);
730
		set_irn_pinned(callDiv, get_irn_pinned(node));
731
		resDiv = new_r_Proj(callDiv, mode_T, pn_Call_T_result);
Michael Beck's avatar
BugFix:    
Michael Beck committed
732
	}  /* if */
733
734
	if (flags & 2) {
		if (flags & 1)
735
			mem = new_r_Proj(callDiv, mode_M, pn_Call_M);
Michael Beck's avatar
Michael Beck committed
736
		opmode = get_irn_op_mode(node);
Matthias Braun's avatar
Matthias Braun committed
737
		irn = get_intrinsic_address(mtp, op_Mod, opmode, opmode, env);
738
		callMod = new_rd_Call(dbg, block, mem, irn, 4, in, mtp);
739
		set_irn_pinned(callMod, get_irn_pinned(node));
740
		resMod = new_r_Proj(callMod, mode_T, pn_Call_T_result);
Michael Beck's avatar
BugFix:    
Michael Beck committed
741
	}  /* if */
742
743
744
745
746
747

	for (proj = get_irn_link(node); proj; proj = get_irn_link(proj)) {
		switch (get_Proj_proj(proj)) {
		case pn_DivMod_M:         /* Memory result. */
			/* reroute to the first call */
			set_Proj_pred(proj, callDiv ? callDiv : (callMod ? callMod : mem));
748
			set_Proj_proj(proj, pn_Call_M);
749
750
751
752
753
754
755
756
757
			break;
		case pn_DivMod_X_except:  /* Execution result if exception occurred. */
			/* reroute to the first call */
			set_Proj_pred(proj, callDiv ? callDiv : (callMod ? callMod : mem));
			set_Proj_proj(proj, pn_Call_X_except);
			break;
		case pn_DivMod_res_div:   /* Result of Div. */
			idx = get_irn_idx(proj);
			assert(idx < env->n_entries);
758
			env->entries[idx]->low_word  = new_r_Proj(resDiv, env->low_unsigned, 0);
759
			env->entries[idx]->high_word = new_r_Proj(resDiv, mode,                      1);
760
761
762
			break;
		case pn_DivMod_res_mod:   /* Result of Mod. */
			idx = get_irn_idx(proj);
763
			env->entries[idx]->low_word  = new_r_Proj(resMod, env->low_unsigned, 0);
764
			env->entries[idx]->high_word = new_r_Proj(resMod, mode,                      1);
765
766
767
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
768
		}  /* switch */
769
770
771
		/* mark this proj: we have handled it already, otherwise we might fall into
		 * out new nodes. */
		mark_irn_visited(proj);
Michael Beck's avatar
BugFix:    
Michael Beck committed
772
	}  /* for */
773
}  /* lower_DivMod */
774
775
776
777
778
779

/**
 * Translate a Binop.
 *
 * Create an intrinsic Call.
 */
780
781
static void lower_Binop(ir_node *node, ir_mode *mode, lower_env_t *env)
{
782
783
784
785
786
	ir_node  *block, *irn;
	ir_node  *in[4];
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
787
	ir_graph *irg;
788
789
790
791
792
793
794
795
796
797
	node_entry_t *entry;

	irn   = get_binop_left(node);
	entry = env->entries[get_irn_idx(irn)];
	assert(entry);

	if (! entry->low_word) {
		/* not ready yet, wait */
		pdeq_putr(env->waitq, node);
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
798
	}  /* if */
799
800
801
802
803
804
805
806
807
808
809
810

	in[0] = entry->low_word;
	in[1] = entry->high_word;

	irn   = get_binop_right(node);
	entry = env->entries[get_irn_idx(irn)];
	assert(entry);

	if (! entry->low_word) {
		/* not ready yet, wait */
		pdeq_putr(env->waitq, node);
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
811
	}  /* if */
812
813
814
815

	in[2] = entry->low_word;
	in[3] = entry->high_word;

816
	dbg   = get_irn_dbg_info(node);
817
	block = get_nodes_block(node);
818
	irg   = get_irn_irg(block);
819
820

	mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
Matthias Braun's avatar
Matthias Braun committed
821
	irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, env);
822
	irn = new_rd_Call(dbg, block, get_irg_no_mem(irg), irn, 4, in, mtp);
823
	set_irn_pinned(irn, get_irn_pinned(node));
824
	irn = new_r_Proj(irn, mode_T, pn_Call_T_result);
825
826
827

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
828
829
	env->entries[idx]->low_word  = new_r_Proj(irn, env->low_unsigned, 0);
	env->entries[idx]->high_word = new_r_Proj(irn, mode,              1);
830
}  /* lower_Binop */
831

Christian Würdig's avatar
Christian Würdig committed
832
833
834
835
836
/**
 * Translate a Shiftop.
 *
 * Create an intrinsic Call.
 */
837
838
static void lower_Shiftop(ir_node *node, ir_mode *mode, lower_env_t *env)
{
Christian Würdig's avatar
Christian Würdig committed
839
840
841
842
843
	ir_node  *block, *irn;
	ir_node  *in[3];
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
844
	ir_graph *irg;
Christian Würdig's avatar
Christian Würdig committed
845
846
847
848
849
850
851
852
853
854
	node_entry_t *entry;

	irn   = get_binop_left(node);
	entry = env->entries[get_irn_idx(irn)];
	assert(entry);

	if (! entry->low_word) {
		/* not ready yet, wait */
		pdeq_putr(env->waitq, node);
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
855
	}  /* if */
Christian Würdig's avatar
Christian Würdig committed
856
857
858
859
860
861

	in[0] = entry->low_word;
	in[1] = entry->high_word;

	/* The shift count is always mode_Iu in firm, so there is no need for lowering */
	in[2] = get_binop_right(node);
862
863
	assert(get_irn_mode(in[2]) != env->high_signed
			&& get_irn_mode(in[2]) != env->high_unsigned);
Christian Würdig's avatar
Christian Würdig committed
864
865
866

	dbg   = get_irn_dbg_info(node);
	block = get_nodes_block(node);
867
	irg   = get_irn_irg(block);
Christian Würdig's avatar
Christian Würdig committed
868
869

	mtp = mode_is_signed(mode) ? shiftop_tp_s : shiftop_tp_u;
Matthias Braun's avatar
Matthias Braun committed
870
	irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, env);
871
	irn = new_rd_Call(dbg, block, get_irg_no_mem(irg), irn, 3, in, mtp);
Christian Würdig's avatar
Christian Würdig committed
872
	set_irn_pinned(irn, get_irn_pinned(node));
873
	irn = new_r_Proj(irn, mode_T, pn_Call_T_result);
Christian Würdig's avatar
Christian Würdig committed
874
875
876

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
877
878
	env->entries[idx]->low_word  = new_r_Proj(irn, env->low_unsigned, 0);
	env->entries[idx]->high_word = new_r_Proj(irn, mode,              1);
879
}  /* lower_Shiftop */
Christian Würdig's avatar
Christian Würdig committed
880

Michael Beck's avatar
Michael Beck committed
881
882
883
/**
 * Translate a Shr and handle special cases.
 */
884
885
static void lower_Shr(ir_node *node, ir_mode *mode, lower_env_t *env)
{
886
	ir_graph *irg   = get_irn_irg(node);
887
	ir_node  *right = get_Shr_right(node);
Michael Beck's avatar
Michael Beck committed
888
889
890
891
892

	if (get_mode_arithmetic(mode) == irma_twos_complement && is_Const(right)) {
		tarval *tv = get_Const_tarval(right);

		if (tarval_is_long(tv) &&
893
		    get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
894
895
			ir_node *block        = get_nodes_block(node);
			ir_node *left         = get_Shr_left(node);
896
			ir_mode *low_unsigned = env->low_unsigned;
897
898
			ir_node *c;
			long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode);
Michael Beck's avatar
Michael Beck committed
899
900
901
			int idx = get_irn_idx(left);

			left = env->entries[idx]->high_word;
Matthias Braun's avatar
Matthias Braun committed
902
903
904
905
906
907
			if (left == NULL) {
				/* not ready yet, wait */
				pdeq_putr(env->waitq, node);
				return;
			}

Michael Beck's avatar
Michael Beck committed
908
			idx = get_irn_idx(node);
909
910
911
			/* convert high word into low_unsigned mode if necessary */
			if (get_irn_mode(left) != low_unsigned)
				left = new_r_Conv(block, left, low_unsigned);
Michael Beck's avatar
Michael Beck committed
912

913
			if (shf_cnt > 0) {
914
915
916
				c = new_r_Const_long(irg, low_unsigned, shf_cnt);
				env->entries[idx]->low_word = new_r_Shr(block, left, c,
				                                        low_unsigned);
Michael Beck's avatar
BugFix:    
Michael Beck committed
917
			} else {
918
				env->entries[idx]->low_word = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
919
			}  /* if */
920
			env->entries[idx]->high_word = new_r_Const(irg, get_mode_null(mode));
Michael Beck's avatar
Michael Beck committed
921
922

			return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
923
924
		}  /* if */
	}  /* if */
Michael Beck's avatar
Michael Beck committed
925
	lower_Shiftop(node, mode, env);
926
}  /* lower_Shr */
Michael Beck's avatar
Michael Beck committed
927
928
929
930

/**
 * Translate a Shl and handle special cases.
 */
931
932
static void lower_Shl(ir_node *node, ir_mode *mode, lower_env_t *env)
{
933
	ir_graph *irg   = get_irn_irg(node);
934
	ir_node  *right = get_Shl_right(node);
Michael Beck's avatar
Michael Beck committed
935
936
937
938
939

	if (get_mode_arithmetic(mode) == irma_twos_complement && is_Const(right)) {
		tarval *tv = get_Const_tarval(right);

		if (tarval_is_long(tv) &&
940
		    get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
941
			ir_mode *mode_l;
Michael Beck's avatar
Michael Beck committed
942
943
			ir_node *block = get_nodes_block(node);
			ir_node *left = get_Shl_left(node);
944
945
			ir_node *c;
			long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode);
Michael Beck's avatar
Michael Beck committed
946
947
			int idx = get_irn_idx(left);

948
949
950
951
952
953
954
955
			left = env->entries[idx]->low_word;
			if (left == NULL) {
				/* not ready yet, wait */
				pdeq_putr(env->waitq, node);
				return;
			}

			left = new_r_Conv(block, left, mode);
Michael Beck's avatar
Michael Beck committed
956
957
			idx = get_irn_idx(node);

958
			mode_l = env->low_unsigned;
959
			if (shf_cnt > 0) {
960
				c = new_r_Const_long(irg, mode_l, shf_cnt);
961
				env->entries[idx]->high_word = new_r_Shl(block, left, c, mode);
Michael Beck's avatar
BugFix:    
Michael Beck committed
962
			} else {
963
				env->entries[idx]->high_word = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
964
			}  /* if */
965
			env->entries[idx]->low_word  = new_r_Const(irg, get_mode_null(mode_l));
Michael Beck's avatar
Michael Beck committed
966
967

			return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
968
969
		}  /* if */
	}  /* if */
Michael Beck's avatar
Michael Beck committed
970
	lower_Shiftop(node, mode, env);
971
}  /* lower_Shl */
Michael Beck's avatar
Michael Beck committed
972
973
974
975

/**
 * Translate a Shrs and handle special cases.
 */
976
977
static void lower_Shrs(ir_node *node, ir_mode *mode, lower_env_t *env)
{
978
	ir_graph *irg   = get_irn_irg(node);
979
	ir_node  *right = get_Shrs_right(node);
Michael Beck's avatar
Michael Beck committed
980
981
982
983
984

	if (get_mode_arithmetic(mode) == irma_twos_complement && is_Const(right)) {
		tarval *tv = get_Const_tarval(right);

		if (tarval_is_long(tv) &&
985
		    get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
986
987
			ir_node *block         = get_nodes_block(node);
			ir_node *left          = get_Shrs_left(node);
988
			ir_mode *low_unsigned  = env->low_unsigned;
989
990
991
			long     shf_cnt       = get_tarval_long(tv) - get_mode_size_bits(mode);
			int      idx           = get_irn_idx(left);
			ir_node *left_unsigned = left;
992
			ir_node *low;
Michael Beck's avatar
Michael Beck committed
993
994
995
			ir_node *c;

			left = env->entries[idx]->high_word;
996
997
998
999
1000
			if (left == NULL) {
				/* not ready yet, wait */
				pdeq_putr(env->waitq, node);
				return;
			}
Michael Beck's avatar
Michael Beck committed
1001

1002
1003
1004
1005
1006
			idx = get_irn_idx(node);
			/* convert high word into low_unsigned mode if necessary */
			if (get_irn_mode(left_unsigned) != low_unsigned)
				left_unsigned = new_r_Conv(block, left, low_unsigned);

1007
			if (shf_cnt > 0) {
1008
1009
				c   = new_r_Const_long(irg, low_unsigned, shf_cnt);
				low = new_r_Shrs(block, left_unsigned, c, low_unsigned);
Michael Beck's avatar
BugFix:    
Michael Beck committed
1010
			} else {
1011
				low = left_unsigned;
Michael Beck's avatar
BugFix:    
Michael Beck committed
1012
			}  /* if */
1013
1014
			/* low word is expected to have low_unsigned */
			env->entries[idx]->low_word = new_r_Conv(block, low, low_unsigned);
1015

1016
1017
			c = new_r_Const_long(irg, low_unsigned,
			                     get_mode_size_bits(mode) - 1);
1018
			env->entries[idx]->high_word = new_r_Shrs(block, left, c, mode);
Michael Beck's avatar
Michael Beck committed
1019
1020

			return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
1021
1022
		}  /* if */
	}  /* if */
Michael Beck's avatar
Michael Beck committed
1023
	lower_Shiftop(node, mode, env);
1024
}  /* lower_Shrs */
Michael Beck's avatar
Michael Beck committed
1025
1026

/**
Michael Beck's avatar
Michael Beck committed
1027
 * Rebuild Rotl nodes into Or(Shl, Shr) and prepare all nodes.
Michael Beck's avatar
Michael Beck committed
1028
 */
1029
1030
static void prepare_links_and_handle_rotl(ir_node *node, void *env)
{
Michael Beck's avatar
Michael Beck committed
1031
1032
1033
1034
	lower_env_t *lenv = env;

	if (is_Rotl(node)) {
		ir_mode *mode = get_irn_op_mode(node);
1035
1036
			if (mode == lenv->high_signed ||
			    mode == lenv->high_unsigned) {
Michael Beck's avatar
Michael Beck committed
1037
1038
1039
				ir_node  *right = get_Rotl_right(node);
				ir_node  *left, *shl, *shr, *or, *block, *sub, *c;
				ir_mode  *omode, *rmode;
1040
				ir_graph *irg;