lower_dw.c 72.4 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
27
28
29
30
31
32
33
34
35
36
37
38
39
 */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STDLIB_H
# include <stdlib.h>
#endif

#include <assert.h>

40
#include "lowering.h"
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#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
59
#include "irdump.h"
60
#include "array_t.h"
61
#include "xmalloc.h"
62

Michael Beck's avatar
Michael Beck committed
63
64
65
66
/** A map from mode to a primitive type. */
static pmap *prim_types;

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

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

72
73
74
75
/** 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
76
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;
77
78
79
80
81

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

/**
Michael Beck's avatar
Michael Beck committed
82
 * An entry in the (op, imode, omode) -> entity map.
83
84
85
 */
typedef struct _op_mode_entry {
	const ir_op   *op;    /**< the op */
Michael Beck's avatar
Michael Beck committed
86
87
	const ir_mode *imode; /**< the input mode */
	const ir_mode *omode; /**< the output mode */
88
	ir_entity     *ent;   /**< the associated entity of this (op, imode, omode) triple */
89
90
} op_mode_entry_t;

Michael Beck's avatar
Michael Beck committed
91
92
93
94
95
96
97
98
99
/**
 * 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;

100
101
102
103
104
/**
 * Every double word node will be replaced,
 * we need some store to hold the replacement:
 */
typedef struct _node_entry_t {
105
106
	ir_node *low_word;    /**< the low word */
	ir_node *high_word;   /**< the high word */
107
108
109
} node_entry_t;

enum lower_flags {
110
111
	MUST_BE_LOWERED = 1,  /**< graph must be lowered */
	CF_CHANGED      = 2,  /**< control flow was changed */
112
113
114
115
116
117
118
119
};

/**
 * The lower environment.
 */
typedef struct _lower_env_t {
	node_entry_t **entries;       /**< entries per node */
	struct obstack obst;          /**< an obstack holding the temporary data */
Michael Beck's avatar
BugFix:    
Michael Beck committed
120
121
	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 */
122
123
124
125
126
127
128
	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 */
	const lwrdw_param_t *params;  /**< transformation parameter */
	unsigned flags;               /**< some flags */
	int      n_entries;           /**< number of entries */
} lower_env_t;

Michael Beck's avatar
Michael Beck committed
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/**
 * Get a primitive mode for a mode.
 */
static ir_type *get_primitive_type(ir_mode *mode) {
	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));
	tp = new_type_primitive(new_id_from_str(buf), mode);

	pmap_insert(prim_types, mode, tp);
	return tp;
145
}  /* get_primitive_type */
Michael Beck's avatar
Michael Beck committed
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

/**
 * Create a method type for a Conv emulation from imode to omode.
 */
static ir_type *get_conv_type(ir_mode *imode, ir_mode *omode, lower_env_t *env) {
	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;
		char buf[64];

		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 */
		snprintf(buf, sizeof(buf), "LConv%s%s", get_mode_name(imode), get_mode_name(omode));
		mtd = new_type_method(new_id_from_str(buf), n_param, n_res);

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

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

203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/**
 * 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);

	for (phi = get_irn_link(block); phi; phi = get_irn_link(phi)) {
		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
227
	}  /* for */
228
}  /* add_block_cf_input_nr */
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243

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

/**
 * 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
270
	}  /* switch */
271
}  /* get_irn_op_mode */
272
273

/**
274
 * Walker, prepare the node links.
275
276
277
278
279
280
 */
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
281
	int          i, idx;
282
283
284
285
286
287
288
289

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

		memset(link, 0, sizeof(*link));

Michael Beck's avatar
Michael Beck committed
290
291
292
293
294
295
296
297
298
299
300
		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;
301
		lenv->flags |= MUST_BE_LOWERED;
302
	} else if (is_Conv(node)) {
303
304
305
306
307
308
		/* 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
309
			/* must lower this node either but don't need a link */
310
			lenv->flags |= MUST_BE_LOWERED;
Michael Beck's avatar
BugFix:    
Michael Beck committed
311
		}  /* if */
312
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
313
	}  /* if */
314
315
316
317
318
319
320
321

	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
322
	} else if (is_Phi(node)) {
323
324
325
326
327
		/* link all Phi nodes to its block */
		ir_node *block = get_nodes_block(node);

		set_irn_link(node, get_irn_link(block));
		set_irn_link(block, node);
Michael Beck's avatar
BugFix:    
Michael Beck committed
328
	} else if (is_Block(node)) {
329
330
331
332
333
334
		/* 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
335
336
		}  /* for */
	}  /* if */
337
}  /* prepare_links */
338
339
340
341
342
343
344
345
346
347

/**
 * Translate a Constant: create two.
 */
static void lower_Const(ir_node *node, ir_mode *mode, lower_env_t *env) {
	tarval   *tv, *tv_l, *tv_h;
	ir_node  *low, *high;
	dbg_info *dbg = get_irn_dbg_info(node);
	ir_node  *block = get_nodes_block(node);
	int      idx;
348
	ir_graph *irg = current_ir_graph;
349
	ir_mode  *low_mode = env->params->low_unsigned;
350
351
352

	tv   = get_Const_tarval(node);

353
354
	tv_l = tarval_convert_to(tv, low_mode);
	low  = new_rd_Const(dbg, irg, block, low_mode, tv_l);
355

Michael Beck's avatar
BugFix:    
Michael Beck committed
356
	tv_h = tarval_convert_to(tarval_shrs(tv, env->tv_mode_bits), mode);
357
	high = new_rd_Const(dbg, irg, block, mode, tv_h);
358
359
360
361
362

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
	env->entries[idx]->low_word  = low;
	env->entries[idx]->high_word = high;
363
}  /* lower_Const */
364
365
366
367
368

/**
 * Translate a Load: create two.
 */
static void lower_Load(ir_node *node, ir_mode *mode, lower_env_t *env) {
369
	ir_mode  *low_mode = env->params->low_unsigned;
370
371
372
373
374
375
376
377
378
379
380
381
382
	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;

	if (env->params->little_endian) {
		low  = adr;
		high = new_r_Add(irg, block, adr,
			new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes),
			get_irn_mode(adr));
Michael Beck's avatar
BugFix:    
Michael Beck committed
383
	} else {
384
385
386
387
		low  = new_r_Add(irg, block, adr,
			new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes),
			get_irn_mode(adr));
		high = adr;
Michael Beck's avatar
BugFix:    
Michael Beck committed
388
	}  /* if */
389
390
391

	/* create two loads */
	dbg  = get_irn_dbg_info(node);
392
	low  = new_rd_Load(dbg, irg, block, mem,  low,  low_mode);
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
	proj = new_r_Proj(irg, block, low, mode_M, pn_Load_M);
	high = new_rd_Load(dbg, irg, block, proj, high, mode);

	set_Load_volatility(low,  get_Load_volatility(node));
	set_Load_volatility(high, get_Load_volatility(node));

	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);
418
419
			env->entries[idx]->low_word  = new_r_Proj(irg, block, low,  low_mode, pn_Load_res);
			env->entries[idx]->high_word = new_r_Proj(irg, block, high, mode,     pn_Load_res);
420
421
422
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
423
		}  /* switch */
424
425
426
		/* 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
427
	}  /* for */
428
}  /* lower_Load */
429
430
431
432
433
434
435
436
437
438
439

/**
 * Translate a Store: create two.
 */
static void lower_Store(ir_node *node, ir_mode *mode, lower_env_t *env) {
	ir_graph *irg;
	ir_node  *block, *adr, *mem;
	ir_node  *low, *high, *irn, *proj;
	dbg_info *dbg;
	int      idx;
	node_entry_t *entry;
Matthias Braun's avatar
Matthias Braun committed
440
441
	(void) node;
	(void) mode;
442
443
444
445
446
447
448
449
450

	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
451
	}  /* if */
452
453
454
455
456
457
458
459
460
461
462

	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;
		high = new_r_Add(irg, block, adr,
			new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes),
			get_irn_mode(adr));
Michael Beck's avatar
BugFix:    
Michael Beck committed
463
	} else {
464
465
466
467
		low  = new_r_Add(irg, block, adr,
			new_r_Const(irg, block, get_tarval_mode(env->tv_mode_bytes), env->tv_mode_bytes),
			get_irn_mode(adr));
		high = adr;
Michael Beck's avatar
BugFix:    
Michael Beck committed
468
	}  /* if */
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497

	/* create two Stores */
	dbg = get_irn_dbg_info(node);
	low  = new_rd_Store(dbg, irg, block, mem, low,  entry->low_word);
	proj = new_r_Proj(irg, block, low, mode_M, pn_Store_M);
	high = new_rd_Store(dbg, irg, block, proj, high, entry->high_word);

	set_Store_volatility(low,  get_Store_volatility(node));
	set_Store_volatility(high, get_Store_volatility(node));

	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
498
		}  /* switch */
499
500
501
		/* 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
502
	}  /* for */
503
}  /* lower_Store */
504
505
506

/**
 * Return a node containing the address of the intrinsic emulation function.
Michael Beck's avatar
Michael Beck committed
507
508
509
510
511
512
513
 *
 * @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 block   where the new mode is created
 * @param env     the lower environment
514
 */
Michael Beck's avatar
Michael Beck committed
515
516
517
static ir_node *get_intrinsic_address(ir_type *method, ir_op *op,
                                      ir_mode *imode, ir_mode *omode,
                                      ir_node *block, lower_env_t *env) {
518
	symconst_symbol sym;
519
	ir_entity *ent;
520
521
	op_mode_entry_t key, *entry;

Michael Beck's avatar
Michael Beck committed
522
523
524
525
	key.op    = op;
	key.imode = imode;
	key.omode = omode;
	key.ent   = NULL;
526

Michael Beck's avatar
Michael Beck committed
527
528
	entry = set_insert(intrinsic_fkt, &key, sizeof(key),
				HASH_PTR(op) ^ HASH_PTR(imode) ^ (HASH_PTR(omode) << 8));
529
530
	if (! entry->ent) {
		/* create a new one */
Michael Beck's avatar
Michael Beck committed
531
		ent = env->params->create_intrinsic(method, op, imode, omode, env->params->ctx);
532
533
534

		assert(ent && "Intrinsic creator must return an entity");
		entry->ent = ent;
Michael Beck's avatar
BugFix:    
Michael Beck committed
535
	} else {
536
		ent = entry->ent;
Michael Beck's avatar
BugFix:    
Michael Beck committed
537
	}  /* if */
538
	sym.entity_p = ent;
539
	return new_r_SymConst(current_ir_graph, block, mode_P_code, sym, symconst_addr_ent);
540
}  /* get_intrinsic_address */
541
542
543
544
545
546
547
548
549

/**
 * Translate a Div.
 *
 * Create an intrinsic Call.
 */
static void lower_Div(ir_node *node, ir_mode *mode, lower_env_t *env) {
	ir_node  *block, *irn, *call, *proj;
	ir_node  *in[4];
Michael Beck's avatar
Michael Beck committed
550
	ir_mode  *opmode;
551
552
553
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
554
	ir_graph *irg;
555
556
557
558
559
560
561
562
563
564
	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
565
	}  /* if */
566
567
568
569
570
571
572
573
574
575
576
577

	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
578
	}  /* if */
579
580
581
582

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

583
	dbg   = get_irn_dbg_info(node);
584
	block = get_nodes_block(node);
585
	irg   = current_ir_graph;
586
587

	mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
Michael Beck's avatar
Michael Beck committed
588
589
	opmode = get_irn_op_mode(node);
	irn = get_intrinsic_address(mtp, get_irn_op(node), opmode, opmode, block, env);
590
	call = new_rd_Call(dbg, irg, block, get_Div_mem(node),
591
592
		irn, 4, in, mtp);
	set_irn_pinned(call, get_irn_pinned(node));
593
	irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609

	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);
			set_Proj_proj(proj, pn_Call_M_except);
			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);
610
611
			env->entries[idx]->low_word  = new_r_Proj(current_ir_graph, block, irn, env->params->low_unsigned, 0);
			env->entries[idx]->high_word = new_r_Proj(current_ir_graph, block, irn, mode,                      1);
612
613
614
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
615
		}  /* switch */
616
617
618
		/* 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
619
	}  /* for */
620
}  /* lower_Div */
621
622
623
624
625
626
627
628
629

/**
 * Translate a Mod.
 *
 * Create an intrinsic Call.
 */
static void lower_Mod(ir_node *node, ir_mode *mode, lower_env_t *env) {
	ir_node  *block, *proj, *irn, *call;
	ir_node  *in[4];
Michael Beck's avatar
Michael Beck committed
630
	ir_mode  *opmode;
631
632
633
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
634
	ir_graph *irg;
635
636
637
638
639
640
641
642
643
644
	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
645
	}  /* if */
646
647
648
649
650
651
652
653
654
655
656
657

	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
658
	}  /* if */
659
660
661
662

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

663
	dbg   = get_irn_dbg_info(node);
664
	block = get_nodes_block(node);
665
	irg   = current_ir_graph;
666
667

	mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
Michael Beck's avatar
Michael Beck committed
668
669
	opmode = get_irn_op_mode(node);
	irn = get_intrinsic_address(mtp, get_irn_op(node), opmode, opmode, block, env);
670
	call = new_rd_Call(dbg, irg, block, get_Mod_mem(node),
671
672
		irn, 4, in, mtp);
	set_irn_pinned(call, get_irn_pinned(node));
673
	irn = new_r_Proj(irg, block, call, mode_T, pn_Call_T_result);
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689

	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);
			set_Proj_proj(proj, pn_Call_M_except);
			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);
690
691
			env->entries[idx]->low_word  = new_r_Proj(irg, block, irn, env->params->low_unsigned, 0);
			env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode,                      1);
692
693
694
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
695
		}  /* switch */
696
697
698
		/* 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
699
	}  /* for */
700
}  /* lower_Mod */
701
702
703
704
705
706
707

/**
 * Translate a DivMod.
 *
 * Create two intrinsic Calls.
 */
static void lower_DivMod(ir_node *node, ir_mode *mode, lower_env_t *env) {
Matthias Braun's avatar
Matthias Braun committed
708
709
710
	ir_node  *block, *proj, *irn, *mem, *callDiv, *callMod;
	ir_node  *resDiv = NULL;
	ir_node  *resMod = NULL;
711
	ir_node  *in[4];
Michael Beck's avatar
Michael Beck committed
712
	ir_mode  *opmode;
713
714
715
716
717
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
	node_entry_t *entry;
	unsigned flags = 0;
718
	ir_graph *irg;
719
720
721
722
723
724
725

	/* 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
726
727
		}  /* switch */
	}  /* for */
728
729
730
731
732
733
734
735
736

	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
737
	}  /* if */
738
739
740
741
742
743
744
745
746
747
748
749

	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
750
	}  /* if */
751
752
753
754

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

755
	dbg   = get_irn_dbg_info(node);
756
	block = get_nodes_block(node);
757
	irg   = current_ir_graph;
758
759
760
761
762
763

	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
764
765
		opmode = get_irn_op_mode(node);
		irn = get_intrinsic_address(mtp, op_Div, opmode, opmode, block, env);
766
		callDiv = new_rd_Call(dbg, irg, block, mem,
767
768
			irn, 4, in, mtp);
		set_irn_pinned(callDiv, get_irn_pinned(node));
769
		resDiv = new_r_Proj(irg, block, callDiv, mode_T, pn_Call_T_result);
Michael Beck's avatar
BugFix:    
Michael Beck committed
770
	}  /* if */
771
772
	if (flags & 2) {
		if (flags & 1)
773
			mem = new_r_Proj(irg, block, callDiv, mode_M, pn_Call_M);
Michael Beck's avatar
Michael Beck committed
774
775
		opmode = get_irn_op_mode(node);
		irn = get_intrinsic_address(mtp, op_Mod, opmode, opmode, block, env);
776
		callMod = new_rd_Call(dbg, irg, block, mem,
777
778
			irn, 4, in, mtp);
		set_irn_pinned(callMod, get_irn_pinned(node));
779
		resMod = new_r_Proj(irg, block, callMod, mode_T, pn_Call_T_result);
Michael Beck's avatar
BugFix:    
Michael Beck committed
780
	}  /* if */
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796

	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));
			set_Proj_proj(proj, pn_Call_M_except);
			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);
797
798
			env->entries[idx]->low_word  = new_r_Proj(irg, block, resDiv, env->params->low_unsigned, 0);
			env->entries[idx]->high_word = new_r_Proj(irg, block, resDiv, mode,                      1);
799
800
801
			break;
		case pn_DivMod_res_mod:   /* Result of Mod. */
			idx = get_irn_idx(proj);
802
803
			env->entries[idx]->low_word  = new_r_Proj(irg, block, resMod, env->params->low_unsigned, 0);
			env->entries[idx]->high_word = new_r_Proj(irg, block, resMod, mode,                      1);
804
805
806
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
807
		}  /* switch */
808
809
810
		/* 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
811
	}  /* for */
812
}  /* lower_DivMod */
813
814
815
816
817
818
819
820
821
822
823
824

/**
 * Translate a Binop.
 *
 * Create an intrinsic Call.
 */
static void lower_Binop(ir_node *node, ir_mode *mode, lower_env_t *env) {
	ir_node  *block, *irn;
	ir_node  *in[4];
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
825
	ir_graph *irg;
826
827
828
829
830
831
832
833
834
835
	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
836
	}  /* if */
837
838
839
840
841
842
843
844
845
846
847
848

	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
849
	}  /* if */
850
851
852
853

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

854
	dbg   = get_irn_dbg_info(node);
855
	block = get_nodes_block(node);
856
	irg   = current_ir_graph;
857
858

	mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
Michael Beck's avatar
Michael Beck committed
859
	irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, block, env);
860
	irn = new_rd_Call(dbg, irg, block, get_irg_no_mem(current_ir_graph),
861
862
		irn, 4, in, mtp);
	set_irn_pinned(irn, get_irn_pinned(node));
863
	irn = new_r_Proj(irg, block, irn, mode_T, pn_Call_T_result);
864
865
866

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
867
868
	env->entries[idx]->low_word  = new_r_Proj(irg, block, irn, env->params->low_unsigned, 0);
	env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode,                      1);
869
}  /* lower_Binop */
870

Christian Würdig's avatar
Christian Würdig committed
871
872
873
874
875
876
877
878
879
880
881
/**
 * Translate a Shiftop.
 *
 * Create an intrinsic Call.
 */
static void lower_Shiftop(ir_node *node, ir_mode *mode, lower_env_t *env) {
	ir_node  *block, *irn;
	ir_node  *in[3];
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
882
	ir_graph *irg;
Christian Würdig's avatar
Christian Würdig committed
883
884
885
886
887
888
889
890
891
892
	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
893
	}  /* if */
Christian Würdig's avatar
Christian Würdig committed
894
895
896
897
898
899
900
901
902

	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);

	dbg   = get_irn_dbg_info(node);
	block = get_nodes_block(node);
903
	irg  = current_ir_graph;
Christian Würdig's avatar
Christian Würdig committed
904
905
906

	mtp = mode_is_signed(mode) ? shiftop_tp_s : shiftop_tp_u;
	irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, block, env);
907
	irn = new_rd_Call(dbg, irg, block, get_irg_no_mem(current_ir_graph),
Christian Würdig's avatar
Christian Würdig committed
908
909
		irn, 3, in, mtp);
	set_irn_pinned(irn, get_irn_pinned(node));
910
	irn = new_r_Proj(irg, block, irn, mode_T, pn_Call_T_result);
Christian Würdig's avatar
Christian Würdig committed
911
912
913

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
914
915
	env->entries[idx]->low_word  = new_r_Proj(irg, block, irn, env->params->low_unsigned, 0);
	env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode,                      1);
916
}  /* lower_Shiftop */
Christian Würdig's avatar
Christian Würdig committed
917

Michael Beck's avatar
Michael Beck committed
918
919
920
921
/**
 * Translate a Shr and handle special cases.
 */
static void lower_Shr(ir_node *node, ir_mode *mode, lower_env_t *env) {
922
923
	ir_node  *right = get_Shr_right(node);
	ir_graph *irg = current_ir_graph;
Michael Beck's avatar
Michael Beck committed
924
925
926
927
928

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

		if (tarval_is_long(tv) &&
929
		    get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
Michael Beck's avatar
Michael Beck committed
930
931
			ir_node *block = get_nodes_block(node);
			ir_node *left = get_Shr_left(node);
932
933
			ir_node *c;
			long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode);
Michael Beck's avatar
Michael Beck committed
934
935
936
937
938
			int idx = get_irn_idx(left);

			left = env->entries[idx]->high_word;
			idx = get_irn_idx(node);

939
			if (shf_cnt > 0) {
940
941
				c = new_r_Const_long(irg, block, mode_Iu, shf_cnt);
				env->entries[idx]->low_word = new_r_Shr(irg, block, left, c, mode);
Michael Beck's avatar
BugFix:    
Michael Beck committed
942
			} else {
943
				env->entries[idx]->low_word = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
944
			}  /* if */
945
			env->entries[idx]->high_word = new_r_Const(irg, block, mode, get_mode_null(mode));
Michael Beck's avatar
Michael Beck committed
946
947

			return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
948
949
		}  /* if */
	}  /* if */
Michael Beck's avatar
Michael Beck committed
950
	lower_Shiftop(node, mode, env);
951
}  /* lower_Shr */
Michael Beck's avatar
Michael Beck committed
952
953
954
955
956

/**
 * Translate a Shl and handle special cases.
 */
static void lower_Shl(ir_node *node, ir_mode *mode, lower_env_t *env) {
957
958
	ir_node  *right = get_Shl_right(node);
	ir_graph *irg = current_ir_graph;
Michael Beck's avatar
Michael Beck committed
959
960
961
962
963

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

		if (tarval_is_long(tv) &&
964
		    get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
965
			ir_mode *mode_l;
Michael Beck's avatar
Michael Beck committed
966
967
			ir_node *block = get_nodes_block(node);
			ir_node *left = get_Shl_left(node);
968
969
			ir_node *c;
			long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode);
Michael Beck's avatar
Michael Beck committed
970
971
			int idx = get_irn_idx(left);

972
			left = new_r_Conv(irg, block, env->entries[idx]->low_word, mode);
Michael Beck's avatar
Michael Beck committed
973
974
			idx = get_irn_idx(node);

975
			if (shf_cnt > 0) {
976
977
				c = new_r_Const_long(irg, block, mode_Iu, shf_cnt);
				env->entries[idx]->high_word = new_r_Shl(irg, block, left, c, mode);
Michael Beck's avatar
BugFix:    
Michael Beck committed
978
			} else {
979
				env->entries[idx]->high_word = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
980
			}  /* if */
981
982
			mode_l = env->params->low_unsigned;
			env->entries[idx]->low_word  = new_r_Const(irg, block, mode_l, get_mode_null(mode_l));
Michael Beck's avatar
Michael Beck committed
983
984

			return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
985
986
		}  /* if */
	}  /* if */
Michael Beck's avatar
Michael Beck committed
987
	lower_Shiftop(node, mode, env);
988
}  /* lower_Shl */
Michael Beck's avatar
Michael Beck committed
989
990
991
992
993

/**
 * Translate a Shrs and handle special cases.
 */
static void lower_Shrs(ir_node *node, ir_mode *mode, lower_env_t *env) {
994
995
	ir_node  *right = get_Shrs_right(node);
	ir_graph *irg = current_ir_graph;
Michael Beck's avatar
Michael Beck committed
996
997
998
999
1000

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

		if (tarval_is_long(tv) &&
1001
		    get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
Michael Beck's avatar
Michael Beck committed
1002
1003
			ir_node *block = get_nodes_block(node);
			ir_node *left = get_Shrs_left(node);
1004
			long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode);
Michael Beck's avatar
Michael Beck committed
1005
1006
1007
1008
1009
1010
			ir_node *c;
			int idx = get_irn_idx(left);

			left = env->entries[idx]->high_word;
			idx = get_irn_idx(node);

1011
			if (shf_cnt > 0) {
1012
				ir_node *tmp;
1013
				c = new_r_Const_long(irg, block, mode_Iu, shf_cnt);
1014
1015
1016
				tmp = new_r_Shrs(irg, block, left, c, mode);
				/* low word is expected to have mode_Iu */
				env->entries[idx]->low_word = new_r_Conv(irg, block, tmp, mode_Iu);
Michael Beck's avatar
BugFix:    
Michael Beck committed
1017
			} else {
1018
				env->entries[idx]->low_word = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
1019
			}  /* if */
1020
1021
			c = new_r_Const_long(irg, block, mode_Iu, get_mode_size_bits(mode) - 1);
			env->entries[idx]->high_word = new_r_Shrs(irg, block, left, c, mode);
Michael Beck's avatar
Michael Beck committed
1022
1023

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

/**
Michael Beck's avatar
Michael Beck committed
1030
 * Rebuild Rotl nodes into Or(Shl, Shr) and prepare all nodes.
Michael Beck's avatar
Michael Beck committed
1031
 */
Michael Beck's avatar
Michael Beck committed
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
static void prepare_links_and_handle_rotl(ir_node *node, void *env) {
	lower_env_t *lenv = env;

	if (is_Rotl(node)) {
		ir_mode *mode = get_irn_op_mode(node);
			if (mode == lenv->params->high_signed ||
			    mode == lenv->params->high_unsigned) {
				ir_node  *right = get_Rotl_right(node);
				ir_node  *left, *shl, *shr, *or, *block, *sub, *c;
				ir_mode  *omode, *rmode;
				ir_graph *irg;
				dbg_info *dbg;
				optimization_state_t state;

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

					if (tarval_is_long(tv) &&
					    get_tarval_long(tv) == (long)get_mode_size_bits(mode)) {
						/* will be optimized in lower_Rotl() */
						return;
					}
				}

				/* replace the Rotl(x,y) by an Or(Shl(x,y), Shr(x,64-y)) and lower those */
				dbg   = get_irn_dbg_info(node);
				omode = get_irn_mode(node);
				left  = get_Rotl_left(node);
				irg   = current_ir_graph;
				block = get_nodes_block(node);
				shl   = new_rd_Shl(dbg, irg, block, left, right, omode);
				rmode = get_irn_mode(right);
				c     = new_Const_long(rmode, get_mode_size_bits(omode));
				sub   = new_rd_Sub(dbg, irg, block, c, right, rmode);
				shr   = new_rd_Shr(dbg, irg, block, left, sub, omode);

				/* optimization must be switched off here, or we will get the Rotl back */
				save_optimization_state(&state);
				set_opt_algebraic_simplification(0);
				or = new_rd_Or(dbg, irg, block, shl, shr, omode);
				restore_optimization_state(&state);

				exchange(node, or);

				/* do lowering on the new nodes */
				prepare_links(shl, env);
				prepare_links(c, env);
				prepare_links(sub, env);
				prepare_links(shr, env);
				prepare_links(or, env);
			}
	} else {
		prepare_links(node, env);
	}
}
Michael Beck's avatar
Michael Beck committed
1087

Michael Beck's avatar
Michael Beck committed
1088
1089
1090
1091
1092
1093
1094
1095
/**
 * Translate a special case Rotl(x, sizeof(w)).
 */
static void lower_Rotl(ir_node *node, ir_mode *mode, lower_env_t *env) {
	ir_node *right = get_Rotl_right(node);
	ir_node *left = get_Rotl_left(node);
	ir_node *h, *l;
	int idx = get_irn_idx(left);
Michael Beck's avatar
Michael Beck committed
1096

Michael Beck's avatar
Michael Beck committed
1097
1098
1099
	assert(get_mode_arithmetic(mode) == irma_twos_complement &&
	       is_Const(right) && tarval_is_long(get_Const_tarval(right)) &&
	       get_tarval_long(get_Const_tarval(right)) == (long)get_mode_size_bits(mode));
Michael Beck's avatar
Michael Beck committed
1100

Michael Beck's avatar
Michael Beck committed
1101
1102
1103
	l = env->entries[idx]->low_word;
	h = env->entries[idx]->high_word;
	idx = get_irn_idx(node);
Michael Beck's avatar
Michael Beck committed
1104

Michael Beck's avatar
Michael Beck committed
1105
1106
1107
	env->entries[idx]->low_word  = h;
	env->entries[idx]->high_word = l;
}  /* lower_Rotl */
1108

1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
/**
 * Translate an Unop.
 *
 * Create an intrinsic Call.
 */
static void lower_Unop(ir_node *node, ir_mode *mode, lower_env_t *env) {
	ir_node  *block, *irn;
	ir_node  *in[2];
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
1120
	ir_graph *irg;
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
	node_entry_t *entry;

	irn   = get_unop_op(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
1131
	}  /* if */
1132
1133
1134
1135

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

1136
	dbg   = get_irn_dbg_info(node);
1137
	block = get_nodes_block(node);
1138
	irg   = current_ir_graph;
1139
1140

	mtp = mode_is_signed(mode) ? unop_tp_s : unop_tp_u;
Michael Beck's avatar
Michael Beck committed
1141
	irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, block, env);
1142
	irn = new_rd_Call(dbg, irg, block, get_irg_no_mem(current_ir_graph),
1143
1144
		irn, 2, in, mtp);
	set_irn_pinned(irn, get_irn_pinned(node));
1145
	irn = new_r_Proj(irg, block, irn, mode_T, pn_Call_T_result);
1146
1147
1148

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
1149
1150
	env->entries[idx]->low_word  = new_r_Proj(irg, block, irn, env->params->low_unsigned, 0);
	env->entries[idx]->high_word = new_r_Proj(irg, block, irn, mode,                      1);
1151
}  /* lower_Unop */
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163

/**
 * Translate a logical Binop.
 *
 * Create two logical Binops.
 */
static void lower_Binop_logical(ir_node *node, ir_mode *mode, lower_env_t *env,
								ir_node *(*constr_rd)(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) ) {
	ir_node  *block, *irn;
	ir_node  *lop_l, *lop_h, *rop_l, *rop_h;
	dbg_info *dbg;
	int      idx;
1164
	ir_graph *irg;
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
	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
1175
	}  /* if */
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187

	lop_l = entry->low_word;
	lop_h = 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
1188
	}  /* if */
1189
1190
1191
1192
1193
1194
1195
1196
1197

	rop_l = entry->low_word;
	rop_h = entry->high_word;

	dbg = get_irn_dbg_info(node);
	block = get_nodes_block(node);

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
1198
	irg = current_ir_graph;
1199
	env->entries[idx]->low_word  = constr_rd(dbg, irg, block, lop_l, rop_l, env->params->low_unsigned);
1200
1201
	env->entries[idx]->high_word = constr_rd(dbg, irg, block, lop_h, rop_h, mode);
}  /* lower_Binop_logical */
1202

1203
/** create a logical operation transformation */
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
#define lower_logical(op)                                                \
static void lower_##op(ir_node *node, ir_mode *mode, lower_env_t *env) { \
	lower_Binop_logical(node, mode, env, new_rd_##op);                   \
}

lower_logical(And)
lower_logical(Or)
lower_logical(Eor)

/**
 * Translate a Not.
 *
 * Create two logical Nots.
 */
static void lower_Not(ir_node *node, ir_mode *mode, lower_env_t *env) {
	ir_node  *block, *irn;
	ir_node  *op_l, *op_h;
	dbg_info *dbg;
	int      idx;
1223
	ir_graph *irg;
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
	node_entry_t *entry;

	irn   = get_Not_op(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
1234
	}  /* if */
1235
1236
1237
1238

	op_l = entry->low_word;
	op_h = entry->high_word;

1239
	dbg   = get_irn_dbg_info(node);
1240
	block = get_nodes_block(node);
1241
	irg   = current_ir_graph;
1242
1243
1244

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
1245
	env->entries[idx]->low_word  = new_rd_Not(dbg, current_ir_graph, block, op_l, env->params->low_unsigned);
1246
	env->entries[idx]->high_word = new_rd_Not(dbg, current_ir_graph, block, op_h, mode);
1247
}  /* lower_Not */