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

Michael Beck's avatar
Michael Beck committed
128
129
130
/**
 * Create a method type for a Conv emulation from imode to omode.
 */
131
132
static ir_type *get_conv_type(ir_mode *imode, ir_mode *omode, lower_env_t *env)
{
Michael Beck's avatar
Michael Beck committed
133
134
135
136
137
138
139
140
141
142
143
	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;

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

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

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

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

183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/**
 * 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);

202
	for (phi = get_Block_phis(block); phi != NULL; phi = get_Phi_next(phi)) {
203
204
205
206
		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
207
	}  /* for */
208
}  /* add_block_cf_input_nr */
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223

/**
 * 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
224
225
		}  /* if */
	}  /* for */
226
227
	assert(i < arity);
	add_block_cf_input_nr(block, nr, cf);
228
}  /* add_block_cf_input */
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249

/**
 * 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
250
	}  /* switch */
251
}  /* get_irn_op_mode */
252
253

/**
254
 * Walker, prepare the node links.
255
256
257
258
259
260
 */
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
261
	int          i, idx;
262

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

Michael Beck's avatar
Michael Beck committed
268
269
270
271
272
273
274
275
276
277
278
		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;
279
		lenv->flags |= MUST_BE_LOWERED;
280
	} else if (is_Conv(node)) {
281
282
283
284
		/* Conv nodes have two modes */
		ir_node *pred = get_Conv_op(node);
		mode = get_irn_mode(pred);

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

	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
300
	} else if (is_Phi(node)) {
301
302
		/* link all Phi nodes to its block */
		ir_node *block = get_nodes_block(node);
303
		add_Block_phi(block, node);
Michael Beck's avatar
BugFix:    
Michael Beck committed
304
	} else if (is_Block(node)) {
305
306
307
308
309
310
		/* 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
311
312
		}  /* for */
	}  /* if */
313
}  /* prepare_links */
314
315
316
317

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

	tv   = get_Const_tarval(node);

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

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

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

/**
 * Translate a Load: create two.
 */
344
345
static void lower_Load(ir_node *node, ir_mode *mode, lower_env_t *env)
{
346
	ir_mode    *low_mode = env->low_unsigned;
347
348
349
350
351
352
353
	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;
354
	ir_cons_flags volatility = get_Load_volatility(node) == volatility_is_volatile
355
	                         ? cons_volatile : 0;
356
357
358

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

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

	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);
390
391
			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);
392
393
394
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
395
		}  /* switch */
396
397
398
		/* 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
399
	}  /* for */
400
}  /* lower_Load */
401
402
403
404

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

	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
425
	}  /* if */
426
427
428
429
430
431
432
433

	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;
434
		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
435
	} else {
436
		low  = new_r_Add(block, adr, new_r_Const(irg, env->tv_mode_bytes), get_irn_mode(adr));
437
		high = adr;
Michael Beck's avatar
BugFix:    
Michael Beck committed
438
	}  /* if */
439
440
441

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

	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
465
		}  /* switch */
466
467
468
		/* 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
469
	}  /* for */
470
}  /* lower_Store */
471
472
473

/**
 * Return a node containing the address of the intrinsic emulation function.
Michael Beck's avatar
Michael Beck committed
474
475
476
477
478
479
 *
 * @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
480
 */
Michael Beck's avatar
Michael Beck committed
481
482
static ir_node *get_intrinsic_address(ir_type *method, ir_op *op,
                                      ir_mode *imode, ir_mode *omode,
483
484
                                      lower_env_t *env)
{
485
	symconst_symbol sym;
486
	ir_entity *ent;
487
488
	op_mode_entry_t key, *entry;

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

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

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

/**
 * Translate a Div.
 *
 * Create an intrinsic Call.
 */
514
515
static void lower_Div(ir_node *node, ir_mode *mode, lower_env_t *env)
{
516
517
	ir_node  *block, *irn, *call, *proj;
	ir_node  *in[4];
Michael Beck's avatar
Michael Beck committed
518
	ir_mode  *opmode;
519
520
521
522
523
524
525
526
527
528
529
530
531
	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
532
	}  /* if */
533
534
535
536
537
538
539
540
541
542
543
544

	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
545
	}  /* if */
546
547
548
549

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

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

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

	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);
565
			set_Proj_proj(proj, pn_Call_M);
566
567
568
569
570
571
572
573
574
			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);
575
			env->entries[idx]->low_word  = new_r_Proj(irn, env->low_unsigned, 0);
576
			env->entries[idx]->high_word = new_r_Proj(irn, mode,                      1);
577
578
579
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
580
		}  /* switch */
581
582
583
		/* 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
584
	}  /* for */
585
}  /* lower_Div */
586
587
588
589
590
591

/**
 * Translate a Mod.
 *
 * Create an intrinsic Call.
 */
592
593
static void lower_Mod(ir_node *node, ir_mode *mode, lower_env_t *env)
{
594
595
	ir_node  *block, *proj, *irn, *call;
	ir_node  *in[4];
Michael Beck's avatar
Michael Beck committed
596
	ir_mode  *opmode;
597
598
599
600
601
602
603
604
605
606
607
608
609
	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
610
	}  /* if */
611
612
613
614
615
616
617
618
619
620
621
622

	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
623
	}  /* if */
624
625
626
627

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

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

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

	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);
643
			set_Proj_proj(proj, pn_Call_M);
644
645
646
647
648
649
650
651
652
			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);
653
			env->entries[idx]->low_word  = new_r_Proj(irn, env->low_unsigned, 0);
654
			env->entries[idx]->high_word = new_r_Proj(irn, mode,                      1);
655
656
657
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
658
		}  /* switch */
659
660
661
		/* 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
662
	}  /* for */
663
}  /* lower_Mod */
664
665
666
667
668
669

/**
 * Translate a DivMod.
 *
 * Create two intrinsic Calls.
 */
670
671
static void lower_DivMod(ir_node *node, ir_mode *mode, lower_env_t *env)
{
Matthias Braun's avatar
Matthias Braun committed
672
673
674
	ir_node  *block, *proj, *irn, *mem, *callDiv, *callMod;
	ir_node  *resDiv = NULL;
	ir_node  *resMod = NULL;
675
	ir_node  *in[4];
Michael Beck's avatar
Michael Beck committed
676
	ir_mode  *opmode;
677
678
679
680
681
682
683
684
685
686
687
688
	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
689
690
		}  /* switch */
	}  /* for */
691
692
693
694
695
696
697
698
699

	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
700
	}  /* if */
701
702
703
704
705
706
707
708
709
710
711
712

	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
713
	}  /* if */
714
715
716
717

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

718
	dbg   = get_irn_dbg_info(node);
719
720
721
722
723
724
725
	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
726
		opmode = get_irn_op_mode(node);
Matthias Braun's avatar
Matthias Braun committed
727
		irn = get_intrinsic_address(mtp, op_Div, opmode, opmode, env);
728
		callDiv = new_rd_Call(dbg, block, mem, irn, 4, in, mtp);
729
		set_irn_pinned(callDiv, get_irn_pinned(node));
730
		resDiv = new_r_Proj(callDiv, mode_T, pn_Call_T_result);
Michael Beck's avatar
BugFix:    
Michael Beck committed
731
	}  /* if */
732
733
	if (flags & 2) {
		if (flags & 1)
734
			mem = new_r_Proj(callDiv, mode_M, pn_Call_M);
Michael Beck's avatar
Michael Beck committed
735
		opmode = get_irn_op_mode(node);
Matthias Braun's avatar
Matthias Braun committed
736
		irn = get_intrinsic_address(mtp, op_Mod, opmode, opmode, env);
737
		callMod = new_rd_Call(dbg, block, mem, irn, 4, in, mtp);
738
		set_irn_pinned(callMod, get_irn_pinned(node));
739
		resMod = new_r_Proj(callMod, mode_T, pn_Call_T_result);
Michael Beck's avatar
BugFix:    
Michael Beck committed
740
	}  /* if */
741
742
743
744
745
746

	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));
747
			set_Proj_proj(proj, pn_Call_M);
748
749
750
751
752
753
754
755
756
			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);
757
			env->entries[idx]->low_word  = new_r_Proj(resDiv, env->low_unsigned, 0);
758
			env->entries[idx]->high_word = new_r_Proj(resDiv, mode,                      1);
759
760
761
			break;
		case pn_DivMod_res_mod:   /* Result of Mod. */
			idx = get_irn_idx(proj);
762
			env->entries[idx]->low_word  = new_r_Proj(resMod, env->low_unsigned, 0);
763
			env->entries[idx]->high_word = new_r_Proj(resMod, mode,                      1);
764
765
766
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
767
		}  /* switch */
768
769
770
		/* 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
771
	}  /* for */
772
}  /* lower_DivMod */
773
774
775
776
777
778

/**
 * Translate a Binop.
 *
 * Create an intrinsic Call.
 */
779
780
static void lower_Binop(ir_node *node, ir_mode *mode, lower_env_t *env)
{
781
782
783
784
785
	ir_node  *block, *irn;
	ir_node  *in[4];
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
786
	ir_graph *irg;
787
788
789
790
791
792
793
794
795
796
	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
797
	}  /* if */
798
799
800
801
802
803
804
805
806
807
808
809

	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
810
	}  /* if */
811
812
813
814

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

815
	dbg   = get_irn_dbg_info(node);
816
	block = get_nodes_block(node);
817
	irg   = current_ir_graph;
818
819

	mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
Matthias Braun's avatar
Matthias Braun committed
820
	irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, env);
821
	irn = new_rd_Call(dbg, block, get_irg_no_mem(current_ir_graph),
822
823
		irn, 4, in, mtp);
	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  = current_ir_graph;
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(current_ir_graph),
Christian Würdig's avatar
Christian Würdig committed
872
873
		irn, 3, in, mtp);
	set_irn_pinned(irn, get_irn_pinned(node));
874
	irn = new_r_Proj(irn, mode_T, pn_Call_T_result);
Christian Würdig's avatar
Christian Würdig committed
875
876
877

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

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

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

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

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

Michael Beck's avatar
Michael Beck committed
909
			idx = get_irn_idx(node);
910
911
912
			/* 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
913

914
			if (shf_cnt > 0) {
915
916
917
				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
918
			} else {
919
				env->entries[idx]->low_word = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
920
			}  /* if */
921
			env->entries[idx]->high_word = new_r_Const(irg, get_mode_null(mode));
Michael Beck's avatar
Michael Beck committed
922
923

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

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

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

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

949
950
951
952
953
954
955
956
			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
957
958
			idx = get_irn_idx(node);

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

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

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

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

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

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

1003
1004
1005
1006
1007
			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);

1008
			if (shf_cnt > 0) {
1009
1010
				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
1011
			} else {
1012
				low = left_unsigned;
Michael Beck's avatar
BugFix:    
Michael Beck committed
1013
			}  /* if */
1014
1015
			/* low word is expected to have low_unsigned */
			env->entries[idx]->low_word = new_r_Conv(block, low, low_unsigned);
1016

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

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

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

	if (is_Rotl(node)) {
		ir_mode *mode = get_irn_op_mode(node);
1036
1037
			if (mode == lenv->high_signed ||
			    mode == lenv->high_unsigned) {
Michael Beck's avatar
Michael Beck committed
1038
1039
1040
				ir_node  *right = get_Rotl_right(node);
				ir_node  *left, *shl, *shr, *or, *block, *sub, *c;
				ir_mode  *omode, *rmode;
1041
				ir_graph *irg;
Michael Beck's avatar
Michael Beck committed
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
				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 */
1056
				irg   = get_irn_irg(node);
Michael Beck's avatar
Michael Beck committed
1057