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 "xmalloc.h"
61

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

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

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

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

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

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

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

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

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

/**
 * 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
119
120
	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 */
121
122
123
124
125
126
127
	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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/**
 * 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;
144
}  /* get_primitive_type */
Michael Beck's avatar
Michael Beck committed
145
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

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

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

202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/**
 * 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
226
	}  /* for */
227
}  /* add_block_cf_input_nr */
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242

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

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

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

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

	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
321
	} else if (is_Phi(node)) {
322
323
324
325
326
		/* 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
327
	} else if (is_Block(node)) {
328
329
330
331
332
333
		/* 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
334
335
		}  /* for */
	}  /* if */
336
}  /* prepare_links */
337
338
339
340
341
342
343
344
345
346

/**
 * 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;
347
	ir_graph *irg = current_ir_graph;
348
	ir_mode  *low_mode = env->params->low_unsigned;
349
350
351

	tv   = get_Const_tarval(node);

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

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

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

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

	/* create two loads */
	dbg  = get_irn_dbg_info(node);
391
	low  = new_rd_Load(dbg, irg, block, mem,  low,  low_mode);
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
	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);
417
418
			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);
419
420
421
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
422
		}  /* switch */
423
424
425
		/* 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
426
	}  /* for */
427
}  /* lower_Load */
428
429
430
431
432
433
434
435
436
437
438

/**
 * 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
439
440
	(void) node;
	(void) mode;
441
442
443
444
445
446
447
448
449

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

	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
462
	} else {
463
464
465
466
		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
467
	}  /* if */
468
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

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

/**
 * Return a node containing the address of the intrinsic emulation function.
Michael Beck's avatar
Michael Beck committed
506
507
508
509
510
511
512
 *
 * @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
513
 */
Michael Beck's avatar
Michael Beck committed
514
515
516
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) {
517
	symconst_symbol sym;
518
	ir_entity *ent;
519
520
	op_mode_entry_t key, *entry;

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

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

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

/**
 * 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
549
	ir_mode  *opmode;
550
551
552
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
553
	ir_graph *irg;
554
555
556
557
558
559
560
561
562
563
	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
564
	}  /* if */
565
566
567
568
569
570
571
572
573
574
575
576

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

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

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

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

	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);
609
610
			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);
611
612
613
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
614
		}  /* switch */
615
616
617
		/* 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
618
	}  /* for */
619
}  /* lower_Div */
620
621
622
623
624
625
626
627
628

/**
 * 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
629
	ir_mode  *opmode;
630
631
632
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
633
	ir_graph *irg;
634
635
636
637
638
639
640
641
642
643
	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
644
	}  /* if */
645
646
647
648
649
650
651
652
653
654
655
656

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

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

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

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

	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);
689
690
			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);
691
692
693
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
694
		}  /* switch */
695
696
697
		/* 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
698
	}  /* for */
699
}  /* lower_Mod */
700
701
702
703
704
705
706

/**
 * 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
707
708
709
	ir_node  *block, *proj, *irn, *mem, *callDiv, *callMod;
	ir_node  *resDiv = NULL;
	ir_node  *resMod = NULL;
710
	ir_node  *in[4];
Michael Beck's avatar
Michael Beck committed
711
	ir_mode  *opmode;
712
713
714
715
716
	dbg_info *dbg;
	ir_type  *mtp;
	int      idx;
	node_entry_t *entry;
	unsigned flags = 0;
717
	ir_graph *irg;
718
719
720
721
722
723
724

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

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

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

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

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

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

	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);
796
797
			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);
798
799
800
			break;
		case pn_DivMod_res_mod:   /* Result of Mod. */
			idx = get_irn_idx(proj);
801
802
			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);
803
804
805
			break;
		default:
			assert(0 && "unexpected Proj number");
Michael Beck's avatar
BugFix:    
Michael Beck committed
806
		}  /* switch */
807
808
809
		/* 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
810
	}  /* for */
811
}  /* lower_DivMod */
812
813
814
815
816
817
818
819
820
821
822
823

/**
 * 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;
824
	ir_graph *irg;
825
826
827
828
829
830
831
832
833
834
	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
835
	}  /* if */
836
837
838
839
840
841
842
843
844
845
846
847

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

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

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

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

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
866
867
	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);
868
}  /* lower_Binop */
869

Christian Würdig's avatar
Christian Würdig committed
870
871
872
873
874
875
876
877
878
879
880
/**
 * 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;
881
	ir_graph *irg;
Christian Würdig's avatar
Christian Würdig committed
882
883
884
885
886
887
888
889
890
891
	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
892
	}  /* if */
Christian Würdig's avatar
Christian Würdig committed
893
894
895
896
897
898
899
900
901

	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);
902
	irg  = current_ir_graph;
Christian Würdig's avatar
Christian Würdig committed
903
904
905

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

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
913
914
	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);
915
}  /* lower_Shiftop */
Christian Würdig's avatar
Christian Würdig committed
916

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

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

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

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

938
			if (shf_cnt > 0) {
939
940
				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
941
			} else {
942
				env->entries[idx]->low_word = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
943
			}  /* if */
944
			env->entries[idx]->high_word = new_r_Const(irg, block, mode, get_mode_null(mode));
Michael Beck's avatar
Michael Beck committed
945
946

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

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

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

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

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

974
			if (shf_cnt > 0) {
975
976
				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
977
			} else {
978
				env->entries[idx]->high_word = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
979
			}  /* if */
980
981
			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
982
983

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

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

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

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

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

1010
			if (shf_cnt > 0) {
1011
				ir_node *tmp;
1012
				c = new_r_Const_long(irg, block, mode_Iu, shf_cnt);
1013
1014
1015
				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
1016
			} else {
1017
				env->entries[idx]->low_word = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
1018
			}  /* if */
1019
1020
			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
1021
1022

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

/**
Michael Beck's avatar
Michael Beck committed
1029
 * Rebuild Rotl nodes into Or(Shl, Shr) and prepare all nodes.
Michael Beck's avatar
Michael Beck committed
1030
 */
Michael Beck's avatar
Michael Beck committed
1031
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
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
1086

Michael Beck's avatar
Michael Beck committed
1087
1088
1089
1090
1091
1092
1093
1094
/**
 * 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
1095

Michael Beck's avatar
Michael Beck committed
1096
1097
1098
	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
1099

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

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

1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
/**
 * 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;
1119
	ir_graph *irg;
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
	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
1130
	}  /* if */
1131
1132
1133
1134

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

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

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

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
1148
1149
	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);
1150
}  /* lower_Unop */
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162

/**
 * 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;
1163
	ir_graph *irg;
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
	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
1174
	}  /* if */
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186

	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
1187
	}  /* if */
1188
1189
1190
1191
1192
1193
1194
1195
1196

	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);
1197
	irg = current_ir_graph;
1198
	env->entries[idx]->low_word  = constr_rd(dbg, irg, block, lop_l, rop_l, env->params->low_unsigned);
1199
1200
	env->entries[idx]->high_word = constr_rd(dbg, irg, block, lop_h, rop_h, mode);
}  /* lower_Binop_logical */
1201

1202
/** create a logical operation transformation */
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
#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;
1222
	ir_graph *irg;
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
	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
1233
	}  /* if */
1234
1235
1236
1237

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

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

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