lower_dw.c 72.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
58
59
60
/** A map from mode to a primitive type. */
static pmap *prim_types;

/** A map from (op, imode, omode) to Intrinsic functions entities. */
61
62
static set *intrinsic_fkt;

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

66
67
68
69
/** 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
70
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;
71
72
73
74
75

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

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

Michael Beck's avatar
Michael Beck committed
85
86
87
88
89
90
91
92
93
/**
 * An entry in the (imode, omode) -> tp map.
 */
typedef struct _conv_tp_entry {
	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;

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

enum lower_flags {
104
105
	MUST_BE_LOWERED = 1,  /**< graph must be lowered */
	CF_CHANGED      = 2,  /**< control flow was changed */
106
107
108
109
110
111
112
113
};

/**
 * The lower environment.
 */
typedef struct _lower_env_t {
	node_entry_t **entries;       /**< entries per node */
	struct obstack obst;          /**< an obstack holding the temporary data */
114
	ir_type  *l_mtp;              /**< lowered method type of the current method */
Michael Beck's avatar
BugFix:    
Michael Beck committed
115
116
	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 */
117
118
	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 */
119
120
	ident    *first_id;           /**< .l for little and .h for big endian */
	ident    *next_id;            /**< .h for little and .l for big endian */
121
122
123
	const lwrdw_param_t *params;  /**< transformation parameter */
	unsigned flags;               /**< some flags */
	int      n_entries;           /**< number of entries */
124
	ir_type  *value_param_tp;     /**< the old value param type */
125
126
} lower_env_t;

Michael Beck's avatar
Michael Beck committed
127
128
129
/**
 * Get a primitive mode for a mode.
 */
130
131
static ir_type *get_primitive_type(ir_mode *mode)
{
Michael Beck's avatar
Michael Beck committed
132
133
134
135
136
137
138
139
	pmap_entry *entry = pmap_find(prim_types, mode);
	ir_type *tp;
	char buf[64];

	if (entry)
		return entry->value;

	snprintf(buf, sizeof(buf), "_prim_%s", get_mode_name(mode));
140
	tp = new_type_primitive(mode);
Michael Beck's avatar
Michael Beck committed
141
142
143

	pmap_insert(prim_types, mode, tp);
	return tp;
144
}  /* get_primitive_type */
Michael Beck's avatar
Michael Beck committed
145
146
147
148

/**
 * Create a method type for a Conv emulation from imode to omode.
 */
149
150
static ir_type *get_conv_type(ir_mode *imode, ir_mode *omode, lower_env_t *env)
{
Michael Beck's avatar
Michael Beck committed
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
	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;

		if (imode == env->params->high_signed || imode == env->params->high_unsigned)
			n_param = 2;
		if (omode == env->params->high_signed || omode == env->params->high_unsigned)
			n_res = 2;

		/* create a new one */
168
		mtd = new_type_method(n_param, n_res);
Michael Beck's avatar
Michael Beck committed
169
170
171
172

		/* set param types and result types */
		n_param = 0;
		if (imode == env->params->high_signed) {
173
			set_method_param_type(mtd, n_param++, tp_u);
Michael Beck's avatar
Michael Beck committed
174
			set_method_param_type(mtd, n_param++, tp_s);
Michael Beck's avatar
BugFix:    
Michael Beck committed
175
		} else if (imode == env->params->high_unsigned) {
Michael Beck's avatar
Michael Beck committed
176
177
			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
178
		} else {
Michael Beck's avatar
Michael Beck committed
179
180
			ir_type *tp = get_primitive_type(imode);
			set_method_param_type(mtd, n_param++, tp);
Michael Beck's avatar
BugFix:    
Michael Beck committed
181
		}  /* if */
Michael Beck's avatar
Michael Beck committed
182
183
184

		n_res = 0;
		if (omode == env->params->high_signed) {
185
			set_method_res_type(mtd, n_res++, tp_u);
Michael Beck's avatar
Michael Beck committed
186
			set_method_res_type(mtd, n_res++, tp_s);
Michael Beck's avatar
BugFix:    
Michael Beck committed
187
		} else if (omode == env->params->high_unsigned) {
Michael Beck's avatar
Michael Beck committed
188
189
			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
190
		} else {
Michael Beck's avatar
Michael Beck committed
191
192
			ir_type *tp = get_primitive_type(omode);
			set_method_res_type(mtd, n_res++, tp);
Michael Beck's avatar
BugFix:    
Michael Beck committed
193
		}  /* if */
Michael Beck's avatar
Michael Beck committed
194
		entry->mtd = mtd;
Michael Beck's avatar
BugFix:    
Michael Beck committed
195
	} else {
Michael Beck's avatar
Michael Beck committed
196
		mtd = entry->mtd;
Michael Beck's avatar
BugFix:    
Michael Beck committed
197
	}  /* if */
Michael Beck's avatar
Michael Beck committed
198
	return mtd;
199
}  /* get_conv_type */
Michael Beck's avatar
Michael Beck committed
200

201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/**
 * 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);

220
	for (phi = get_Block_phis(block); phi != NULL; phi = get_Phi_next(phi)) {
221
222
223
224
		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
225
	}  /* for */
226
}  /* add_block_cf_input_nr */
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241

/**
 * 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
242
243
		}  /* if */
	}  /* for */
244
245
	assert(i < arity);
	add_block_cf_input_nr(block, nr, cf);
246
}  /* add_block_cf_input */
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267

/**
 * 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
268
	}  /* switch */
269
}  /* get_irn_op_mode */
270
271

/**
272
 * Walker, prepare the node links.
273
274
275
276
277
278
 */
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
279
	int          i, idx;
280
281
282
283

	if (mode == lenv->params->high_signed ||
		mode == lenv->params->high_unsigned) {
		/* ok, found a node that will be lowered */
284
		link = OALLOCZ(&lenv->obst, node_entry_t);
285

Michael Beck's avatar
Michael Beck committed
286
287
288
289
290
291
292
293
294
295
296
		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;
297
		lenv->flags |= MUST_BE_LOWERED;
298
	} else if (is_Conv(node)) {
299
300
301
302
303
304
		/* Conv nodes have two modes */
		ir_node *pred = get_Conv_op(node);
		mode = get_irn_mode(pred);

		if (mode == lenv->params->high_signed ||
			mode == lenv->params->high_unsigned) {
Michael Beck's avatar
BugFix:    
Michael Beck committed
305
			/* must lower this node either but don't need a link */
306
			lenv->flags |= MUST_BE_LOWERED;
Michael Beck's avatar
BugFix:    
Michael Beck committed
307
		}  /* if */
308
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
309
	}  /* if */
310
311
312
313
314
315
316
317

	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
318
	} else if (is_Phi(node)) {
319
320
		/* link all Phi nodes to its block */
		ir_node *block = get_nodes_block(node);
321
		add_Block_phi(block, node);
Michael Beck's avatar
BugFix:    
Michael Beck committed
322
	} else if (is_Block(node)) {
323
324
325
326
327
328
		/* 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
329
330
		}  /* for */
	}  /* if */
331
}  /* prepare_links */
332
333
334
335

/**
 * Translate a Constant: create two.
 */
336
337
static void lower_Const(ir_node *node, ir_mode *mode, lower_env_t *env)
{
338
339
340
341
	tarval   *tv, *tv_l, *tv_h;
	ir_node  *low, *high;
	dbg_info *dbg = get_irn_dbg_info(node);
	int      idx;
342
	ir_graph *irg = current_ir_graph;
343
	ir_mode  *low_mode = env->params->low_unsigned;
344
345
346

	tv   = get_Const_tarval(node);

347
	tv_l = tarval_convert_to(tv, low_mode);
348
	low  = new_rd_Const(dbg, irg, tv_l);
349

Michael Beck's avatar
BugFix:    
Michael Beck committed
350
	tv_h = tarval_convert_to(tarval_shrs(tv, env->tv_mode_bits), mode);
351
	high = new_rd_Const(dbg, irg, tv_h);
352
353
354
355
356

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
	env->entries[idx]->low_word  = low;
	env->entries[idx]->high_word = high;
357
}  /* lower_Const */
358
359
360
361

/**
 * Translate a Load: create two.
 */
362
363
static void lower_Load(ir_node *node, ir_mode *mode, lower_env_t *env)
{
364
365
366
367
368
369
370
371
	ir_mode    *low_mode = env->params->low_unsigned;
	ir_graph   *irg = current_ir_graph;
	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;
372
	ir_cons_flags volatility = get_Load_volatility(node) == volatility_is_volatile
373
	                         ? cons_volatile : 0;
374
375
376

	if (env->params->little_endian) {
		low  = adr;
377
		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
378
	} else {
379
		low  = new_r_Add(block, adr, new_r_Const(irg, env->tv_mode_bytes), get_irn_mode(adr));
380
		high = adr;
Michael Beck's avatar
BugFix:    
Michael Beck committed
381
	}  /* if */
382
383
384

	/* create two loads */
	dbg  = get_irn_dbg_info(node);
385
	low  = new_rd_Load(dbg, block, mem,  low,  low_mode, volatility);
386
	proj = new_r_Proj(low, mode_M, pn_Load_M);
387
	high = new_rd_Load(dbg, block, proj, high, mode, volatility);
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407

	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);
408
409
			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);
410
411
412
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
413
		}  /* switch */
414
415
416
		/* 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
417
	}  /* for */
418
}  /* lower_Load */
419
420
421
422

/**
 * Translate a Store: create two.
 */
423
424
static void lower_Store(ir_node *node, ir_mode *mode, lower_env_t *env)
{
425
426
427
428
429
	ir_graph     *irg;
	ir_node      *block, *adr, *mem;
	ir_node      *low, *high, *irn, *proj;
	dbg_info     *dbg;
	int           idx;
430
	node_entry_t *entry;
431
	ir_cons_flags    volatility = get_Store_volatility(node) == volatility_is_volatile
432
	                           ? cons_volatile : 0;
Matthias Braun's avatar
Matthias Braun committed
433
	(void) mode;
434
435
436
437
438
439
440
441
442

	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
443
	}  /* if */
444
445
446
447
448
449
450
451

	irg = current_ir_graph;
	adr = get_Store_ptr(node);
	mem = get_Store_mem(node);
	block = get_nodes_block(node);

	if (env->params->little_endian) {
		low  = adr;
452
		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
453
	} else {
454
		low  = new_r_Add(block, adr, new_r_Const(irg, env->tv_mode_bytes), get_irn_mode(adr));
455
		high = adr;
Michael Beck's avatar
BugFix:    
Michael Beck committed
456
	}  /* if */
457
458
459

	/* create two Stores */
	dbg = get_irn_dbg_info(node);
460
	low  = new_rd_Store(dbg, block, mem, low,  entry->low_word, volatility);
461
	proj = new_r_Proj(low, mode_M, pn_Store_M);
462
	high = new_rd_Store(dbg, block, proj, high, entry->high_word, volatility);
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482

	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
483
		}  /* switch */
484
485
486
		/* 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
487
	}  /* for */
488
}  /* lower_Store */
489
490
491

/**
 * Return a node containing the address of the intrinsic emulation function.
Michael Beck's avatar
Michael Beck committed
492
493
494
495
496
497
 *
 * @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
498
 */
Michael Beck's avatar
Michael Beck committed
499
500
static ir_node *get_intrinsic_address(ir_type *method, ir_op *op,
                                      ir_mode *imode, ir_mode *omode,
501
502
                                      lower_env_t *env)
{
503
	symconst_symbol sym;
504
	ir_entity *ent;
505
506
	op_mode_entry_t key, *entry;

Michael Beck's avatar
Michael Beck committed
507
508
509
510
	key.op    = op;
	key.imode = imode;
	key.omode = omode;
	key.ent   = NULL;
511

Michael Beck's avatar
Michael Beck committed
512
513
	entry = set_insert(intrinsic_fkt, &key, sizeof(key),
				HASH_PTR(op) ^ HASH_PTR(imode) ^ (HASH_PTR(omode) << 8));
514
515
	if (! entry->ent) {
		/* create a new one */
Michael Beck's avatar
Michael Beck committed
516
		ent = env->params->create_intrinsic(method, op, imode, omode, env->params->ctx);
517
518
519

		assert(ent && "Intrinsic creator must return an entity");
		entry->ent = ent;
Michael Beck's avatar
BugFix:    
Michael Beck committed
520
	} else {
521
		ent = entry->ent;
Michael Beck's avatar
BugFix:    
Michael Beck committed
522
	}  /* if */
523
	sym.entity_p = ent;
524
	return new_r_SymConst(current_ir_graph, mode_P_code, sym, symconst_addr_ent);
525
}  /* get_intrinsic_address */
526
527
528
529
530
531

/**
 * Translate a Div.
 *
 * Create an intrinsic Call.
 */
532
533
static void lower_Div(ir_node *node, ir_mode *mode, lower_env_t *env)
{
534
535
	ir_node  *block, *irn, *call, *proj;
	ir_node  *in[4];
Michael Beck's avatar
Michael Beck committed
536
	ir_mode  *opmode;
537
538
539
540
541
542
543
544
545
546
547
548
549
	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
550
	}  /* if */
551
552
553
554
555
556
557
558
559
560
561
562

	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
563
	}  /* if */
564
565
566
567

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

568
	dbg   = get_irn_dbg_info(node);
569
570
571
	block = get_nodes_block(node);

	mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
Michael Beck's avatar
Michael Beck committed
572
	opmode = get_irn_op_mode(node);
Matthias Braun's avatar
Matthias Braun committed
573
	irn = get_intrinsic_address(mtp, get_irn_op(node), opmode, opmode, env);
574
	call = new_rd_Call(dbg, block, get_Div_mem(node), irn, 4, in, mtp);
575
	set_irn_pinned(call, get_irn_pinned(node));
576
	irn = new_r_Proj(call, mode_T, pn_Call_T_result);
577
578
579
580
581
582

	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);
583
			set_Proj_proj(proj, pn_Call_M);
584
585
586
587
588
589
590
591
592
			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);
593
594
			env->entries[idx]->low_word  = new_r_Proj(irn, env->params->low_unsigned, 0);
			env->entries[idx]->high_word = new_r_Proj(irn, mode,                      1);
595
596
597
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
598
		}  /* switch */
599
600
601
		/* 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
602
	}  /* for */
603
}  /* lower_Div */
604
605
606
607
608
609

/**
 * Translate a Mod.
 *
 * Create an intrinsic Call.
 */
610
611
static void lower_Mod(ir_node *node, ir_mode *mode, lower_env_t *env)
{
612
613
	ir_node  *block, *proj, *irn, *call;
	ir_node  *in[4];
Michael Beck's avatar
Michael Beck committed
614
	ir_mode  *opmode;
615
616
617
618
619
620
621
622
623
624
625
626
627
	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
628
	}  /* if */
629
630
631
632
633
634
635
636
637
638
639
640

	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
641
	}  /* if */
642
643
644
645

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

646
	dbg   = get_irn_dbg_info(node);
647
648
649
	block = get_nodes_block(node);

	mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
Michael Beck's avatar
Michael Beck committed
650
	opmode = get_irn_op_mode(node);
Matthias Braun's avatar
Matthias Braun committed
651
	irn = get_intrinsic_address(mtp, get_irn_op(node), opmode, opmode, env);
652
	call = new_rd_Call(dbg, block, get_Mod_mem(node), irn, 4, in, mtp);
653
	set_irn_pinned(call, get_irn_pinned(node));
654
	irn = new_r_Proj(call, mode_T, pn_Call_T_result);
655
656
657
658
659
660

	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);
661
			set_Proj_proj(proj, pn_Call_M);
662
663
664
665
666
667
668
669
670
			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);
671
672
			env->entries[idx]->low_word  = new_r_Proj(irn, env->params->low_unsigned, 0);
			env->entries[idx]->high_word = new_r_Proj(irn, mode,                      1);
673
674
675
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
676
		}  /* switch */
677
678
679
		/* 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
680
	}  /* for */
681
}  /* lower_Mod */
682
683
684
685
686
687

/**
 * Translate a DivMod.
 *
 * Create two intrinsic Calls.
 */
688
689
static void lower_DivMod(ir_node *node, ir_mode *mode, lower_env_t *env)
{
Matthias Braun's avatar
Matthias Braun committed
690
691
692
	ir_node  *block, *proj, *irn, *mem, *callDiv, *callMod;
	ir_node  *resDiv = NULL;
	ir_node  *resMod = NULL;
693
	ir_node  *in[4];
Michael Beck's avatar
Michael Beck committed
694
	ir_mode  *opmode;
695
696
697
698
699
700
701
702
703
704
705
706
	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
707
708
		}  /* switch */
	}  /* for */
709
710
711
712
713
714
715
716
717

	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
718
	}  /* if */
719
720
721
722
723
724
725
726
727
728
729
730

	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
731
	}  /* if */
732
733
734
735

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

736
	dbg   = get_irn_dbg_info(node);
737
738
739
740
741
742
743
	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
744
		opmode = get_irn_op_mode(node);
Matthias Braun's avatar
Matthias Braun committed
745
		irn = get_intrinsic_address(mtp, op_Div, opmode, opmode, env);
746
		callDiv = new_rd_Call(dbg, block, mem, irn, 4, in, mtp);
747
		set_irn_pinned(callDiv, get_irn_pinned(node));
748
		resDiv = new_r_Proj(callDiv, mode_T, pn_Call_T_result);
Michael Beck's avatar
BugFix:    
Michael Beck committed
749
	}  /* if */
750
751
	if (flags & 2) {
		if (flags & 1)
752
			mem = new_r_Proj(callDiv, mode_M, pn_Call_M);
Michael Beck's avatar
Michael Beck committed
753
		opmode = get_irn_op_mode(node);
Matthias Braun's avatar
Matthias Braun committed
754
		irn = get_intrinsic_address(mtp, op_Mod, opmode, opmode, env);
755
		callMod = new_rd_Call(dbg, block, mem, irn, 4, in, mtp);
756
		set_irn_pinned(callMod, get_irn_pinned(node));
757
		resMod = new_r_Proj(callMod, mode_T, pn_Call_T_result);
Michael Beck's avatar
BugFix:    
Michael Beck committed
758
	}  /* if */
759
760
761
762
763
764

	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));
765
			set_Proj_proj(proj, pn_Call_M);
766
767
768
769
770
771
772
773
774
			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);
775
776
			env->entries[idx]->low_word  = new_r_Proj(resDiv, env->params->low_unsigned, 0);
			env->entries[idx]->high_word = new_r_Proj(resDiv, mode,                      1);
777
778
779
			break;
		case pn_DivMod_res_mod:   /* Result of Mod. */
			idx = get_irn_idx(proj);
780
781
			env->entries[idx]->low_word  = new_r_Proj(resMod, env->params->low_unsigned, 0);
			env->entries[idx]->high_word = new_r_Proj(resMod, mode,                      1);
782
783
784
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
785
		}  /* switch */
786
787
788
		/* 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
789
	}  /* for */
790
}  /* lower_DivMod */
791
792
793
794
795
796

/**
 * Translate a Binop.
 *
 * Create an intrinsic Call.
 */
797
798
static void lower_Binop(ir_node *node, ir_mode *mode, lower_env_t *env)
{
799
800
801
802
803
	ir_node  *block, *irn;
	ir_node  *in[4];
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
804
	ir_graph *irg;
805
806
807
808
809
810
811
812
813
814
	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
815
	}  /* if */
816
817
818
819
820
821
822
823
824
825
826
827

	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
828
	}  /* if */
829
830
831
832

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

833
	dbg   = get_irn_dbg_info(node);
834
	block = get_nodes_block(node);
835
	irg   = current_ir_graph;
836
837

	mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
Matthias Braun's avatar
Matthias Braun committed
838
	irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, env);
839
	irn = new_rd_Call(dbg, block, get_irg_no_mem(current_ir_graph),
840
841
		irn, 4, in, mtp);
	set_irn_pinned(irn, get_irn_pinned(node));
842
	irn = new_r_Proj(irn, mode_T, pn_Call_T_result);
843
844
845

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
846
847
	env->entries[idx]->low_word  = new_r_Proj(irn, env->params->low_unsigned, 0);
	env->entries[idx]->high_word = new_r_Proj(irn, mode,                      1);
848
}  /* lower_Binop */
849

Christian Würdig's avatar
Christian Würdig committed
850
851
852
853
854
/**
 * Translate a Shiftop.
 *
 * Create an intrinsic Call.
 */
855
856
static void lower_Shiftop(ir_node *node, ir_mode *mode, lower_env_t *env)
{
Christian Würdig's avatar
Christian Würdig committed
857
858
859
860
861
	ir_node  *block, *irn;
	ir_node  *in[3];
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
862
	ir_graph *irg;
Christian Würdig's avatar
Christian Würdig committed
863
864
865
866
867
868
869
870
871
872
	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
873
	}  /* if */
Christian Würdig's avatar
Christian Würdig committed
874
875
876
877
878
879

	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);
Matthias Braun's avatar
Matthias Braun committed
880
881
	assert(get_irn_mode(in[2]) != env->params->high_signed
			&& get_irn_mode(in[2]) != env->params->high_unsigned);
Christian Würdig's avatar
Christian Würdig committed
882
883
884

	dbg   = get_irn_dbg_info(node);
	block = get_nodes_block(node);
885
	irg  = current_ir_graph;
Christian Würdig's avatar
Christian Würdig committed
886
887

	mtp = mode_is_signed(mode) ? shiftop_tp_s : shiftop_tp_u;
Matthias Braun's avatar
Matthias Braun committed
888
	irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, env);
889
	irn = new_rd_Call(dbg, block, get_irg_no_mem(current_ir_graph),
Christian Würdig's avatar
Christian Würdig committed
890
891
		irn, 3, in, mtp);
	set_irn_pinned(irn, get_irn_pinned(node));
892
	irn = new_r_Proj(irn, mode_T, pn_Call_T_result);
Christian Würdig's avatar
Christian Würdig committed
893
894
895

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

Michael Beck's avatar
Michael Beck committed
900
901
902
/**
 * Translate a Shr and handle special cases.
 */
903
904
static void lower_Shr(ir_node *node, ir_mode *mode, lower_env_t *env)
{
905
906
	ir_node  *right = get_Shr_right(node);
	ir_graph *irg = current_ir_graph;
Michael Beck's avatar
Michael Beck committed
907
908
909
910
911

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

		if (tarval_is_long(tv) &&
912
		    get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
Michael Beck's avatar
Michael Beck committed
913
914
			ir_node *block = get_nodes_block(node);
			ir_node *left = get_Shr_left(node);
915
916
			ir_node *c;
			long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode);
Michael Beck's avatar
Michael Beck committed
917
918
919
			int idx = get_irn_idx(left);

			left = env->entries[idx]->high_word;
Matthias Braun's avatar
Matthias Braun committed
920
921
922
923
924
925
			if (left == NULL) {
				/* not ready yet, wait */
				pdeq_putr(env->waitq, node);
				return;
			}

Michael Beck's avatar
Michael Beck committed
926
927
			idx = get_irn_idx(node);

928
			if (shf_cnt > 0) {
929
				c = new_r_Const_long(irg, env->params->low_unsigned, shf_cnt);
930
				env->entries[idx]->low_word = new_r_Shr(block, left, c, mode);
Michael Beck's avatar
BugFix:    
Michael Beck committed
931
			} else {
932
				env->entries[idx]->low_word = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
933
			}  /* if */
934
			env->entries[idx]->high_word = new_r_Const(irg, get_mode_null(mode));
Michael Beck's avatar
Michael Beck committed
935
936

			return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
937
938
		}  /* if */
	}  /* if */
Michael Beck's avatar
Michael Beck committed
939
	lower_Shiftop(node, mode, env);
940
}  /* lower_Shr */
Michael Beck's avatar
Michael Beck committed
941
942
943
944

/**
 * Translate a Shl and handle special cases.
 */
945
946
static void lower_Shl(ir_node *node, ir_mode *mode, lower_env_t *env)
{
947
948
	ir_node  *right = get_Shl_right(node);
	ir_graph *irg = current_ir_graph;
Michael Beck's avatar
Michael Beck committed
949
950
951
952
953

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

		if (tarval_is_long(tv) &&
954
		    get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
955
			ir_mode *mode_l;
Michael Beck's avatar
Michael Beck committed
956
957
			ir_node *block = get_nodes_block(node);
			ir_node *left = get_Shl_left(node);
958
959
			ir_node *c;
			long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode);
Michael Beck's avatar
Michael Beck committed
960
961
			int idx = get_irn_idx(left);

962
			left = new_r_Conv(block, env->entries[idx]->low_word, mode);
Michael Beck's avatar
Michael Beck committed
963
964
			idx = get_irn_idx(node);

965
			mode_l = env->params->low_unsigned;
966
			if (shf_cnt > 0) {
967
				c = new_r_Const_long(irg, mode_l, shf_cnt);
968
				env->entries[idx]->high_word = new_r_Shl(block, left, c, mode);
Michael Beck's avatar
BugFix:    
Michael Beck committed
969
			} else {
970
				env->entries[idx]->high_word = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
971
			}  /* if */
972
			env->entries[idx]->low_word  = new_r_Const(irg, get_mode_null(mode_l));
Michael Beck's avatar
Michael Beck committed
973
974

			return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
975
976
		}  /* if */
	}  /* if */
Michael Beck's avatar
Michael Beck committed
977
	lower_Shiftop(node, mode, env);
978
}  /* lower_Shl */
Michael Beck's avatar
Michael Beck committed
979
980
981
982

/**
 * Translate a Shrs and handle special cases.
 */
983
984
static void lower_Shrs(ir_node *node, ir_mode *mode, lower_env_t *env)
{
985
986
	ir_node  *right = get_Shrs_right(node);
	ir_graph *irg = current_ir_graph;
Michael Beck's avatar
Michael Beck committed
987
988
989
990
991

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

		if (tarval_is_long(tv) &&
992
		    get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
993
994
995
996
			ir_node *block   = get_nodes_block(node);
			ir_node *left    = get_Shrs_left(node);
			long     shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode);
			int      idx     = get_irn_idx(left);
997
			ir_mode *mode_l;
998
			ir_node *low;
Michael Beck's avatar
Michael Beck committed
999
1000
			ir_node *c;