lower_dw.c 72 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
76
 */
typedef struct _op_mode_entry {
	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
85
86
87
88
89
90
/**
 * 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;

91
92
93
94
95
/**
 * Every double word node will be replaced,
 * we need some store to hold the replacement:
 */
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
108
109
110
};

/**
 * The lower environment.
 */
typedef struct _lower_env_t {
	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
	ident    *first_id;           /**< .l for little and .h for big endian */
	ident    *next_id;            /**< .h for little and .l for big endian */
118
119
120
	const lwrdw_param_t *params;  /**< transformation parameter */
	unsigned flags;               /**< some flags */
	int      n_entries;           /**< number of entries */
121
	ir_type  *value_param_tp;     /**< the old value param type */
122
123
} lower_env_t;

Michael Beck's avatar
Michael Beck committed
124
125
126
/**
 * Create a method type for a Conv emulation from imode to omode.
 */
127
128
static ir_type *get_conv_type(ir_mode *imode, ir_mode *omode, lower_env_t *env)
{
Michael Beck's avatar
Michael Beck committed
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
	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 */
146
		mtd = new_type_method(n_param, n_res);
Michael Beck's avatar
Michael Beck committed
147
148
149
150

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

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

179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
/**
 * 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);

198
	for (phi = get_Block_phis(block); phi != NULL; phi = get_Phi_next(phi)) {
199
200
201
202
		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
203
	}  /* for */
204
}  /* add_block_cf_input_nr */
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 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
220
221
		}  /* if */
	}  /* for */
222
223
	assert(i < arity);
	add_block_cf_input_nr(block, nr, cf);
224
}  /* add_block_cf_input */
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245

/**
 * 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
246
	}  /* switch */
247
}  /* get_irn_op_mode */
248
249

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

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

Michael Beck's avatar
Michael Beck committed
264
265
266
267
268
269
270
271
272
273
274
		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;
275
		lenv->flags |= MUST_BE_LOWERED;
276
	} else if (is_Conv(node)) {
277
278
279
280
281
282
		/* 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
283
			/* must lower this node either but don't need a link */
284
			lenv->flags |= MUST_BE_LOWERED;
Michael Beck's avatar
BugFix:    
Michael Beck committed
285
		}  /* if */
286
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
287
	}  /* if */
288
289
290
291
292
293
294
295

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

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

	tv   = get_Const_tarval(node);

325
	tv_l = tarval_convert_to(tv, low_mode);
326
	low  = new_rd_Const(dbg, irg, tv_l);
327

Michael Beck's avatar
BugFix:    
Michael Beck committed
328
	tv_h = tarval_convert_to(tarval_shrs(tv, env->tv_mode_bits), mode);
329
	high = new_rd_Const(dbg, irg, tv_h);
330
331
332
333
334

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
	env->entries[idx]->low_word  = low;
	env->entries[idx]->high_word = high;
335
}  /* lower_Const */
336
337
338
339

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

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

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

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

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

	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
421
	}  /* if */
422
423
424
425
426
427
428
429

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

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

	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
461
		}  /* switch */
462
463
464
		/* 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
465
	}  /* for */
466
}  /* lower_Store */
467
468
469

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

Michael Beck's avatar
Michael Beck committed
485
486
487
488
	key.op    = op;
	key.imode = imode;
	key.omode = omode;
	key.ent   = NULL;
489

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

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

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

	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
541
	}  /* if */
542
543
544
545

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

546
	dbg   = get_irn_dbg_info(node);
547
548
549
	block = get_nodes_block(node);

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

	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);
561
			set_Proj_proj(proj, pn_Call_M);
562
563
564
565
566
567
568
569
570
			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);
571
572
			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);
573
574
575
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
576
		}  /* switch */
577
578
579
		/* 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
580
	}  /* for */
581
}  /* lower_Div */
582
583
584
585
586
587

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

	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
619
	}  /* if */
620
621
622
623

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

624
	dbg   = get_irn_dbg_info(node);
625
626
627
	block = get_nodes_block(node);

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

	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);
639
			set_Proj_proj(proj, pn_Call_M);
640
641
642
643
644
645
646
647
648
			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);
649
650
			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);
651
652
653
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
654
		}  /* switch */
655
656
657
		/* 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
658
	}  /* for */
659
}  /* lower_Mod */
660
661
662
663
664
665

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

	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
696
	}  /* if */
697
698
699
700
701
702
703
704
705
706
707
708

	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
709
	}  /* if */
710
711
712
713

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

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

	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));
743
			set_Proj_proj(proj, pn_Call_M);
744
745
746
747
748
749
750
751
752
			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);
753
754
			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);
755
756
757
			break;
		case pn_DivMod_res_mod:   /* Result of Mod. */
			idx = get_irn_idx(proj);
758
759
			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);
760
761
762
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
763
		}  /* switch */
764
765
766
		/* 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
767
	}  /* for */
768
}  /* lower_DivMod */
769
770
771
772
773
774

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

	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
806
	}  /* if */
807
808
809
810

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

811
	dbg   = get_irn_dbg_info(node);
812
	block = get_nodes_block(node);
813
	irg   = current_ir_graph;
814
815

	mtp = mode_is_signed(mode) ? binop_tp_s : binop_tp_u;
Matthias Braun's avatar
Matthias Braun committed
816
	irn = get_intrinsic_address(mtp, get_irn_op(node), mode, mode, env);
817
	irn = new_rd_Call(dbg, block, get_irg_no_mem(current_ir_graph),
818
819
		irn, 4, in, mtp);
	set_irn_pinned(irn, get_irn_pinned(node));
820
	irn = new_r_Proj(irn, mode_T, pn_Call_T_result);
821
822
823

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
824
825
	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);
826
}  /* lower_Binop */
827

Christian Würdig's avatar
Christian Würdig committed
828
829
830
831
832
/**
 * Translate a Shiftop.
 *
 * Create an intrinsic Call.
 */
833
834
static void lower_Shiftop(ir_node *node, ir_mode *mode, lower_env_t *env)
{
Christian Würdig's avatar
Christian Würdig committed
835
836
837
838
839
	ir_node  *block, *irn;
	ir_node  *in[3];
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
840
	ir_graph *irg;
Christian Würdig's avatar
Christian Würdig committed
841
842
843
844
845
846
847
848
849
850
	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
851
	}  /* if */
Christian Würdig's avatar
Christian Würdig committed
852
853
854
855
856
857

	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
858
859
	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
860
861
862

	dbg   = get_irn_dbg_info(node);
	block = get_nodes_block(node);
863
	irg  = current_ir_graph;
Christian Würdig's avatar
Christian Würdig committed
864
865

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

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
874
875
	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);
876
}  /* lower_Shiftop */
Christian Würdig's avatar
Christian Würdig committed
877

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

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

		if (tarval_is_long(tv) &&
890
		    get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
Michael Beck's avatar
Michael Beck committed
891
892
			ir_node *block = get_nodes_block(node);
			ir_node *left = get_Shr_left(node);
893
894
			ir_node *c;
			long shf_cnt = get_tarval_long(tv) - get_mode_size_bits(mode);
Michael Beck's avatar
Michael Beck committed
895
896
897
			int idx = get_irn_idx(left);

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

Michael Beck's avatar
Michael Beck committed
904
905
			idx = get_irn_idx(node);

906
			if (shf_cnt > 0) {
907
				c = new_r_Const_long(irg, env->params->low_unsigned, shf_cnt);
908
				env->entries[idx]->low_word = new_r_Shr(block, left, c, mode);
Michael Beck's avatar
BugFix:    
Michael Beck committed
909
			} else {
910
				env->entries[idx]->low_word = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
911
			}  /* if */
912
			env->entries[idx]->high_word = new_r_Const(irg, get_mode_null(mode));
Michael Beck's avatar
Michael Beck committed
913
914

			return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
915
916
		}  /* if */
	}  /* if */
Michael Beck's avatar
Michael Beck committed
917
	lower_Shiftop(node, mode, env);
918
}  /* lower_Shr */
Michael Beck's avatar
Michael Beck committed
919
920
921
922

/**
 * Translate a Shl and handle special cases.
 */
923
924
static void lower_Shl(ir_node *node, ir_mode *mode, lower_env_t *env)
{
925
926
	ir_node  *right = get_Shl_right(node);
	ir_graph *irg = current_ir_graph;
Michael Beck's avatar
Michael Beck committed
927
928
929
930
931

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

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

940
941
942
943
944
945
946
947
			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
948
949
			idx = get_irn_idx(node);

950
			mode_l = env->params->low_unsigned;
951
			if (shf_cnt > 0) {
952
				c = new_r_Const_long(irg, mode_l, shf_cnt);
953
				env->entries[idx]->high_word = new_r_Shl(block, left, c, mode);
Michael Beck's avatar
BugFix:    
Michael Beck committed
954
			} else {
955
				env->entries[idx]->high_word = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
956
			}  /* if */
957
			env->entries[idx]->low_word  = new_r_Const(irg, get_mode_null(mode_l));
Michael Beck's avatar
Michael Beck committed
958
959

			return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
960
961
		}  /* if */
	}  /* if */
Michael Beck's avatar
Michael Beck committed
962
	lower_Shiftop(node, mode, env);
963
}  /* lower_Shl */
Michael Beck's avatar
Michael Beck committed
964
965
966
967

/**
 * Translate a Shrs and handle special cases.
 */
968
969
static void lower_Shrs(ir_node *node, ir_mode *mode, lower_env_t *env)
{
970
971
	ir_node  *right = get_Shrs_right(node);
	ir_graph *irg = current_ir_graph;
Michael Beck's avatar
Michael Beck committed
972
973
974
975
976

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

		if (tarval_is_long(tv) &&
977
		    get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
978
979
980
981
			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);
982
			ir_mode *mode_l;
983
			ir_node *low;
Michael Beck's avatar
Michael Beck committed
984
985
986
			ir_node *c;

			left = env->entries[idx]->high_word;
987
988
989
990
991
			if (left == NULL) {
				/* not ready yet, wait */
				pdeq_putr(env->waitq, node);
				return;
			}
Michael Beck's avatar
Michael Beck committed
992

993
			idx    = get_irn_idx(node);
994
			mode_l = env->params->low_unsigned;
995
			if (shf_cnt > 0) {
996
				c   = new_r_Const_long(irg, mode_l, shf_cnt);
997
				low = new_r_Shrs(block, left, c, mode);
Michael Beck's avatar
BugFix:    
Michael Beck committed
998
			} else {
999
				low = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
1000
			}  /* if */
1001
			/* low word is expected to have mode_l */
1002
			env->entries[idx]->low_word = new_r_Conv(block, low, mode_l);
1003

1004
			c = new_r_Const_long(irg, mode_l, get_mode_size_bits(mode) - 1);
1005
			env->entries[idx]->high_word = new_r_Shrs(block, left, c, mode);
Michael Beck's avatar
Michael Beck committed
1006
1007

			return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
1008
1009
		}  /* if */
	}  /* if */
Michael Beck's avatar
Michael Beck committed
1010
	lower_Shiftop(node, mode, env);
1011
}  /* lower_Shrs */
Michael Beck's avatar
Michael Beck committed
1012
1013

/**
Michael Beck's avatar
Michael Beck committed
1014
 * Rebuild Rotl nodes into Or(Shl, Shr) and prepare all nodes.
Michael Beck's avatar
Michael Beck committed
1015
 */
1016
1017
static void prepare_links_and_handle_rotl(ir_node *node, void *env)
{
Michael Beck's avatar
Michael Beck committed
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
	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;
				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);
				block = get_nodes_block(node);
1045
				shl   = new_rd_Shl(dbg, block, left, right, omode);
Michael Beck's avatar
Michael Beck committed
1046
1047
				rmode = get_irn_mode(right);
				c     = new_Const_long(rmode, get_mode_size_bits(omode));
1048
1049
				sub   = new_rd_Sub(dbg, block, c, right, rmode);
				shr   = new_rd_Shr(dbg, block, left, sub, omode);
Michael Beck's avatar
Michael Beck committed
1050
1051
1052
1053

				/* optimization must be switched off here, or we will get the Rotl back */
				save_optimization_state(&state);
				set_opt_algebraic_simplification(0);
1054
				or = new_rd_Or(dbg, block, shl, shr, omode);
Michael Beck's avatar
Michael Beck committed
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
				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
1070

Michael Beck's avatar
Michael Beck committed
1071
1072
1073
/**
 * Translate a special case Rotl(x, sizeof(w)).
 */
1074
1075
static void lower_Rotl(ir_node *node, ir_mode *mode, lower_env_t *env)
{
Michael Beck's avatar
Michael Beck committed
1076
1077
1078
1079
	ir_node *right = get_Rotl_right(node);
	ir_node *left = get_Rotl_left(node);
	ir_node *h, *l;
	int idx = get_irn_idx(left);
Matthias Braun's avatar
Matthias Braun committed
1080
1081
	(void) right;
	(void) mode;
Michael Beck's avatar
Michael Beck committed
1082

Michael Beck's avatar
Michael Beck committed
1083
1084
1085
	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
1086

Michael Beck's avatar
Michael Beck committed
1087
1088
1089
	l = env->entries[idx]->low_word;
	h = env->entries[idx]->high_word;
	idx = get_irn_idx(node);
Michael Beck's avatar
Michael Beck committed
1090

Michael Beck's avatar
Michael Beck committed
1091
1092
1093
	env->entries[idx]->low_word  = h;
	env->entries[idx]->high_word = l;
}  /* lower_Rotl */
1094

1095
1096
1097