lower_dw.c 73 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
30
31
32
33
34
35
36
37

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

#include <assert.h>

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

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

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

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

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

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

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

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

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

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

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

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

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

201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
/**
 * Add an additional control flow input to a block.
 * Patch all Phi nodes. The new Phi inputs are copied from
 * old input number nr.
 */
static void add_block_cf_input_nr(ir_node *block, int nr, ir_node *cf)
{
	int i, arity = get_irn_arity(block);
	ir_node **in, *phi;

	assert(nr < arity);

	NEW_ARR_A(ir_node *, in, arity + 1);
	for (i = 0; i < arity; ++i)
		in[i] = get_irn_n(block, i);
	in[i] = cf;

	set_irn_in(block, i + 1, in);

220
	for (phi = get_Block_phis(block); phi != NULL; phi = get_Phi_next(phi)) {
221
222
223
224
		for (i = 0; i < arity; ++i)
			in[i] = get_irn_n(phi, i);
		in[i] = in[nr];
		set_irn_in(phi, i + 1, in);
Michael Beck's avatar
BugFix:    
Michael Beck committed
225
	}  /* for */
226
}  /* add_block_cf_input_nr */
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241

/**
 * Add an additional control flow input to a block.
 * Patch all Phi nodes. The new Phi inputs are copied from
 * old input from cf tmpl.
 */
static void add_block_cf_input(ir_node *block, ir_node *tmpl, ir_node *cf)
{
	int i, arity = get_irn_arity(block);
	int nr = 0;

	for (i = 0; i < arity; ++i) {
		if (get_irn_n(block, i) == tmpl) {
			nr = i;
			break;
Michael Beck's avatar
BugFix:    
Michael Beck committed
242
243
		}  /* if */
	}  /* for */
244
245
	assert(i < arity);
	add_block_cf_input_nr(block, nr, cf);
246
}  /* add_block_cf_input */
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267

/**
 * Return the "operational" mode of a Firm node.
 */
static ir_mode *get_irn_op_mode(ir_node *node)
{
	switch (get_irn_opcode(node)) {
	case iro_Load:
		return get_Load_mode(node);
	case iro_Store:
		return get_irn_mode(get_Store_value(node));
	case iro_DivMod:
		return get_irn_mode(get_DivMod_left(node));
	case iro_Div:
		return get_irn_mode(get_Div_left(node));
	case iro_Mod:
		return get_irn_mode(get_Mod_left(node));
	case iro_Cmp:
		return get_irn_mode(get_Cmp_left(node));
	default:
		return get_irn_mode(node);
Michael Beck's avatar
BugFix:    
Michael Beck committed
268
	}  /* switch */
269
}  /* get_irn_op_mode */
270
271

/**
272
 * Walker, prepare the node links.
273
274
275
276
277
278
 */
static void prepare_links(ir_node *node, void *env)
{
	lower_env_t  *lenv = env;
	ir_mode      *mode = get_irn_op_mode(node);
	node_entry_t *link;
Michael Beck's avatar
Michael Beck committed
279
	int          i, idx;
280
281
282
283
284
285
286
287

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

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

/**
 * 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);
	int      idx;
343
	ir_graph *irg = current_ir_graph;
344
	ir_mode  *low_mode = env->params->low_unsigned;
345
346
347

	tv   = get_Const_tarval(node);

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

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

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

/**
 * Translate a Load: create two.
 */
static void lower_Load(ir_node *node, ir_mode *mode, lower_env_t *env) {
364
	ir_mode  *low_mode = env->params->low_unsigned;
365
366
367
368
369
370
371
372
373
374
375
	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,
376
			new_r_Const(irg, env->tv_mode_bytes),
377
			get_irn_mode(adr));
Michael Beck's avatar
BugFix:    
Michael Beck committed
378
	} else {
379
		low  = new_r_Add(irg, block, adr,
380
			new_r_Const(irg, env->tv_mode_bytes),
381
382
			get_irn_mode(adr));
		high = adr;
Michael Beck's avatar
BugFix:    
Michael Beck committed
383
	}  /* if */
384
385
386

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

/**
 * 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
435
436
	(void) node;
	(void) mode;
437
438
439
440
441
442
443
444
445

	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
446
	}  /* if */
447
448
449
450
451
452
453
454
455

	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,
456
			new_r_Const(irg, env->tv_mode_bytes),
457
			get_irn_mode(adr));
Michael Beck's avatar
BugFix:    
Michael Beck committed
458
	} else {
459
		low  = new_r_Add(irg, block, adr,
460
			new_r_Const(irg, env->tv_mode_bytes),
461
462
			get_irn_mode(adr));
		high = adr;
Michael Beck's avatar
BugFix:    
Michael Beck committed
463
	}  /* if */
464
465
466
467
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

	/* 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
493
		}  /* switch */
494
495
496
		/* 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
497
	}  /* for */
498
}  /* lower_Store */
499
500
501

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

Michael Beck's avatar
Michael Beck committed
517
518
519
520
	key.op    = op;
	key.imode = imode;
	key.omode = omode;
	key.ent   = NULL;
521

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

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

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

	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
573
	}  /* if */
574
575
576
577

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

578
	dbg   = get_irn_dbg_info(node);
579
	block = get_nodes_block(node);
580
	irg   = current_ir_graph;
581
582

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

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

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

	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
653
	}  /* if */
654
655
656
657

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

658
	dbg   = get_irn_dbg_info(node);
659
	block = get_nodes_block(node);
660
	irg   = current_ir_graph;
661
662

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

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

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

	/* 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
721
722
		}  /* switch */
	}  /* for */
723
724
725
726
727
728
729
730
731

	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
732
	}  /* if */
733
734
735
736
737
738
739
740
741
742
743
744

	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
745
	}  /* if */
746
747
748
749

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

750
	dbg   = get_irn_dbg_info(node);
751
	block = get_nodes_block(node);
752
	irg   = current_ir_graph;
753
754
755
756
757
758

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

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

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

	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
844
	}  /* if */
845
846
847
848

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

849
	dbg   = get_irn_dbg_info(node);
850
	block = get_nodes_block(node);
851
	irg   = current_ir_graph;
852
853

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

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
862
863
	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);
864
}  /* lower_Binop */
865

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

	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);
898
	irg  = current_ir_graph;
Christian Würdig's avatar
Christian Würdig committed
899
900
901

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

	idx = get_irn_idx(node);
	assert(idx < env->n_entries);
909
910
	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);
911
}  /* lower_Shiftop */
Christian Würdig's avatar
Christian Würdig committed
912

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

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

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

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

934
			if (shf_cnt > 0) {
935
				c = new_r_Const_long(irg, env->params->low_unsigned, shf_cnt);
936
				env->entries[idx]->low_word = new_r_Shr(irg, block, left, c, mode);
Michael Beck's avatar
BugFix:    
Michael Beck committed
937
			} else {
938
				env->entries[idx]->low_word = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
939
			}  /* if */
940
			env->entries[idx]->high_word = new_r_Const(irg, get_mode_null(mode));
Michael Beck's avatar
Michael Beck committed
941
942

			return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
943
944
		}  /* if */
	}  /* if */
Michael Beck's avatar
Michael Beck committed
945
	lower_Shiftop(node, mode, env);
946
}  /* lower_Shr */
Michael Beck's avatar
Michael Beck committed
947
948
949
950
951

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

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

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

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

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

			return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
980
981
		}  /* if */
	}  /* if */
Michael Beck's avatar
Michael Beck committed
982
	lower_Shiftop(node, mode, env);
983
}  /* lower_Shl */
Michael Beck's avatar
Michael Beck committed
984
985
986
987
988

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

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

		if (tarval_is_long(tv) &&
996
		    get_tarval_long(tv) >= (long)get_mode_size_bits(mode)) {
997
998
999
1000
			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);
1001
			ir_mode *mode_l;
1002
			ir_node *low;
Michael Beck's avatar
Michael Beck committed
1003
1004
1005
1006
1007
			ir_node *c;

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

1008
			mode_l = env->params->low_unsigned;
1009
			if (shf_cnt > 0) {
1010
				c   = new_r_Const_long(irg, mode_l, shf_cnt);
1011
				low = new_r_Shrs(irg, block, left, c, mode);
Michael Beck's avatar
BugFix:    
Michael Beck committed
1012
			} else {
1013
				low = left;
Michael Beck's avatar
BugFix:    
Michael Beck committed
1014
			}  /* if */
1015
1016
			/* low word is expected to have mode_l */
			env->entries[idx]->low_word = new_r_Conv(irg, block, low, mode_l);
1017

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

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

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

Michael Beck's avatar
Michael Beck committed
1086
1087
1088
1089
1090
1091
1092
1093
/**
 * 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);
Matthias Braun's avatar
Matthias Braun committed
1094
1095
	(void) right;
	(void) mode;
Michael Beck's avatar
Michael Beck committed
1096

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

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

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

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

	irn   = get_unop_op(node);
	entry = env->entries[get_irn_idx(irn)];
	assert(entry);

	if (! entry->low_word) {
		/* not ready yet, wait */
		pdeq_putr(env->waitq, node);
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
1131
	}  /* if */
1132
1133
1134
1135

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

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

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

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

/**
 * Translate a logical Binop.
 *
 * Create two logical Binops.
 */
static void lower_Binop_logical(ir_node *node, ir_mode *mode, lower_env_t *env,
								ir_node *(*constr_rd)(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *op1, ir_node *op2, ir_mode *mode) ) {
	ir_node  *block, *irn;
	ir_node  *lop_l, *lop_h, *rop_l, *rop_h;
	dbg_info *dbg;
	int      idx;
1164
	ir_graph *irg;
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
	node_entry_t *entry;

	irn   = get_binop_left(node);
	entry = env->entries[get_irn_idx(irn)];
	assert(entry);

	if (! entry->low_word) {
		/* not ready yet, wait */
		pdeq_putr(env->waitq, node);
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
1175
	}  /* if */
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187

	lop_l = entry->low_word;
	lop_h = entry->high_word;

	irn   = get_binop_right(node);
	entry = env->entries[get_irn_idx(irn)];
	assert(entry);

	if (! entry->low_word) {
		/* not ready yet, wait */
		pdeq_putr(env->waitq, node);
		return;
Michael Beck's avatar
BugFix:    
Michael Beck committed
1188
	}  /* if */
1189
1190
1191
1192
1193
1194
1195
1196
1197

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

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

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

1203
/** create a logical operation transformation */