betranshlp.c 17.4 KB
Newer Older
1
2
/*
 * This file is part of libFirm.
3
 * Copyright (C) 2012 University of Karlsruhe.
4
5
6
7
8
 */

/**
 * @file
 * @brief       be transform helper extracted from the ia32 backend.
Michael Beck's avatar
Michael Beck committed
9
 * @author      Matthias Braun, Michael Beck
10
11
12
13
14
15
16
 * @date        14.06.2007
 */
#include "pdeq.h"
#include "irop_t.h"
#include "iropt_t.h"
#include "irnode_t.h"
#include "irgraph_t.h"
17
#include "ircons_t.h"
18
19
20
21
#include "irhooks.h"
#include "iredges.h"
#include "irouts.h"
#include "trouts.h"
Matthias Braun's avatar
Matthias Braun committed
22
#include "irgmod.h"
23
24
#include "cgana.h"
#include "debug.h"
25
#include "execfreq_t.h"
26

27
#include "beirg.h"
28
#include "beabi.h"
29
#include "betranshlp.h"
30
#include "belive.h"
31
#include "benode.h"
32
33
34
35
36

typedef struct be_transform_env_t {
	ir_graph *irg;         /**< The irg, the node should be created in */
	waitq    *worklist;    /**< worklist of nodes that still need to be
	                            transformed */
37
	ir_node  *old_anchor;  /**< the old anchor node in the old irg */
38
39
40
41
42
} be_transform_env_t;


static be_transform_env_t env;

43
44
void be_set_transformed_node(ir_node *old_node, ir_node *new_node)
{
45
	set_irn_link(old_node, new_node);
46
	mark_irn_visited(old_node);
47
48
}

49
50
int be_is_transformed(const ir_node *node)
{
51
52
53
	return irn_visited(node);
}

54
55
static inline ir_node *be_get_transformed_node(ir_node *old_node)
{
56
	if (irn_visited(old_node)) {
57
		ir_node *new_node = (ir_node*)get_irn_link(old_node);
58
59
60
61
		assert(new_node != NULL);
		return new_node;
	}
	return NULL;
62
63
}

64
65
void be_duplicate_deps(ir_node *old_node, ir_node *new_node)
{
66
	int deps = get_irn_n_deps(old_node);
Matthias Braun's avatar
Matthias Braun committed
67
	for (int i = 0; i < deps; ++i) {
68
69
70
71
72
73
74
		ir_node *dep     = get_irn_dep(old_node, i);
		ir_node *new_dep = be_transform_node(dep);

		add_irn_dep(new_node, new_dep);
	}
}

75
76
77
ir_node *be_transform_phi(ir_node *node, const arch_register_req_t *req)
{
	ir_node  *block = be_transform_node(get_nodes_block(node));
78
	ir_graph *irg   = get_Block_irg(block);
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
	dbg_info *dbgi  = get_irn_dbg_info(node);

	/* phi nodes allow loops, so we use the old arguments for now
	 * and fix this later */
	ir_node **ins   = get_irn_in(node)+1;
	int       arity = get_irn_arity(node);
	ir_mode  *mode  = req->cls != NULL ? req->cls->mode : get_irn_mode(node);
	ir_node  *phi   = new_ir_node(dbgi, irg, block, op_Phi, mode, arity, ins);
	copy_node_attr(irg, node, phi);
	be_duplicate_deps(node, phi);

	backend_info_t *info = be_get_info(phi);
	struct obstack *obst = be_get_be_obst(irg);
	info->in_reqs = OALLOCN(obst, const arch_register_req_t*, arity);
	for (int i = 0; i < arity; ++i) {
		info->in_reqs[i] = req;
	}

	arch_set_irn_register_req_out(phi, 0, req);
	be_enqueue_preds(node);

	return phi;
}

103
104
105
106
107
108
109
110
111
void be_set_transform_function(ir_op *op, be_transform_func func)
{
	/* shouldn't be assigned twice (except for exchanging the default
	 * be_duplicate_node entries) */
	assert(op->ops.generic == NULL
			|| op->ops.generic == (op_func) be_duplicate_node);
	op->ops.generic = (op_func) func;
}

112
113
114
115
116
void be_set_transform_proj_function(ir_op *op, be_transform_func func)
{
	op->ops.generic1 = (op_func) func;
}

117
118
119
120
121
/**
 * Transform helper for blocks.
 */
static ir_node *transform_block(ir_node *node)
{
Matthias Braun's avatar
Matthias Braun committed
122
123
124
125
126
	ir_graph *irg   = get_irn_irg(node);
	dbg_info *dbgi  = get_irn_dbg_info(node);
	ir_mode  *mode  = get_irn_mode(node);
	ir_node  *block = new_ir_node(dbgi, irg, NULL, get_irn_op(node), mode,
	                              get_irn_arity(node), get_irn_in(node) + 1);
127
128
129
	copy_node_attr(irg, node, block);
	block->node_nr = node->node_nr;

130
131
132
133
	/* transfer execfreq value */
	double execfreq = get_block_execfreq(node);
	set_block_execfreq(block, execfreq);

134
135
136
137
138
139
140
141
142
	/* put the preds in the worklist */
	be_enqueue_preds(node);

	return block;
}

static ir_node *transform_end(ir_node *node)
{
	/* end has to be duplicated manually because we need a dynamic in array */
Matthias Braun's avatar
Matthias Braun committed
143
144
145
146
	ir_graph *irg     = get_irn_irg(node);
	dbg_info *dbgi    = get_irn_dbg_info(node);
	ir_node  *block   = be_transform_node(get_nodes_block(node));
	ir_node  *new_end = new_ir_node(dbgi, irg, block, op_End, mode_X, -1, NULL);
147
148
149
150
151
152
153
	copy_node_attr(irg, node, new_end);
	be_duplicate_deps(node, new_end);

	set_irg_end(irg, new_end);

	/* do not transform predecessors yet to keep the pre-transform
	 * phase from visiting all the graph */
Matthias Braun's avatar
Matthias Braun committed
154
155
	int arity = get_irn_arity(node);
	for (int i = 0; i < arity; ++i) {
156
157
158
159
160
161
162
163
		ir_node *in = get_irn_n(node, i);
		add_End_keepalive(new_end, in);
	}
	be_enqueue_preds(node);

	return new_end;
}

164
165
166
167
168
169
170
171
172
173
174
static ir_node *transform_proj(ir_node *node)
{
	ir_node *pred    = get_Proj_pred(node);
	ir_op   *pred_op = get_irn_op(pred);
	be_transform_func *proj_transform
		= (be_transform_func*)pred_op->ops.generic1;
	/* we should have a Proj transformer registered */
	assert(proj_transform != NULL);
	return proj_transform(node);
}

175
176
ir_node *be_duplicate_node(ir_node *node)
{
177
178
179
180
181
182
	ir_node  *block = be_transform_node(get_nodes_block(node));
	ir_graph *irg   = env.irg;
	dbg_info *dbgi  = get_irn_dbg_info(node);
	ir_mode  *mode  = get_irn_mode(node);
	ir_op    *op    = get_irn_op(node);

Matthias Braun's avatar
Matthias Braun committed
183
184
	ir_node *new_node;
	int      arity = get_irn_arity(node);
185
186
	if (op->opar == oparity_dynamic) {
		new_node = new_ir_node(dbgi, irg, block, op, mode, -1, NULL);
Matthias Braun's avatar
Matthias Braun committed
187
		for (int i = 0; i < arity; ++i) {
188
189
190
191
192
			ir_node *in = get_irn_n(node, i);
			in = be_transform_node(in);
			add_irn_n(new_node, in);
		}
	} else {
193
		ir_node **ins = ALLOCAN(ir_node*, arity);
Matthias Braun's avatar
Matthias Braun committed
194
		for (int i = 0; i < arity; ++i) {
195
196
197
198
199
200
201
			ir_node *in = get_irn_n(node, i);
			ins[i] = be_transform_node(in);
		}

		new_node = new_ir_node(dbgi, irg, block, op, mode, arity, ins);
	}

202
	copy_node_attr(irg, node, new_node);
203
204
205
206
207
208
	be_duplicate_deps(node, new_node);

	new_node->node_nr = node->node_nr;
	return new_node;
}

209
210
ir_node *be_transform_node(ir_node *node)
{
Matthias Braun's avatar
Matthias Braun committed
211
	ir_node *new_node = be_get_transformed_node(node);
212
	if (new_node != NULL)
213
214
		return new_node;

215
	DEBUG_ONLY(be_set_transformed_node(node, NULL);)
216

Matthias Braun's avatar
Matthias Braun committed
217
218
	ir_op *op = get_irn_op(node);
	be_transform_func *transform = (be_transform_func *)op->ops.generic;
219
220
221

	new_node = transform(node);
	assert(new_node != NULL);
222
223
224
225
226

	be_set_transformed_node(node, new_node);
	return new_node;
}

227
228
void be_enqueue_preds(ir_node *node)
{
229
	/* put the preds in the worklist */
Matthias Braun's avatar
Matthias Braun committed
230
231
	int arity = get_irn_arity(node);
	for (int i = 0; i < arity; ++i) {
232
233
234
235
236
237
238
239
		ir_node *pred = get_irn_n(node, i);
		pdeq_putr(env.worklist, pred);
	}
}

/**
 * Rewire nodes which are potential loops (like Phis) to avoid endless loops.
 */
240
241
static void fix_loops(ir_node *node)
{
242
	if (irn_visited_else_mark(node))
243
244
		return;

245
246
	assert(node_is_in_irgs_storage(env.irg, node));

Matthias Braun's avatar
Matthias Braun committed
247
	bool changed = false;
248
249
	if (! is_Block(node)) {
		ir_node *block     = get_nodes_block(node);
250
		ir_node *new_block = (ir_node*)get_irn_link(block);
251
252
253
254

		if (new_block != NULL) {
			set_nodes_block(node, new_block);
			block = new_block;
Matthias Braun's avatar
Matthias Braun committed
255
			changed = true;
256
257
258
259
260
		}

		fix_loops(block);
	}

Matthias Braun's avatar
Matthias Braun committed
261
262
	int arity = get_irn_arity(node);
	for (int i = 0; i < arity; ++i) {
263
		ir_node *in = get_irn_n(node, i);
264
		ir_node *nw = (ir_node*)get_irn_link(in);
265
266
267
268

		if (nw != NULL && nw != in) {
			set_irn_n(node, i, nw);
			in = nw;
Matthias Braun's avatar
Matthias Braun committed
269
			changed = true;
270
271
272
273
		}

		fix_loops(in);
	}
274
	/* fix proj block */
275
	if (is_Proj(node)) {
276
		set_nodes_block(node, get_nodes_block(get_Proj_pred(node)));
Matthias Braun's avatar
Matthias Braun committed
277
		changed = true;
278
	}
279

280
	arity = get_irn_n_deps(node);
Matthias Braun's avatar
Matthias Braun committed
281
	for (int i = 0; i < arity; ++i) {
282
		ir_node *in = get_irn_dep(node, i);
283
		ir_node *nw = (ir_node*)get_irn_link(in);
284
285
286
287

		if (nw != NULL && nw != in) {
			set_irn_dep(node, i, nw);
			in = nw;
Matthias Braun's avatar
Matthias Braun committed
288
			changed = true;
289
290
291
292
		}

		fix_loops(in);
	}
293

294
	if (changed) {
295
		identify_remember(node);
296
	}
297
298
}

299
300
ir_node *be_pre_transform_node(ir_node *place)
{
301
302
303
304
305
306
	if (place == NULL)
		return NULL;

	return be_transform_node(place);
}

307
static void pre_transform_anchor(ir_graph *irg, int anchor)
308
309
310
{
	ir_node *old_anchor_node = get_irn_n(env.old_anchor, anchor);
	ir_node *transformed     = be_transform_node(old_anchor_node);
311
	set_irg_anchor(irg, anchor, transformed);
312
313
}

314
315
316
/**
 * Transforms all nodes. Deletes the old obstack and creates a new one.
 */
317
static void transform_nodes(ir_graph *irg, arch_pretrans_nodes *pre_transform)
318
{
319
320
321
322
	hook_dead_node_elim(irg, 1);

	inc_irg_visited(irg);

323
324
325
	env.irg        = irg;
	env.worklist   = new_waitq();
	env.old_anchor = irg->anchor;
326

Matthias Braun's avatar
Matthias Braun committed
327
	ir_node *old_end = get_irg_end(irg);
328
329

	/* put all anchor nodes in the worklist */
Matthias Braun's avatar
Matthias Braun committed
330
	for (int i = get_irg_n_anchors(irg) - 1; i >= 0; --i) {
331
		ir_node *anchor = get_irg_anchor(irg, i);
332
333
334
335
336
337

		if (anchor == NULL)
			continue;
		waitq_put(env.worklist, anchor);
	}

Matthias Braun's avatar
Matthias Braun committed
338
	ir_node *new_anchor  = new_r_Anchor(irg);
339
	irg->anchor = new_anchor;
340

341
342
	/* pre transform some anchors (so they are available in the other transform
	 * functions) */
343
344
345
346
347
348
	pre_transform_anchor(irg, anchor_no_mem);
	pre_transform_anchor(irg, anchor_end_block);
	pre_transform_anchor(irg, anchor_end);
	pre_transform_anchor(irg, anchor_start_block);
	pre_transform_anchor(irg, anchor_start);
	pre_transform_anchor(irg, anchor_frame);
349
350

	if (pre_transform)
351
		pre_transform();
352
353
354

	/* process worklist (this should transform all nodes in the graph) */
	while (! waitq_empty(env.worklist)) {
355
		ir_node *node = (ir_node*)waitq_get(env.worklist);
356
357
358
359
360
		be_transform_node(node);
	}

	/* fix loops and set new anchors*/
	inc_irg_visited(irg);
Matthias Braun's avatar
Matthias Braun committed
361
	for (int i = get_irg_n_anchors(irg) - 1; i >= 0; --i) {
362
		ir_node *anchor = get_irn_n(env.old_anchor, i);
363
364
365
366

		if (anchor == NULL)
			continue;

367
		anchor = (ir_node*)get_irn_link(anchor);
368
		fix_loops(anchor);
369
		set_irn_n(new_anchor, i, anchor);
370
371
372
373
374
375
376
	}

	del_waitq(env.worklist);
	free_End(old_end);
	hook_dead_node_elim(irg, 0);
}

377
void be_transform_graph(ir_graph *irg, arch_pretrans_nodes *func)
378
379
380
381
382
{
	ir_graph *old_current_ir_graph = current_ir_graph;
	current_ir_graph = irg;

	/* create a new obstack */
383
384
	struct obstack old_obst = irg->obst;
	obstack_init(&irg->obst);
385
386
	irg->last_node_idx = 0;

387
	free_vrp_data(irg);
388

389
	/* create new value table for CSE */
390
	new_identities(irg);
391
392

	/* do the main transformation */
393
	transform_nodes(irg, func);
394
395

	/* free the old obstack */
396
	obstack_free(&old_obst, 0);
397
398
399
400

	/* restore state */
	current_ir_graph = old_current_ir_graph;

401
	/* most analysis info is wrong after transformation */
402
	be_invalidate_live_chk(irg);
Matthias Braun's avatar
Matthias Braun committed
403
	confirm_irg_properties(irg, IR_GRAPH_PROPERTIES_NONE);
404

405
406
407
	/* recalculate edges */
	edges_activate(irg);
}
408
409
410
411

bool be_upper_bits_clean(const ir_node *node, ir_mode *mode)
{
	ir_op *op = get_irn_op(node);
412
	if (op->ops.generic2 == NULL)
413
		return false;
414
	upper_bits_clean_func func = (upper_bits_clean_func)op->ops.generic2;
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
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
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
	return func(node, mode);
}

static bool bit_binop_upper_bits_clean(const ir_node *node, ir_mode *mode)
{
	return be_upper_bits_clean(get_binop_left(node), mode)
	    && be_upper_bits_clean(get_binop_right(node), mode);
}

static bool mux_upper_bits_clean(const ir_node *node, ir_mode *mode)
{
	return be_upper_bits_clean(get_Mux_true(node), mode)
	    && be_upper_bits_clean(get_Mux_false(node), mode);
}

static bool and_upper_bits_clean(const ir_node *node, ir_mode *mode)
{
	if (!mode_is_signed(mode)) {
		return be_upper_bits_clean(get_And_left(node), mode)
		    || be_upper_bits_clean(get_And_right(node), mode);
	} else {
		return bit_binop_upper_bits_clean(node, mode);
	}
}

static bool shr_upper_bits_clean(const ir_node *node, ir_mode *mode)
{
	if (mode_is_signed(mode)) {
		return false;
	} else {
		const ir_node *right = get_Shr_right(node);
		if (is_Const(right)) {
			ir_tarval *tv  = get_Const_tarval(right);
			long       val = get_tarval_long(tv);
			if (val >= 32 - (long)get_mode_size_bits(mode))
				return true;
		}
		return be_upper_bits_clean(get_Shr_left(node), mode);
	}
}

static bool shrs_upper_bits_clean(const ir_node *node, ir_mode *mode)
{
	return be_upper_bits_clean(get_Shrs_left(node), mode);
}

static bool const_upper_bits_clean(const ir_node *node, ir_mode *mode)
{
	ir_tarval *tv  = get_Const_tarval(node);
	long       val = get_tarval_long(tv);
	if (mode_is_signed(mode)) {
		long    shifted = val >> (get_mode_size_bits(mode)-1);
		return shifted == 0 || shifted == -1;
	} else {
		unsigned long shifted = (unsigned long)val;
		shifted >>= get_mode_size_bits(mode)-1;
		shifted >>= 1;
		return shifted == 0;
	}
}

static bool conv_upper_bits_clean(const ir_node *node, ir_mode *mode)
{
	ir_mode       *dest_mode = get_irn_mode(node);
	const ir_node *op        = get_Conv_op(node);
	ir_mode       *src_mode  = get_irn_mode(op);
	if (mode_is_float(src_mode))
		return true;

	unsigned src_bits  = get_mode_size_bits(src_mode);
	unsigned dest_bits = get_mode_size_bits(dest_mode);
	/* downconvs are a nop */
	if (src_bits >= dest_bits)
		return be_upper_bits_clean(op, mode);
	/* upconvs are fine if src is big enough or if sign matches */
	if (src_bits <= get_mode_size_bits(mode)
		&& mode_is_signed(src_mode) == mode_is_signed(mode))
		return true;
	return false;
}

static bool proj_upper_bits_clean(const ir_node *node, ir_mode *mode)
{
	const ir_node *pred = get_Proj_pred(node);
	switch (get_irn_opcode(pred)) {
	case iro_Load: {
		ir_mode *load_mode = get_Load_mode(pred);
		unsigned load_bits = get_mode_size_bits(load_mode);
		if (load_bits > get_mode_size_bits(mode))
			return false;
		if (mode_is_signed(load_mode) != mode_is_signed(mode))
			return false;
		return true;
	}
	default:
		break;
	}
	return false;
}

void be_set_upper_bits_clean_function(ir_op *op, upper_bits_clean_func func)
{
517
	op->ops.generic2 = (op_func)func;
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
}

void be_start_transform_setup(void)
{
	ir_clear_opcodes_generic_func();

	be_set_transform_function(op_Bad,         be_duplicate_node);
	be_set_transform_function(op_be_CopyKeep, be_duplicate_node);
	be_set_transform_function(op_be_IncSP,    be_duplicate_node);
	be_set_transform_function(op_be_Keep,     be_duplicate_node);
	be_set_transform_function(op_be_Return,   be_duplicate_node);
	be_set_transform_function(op_be_Start,    be_duplicate_node);
	be_set_transform_function(op_Block,       transform_block);
	be_set_transform_function(op_End,         transform_end);
	be_set_transform_function(op_NoMem,       be_duplicate_node);
	be_set_transform_function(op_Pin,         be_duplicate_node);
534
	be_set_transform_function(op_Proj,        transform_proj);
535
536
537
538
539
540
541
542
543
544
545
546
547
	be_set_transform_function(op_Start,       be_duplicate_node);
	be_set_transform_function(op_Sync,        be_duplicate_node);

	be_set_upper_bits_clean_function(op_And,   and_upper_bits_clean);
	be_set_upper_bits_clean_function(op_Const, const_upper_bits_clean);
	be_set_upper_bits_clean_function(op_Conv,  conv_upper_bits_clean);
	be_set_upper_bits_clean_function(op_Eor,   bit_binop_upper_bits_clean);
	be_set_upper_bits_clean_function(op_Mux,   mux_upper_bits_clean);
	be_set_upper_bits_clean_function(op_Or,    bit_binop_upper_bits_clean);
	be_set_upper_bits_clean_function(op_Proj,  proj_upper_bits_clean);
	be_set_upper_bits_clean_function(op_Shr,   shr_upper_bits_clean);
	be_set_upper_bits_clean_function(op_Shrs,  shrs_upper_bits_clean);
}
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605

bool be_pattern_is_rotl(ir_node const *const irn_or, ir_node **const left,
                        ir_node **const right)
{
	assert(is_Add(irn_or) || is_Or(irn_or));

	ir_mode *mode = get_irn_mode(irn_or);
	if (!mode_is_int(mode))
		return false;

	ir_node *shl = get_binop_left(irn_or);
	ir_node *shr = get_binop_right(irn_or);
	if (is_Shr(shl)) {
		if (!is_Shl(shr))
			return false;

		ir_node *tmp = shl;
		shl = shr;
		shr = tmp;
	} else if (!is_Shl(shl)) {
		return false;
	} else if (!is_Shr(shr)) {
		return false;
	}

	ir_node *x = get_Shl_left(shl);
	if (x != get_Shr_left(shr))
		return false;

	ir_node *c1 = get_Shl_right(shl);
	ir_node *c2 = get_Shr_right(shr);
	if (is_Const(c1) && is_Const(c2)) {
		ir_tarval *tv1 = get_Const_tarval(c1);
		if (!tarval_is_long(tv1))
			return false;

		ir_tarval *tv2 = get_Const_tarval(c2);
		if (!tarval_is_long(tv2))
			return false;

		if (get_tarval_long(tv1) + get_tarval_long(tv2)
		    != (long) get_mode_size_bits(mode))
			return false;

		*left  = x;
		*right = c1;
		return true;
	}

	/* Note: the obvious rot formulation (a << x) | (a >> (32-x)) gets
	 * transformed to (a << x) | (a >> -x) by transform_node_shift_modulo() */
	if (!ir_is_negated_value(c1, c2))
		return false;

	*left  = x;
	*right = c1;
	return true;
}
Matthias Braun's avatar
Matthias Braun committed
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629

void be_map_exc_node_to_runtime_call(ir_node *node, ir_mode *res_mode,
                                     ir_entity *runtime_entity,
                                     long pn_M, long pn_X_regular,
                                     long pn_X_except, long pn_res)
{
	assert(is_memop(node));

	size_t    n_in = get_irn_arity(node)-1;
	ir_node **in   = ALLOCAN(ir_node*, n_in);
	ir_type  *mtp  = get_entity_type(runtime_entity);

	assert(get_method_n_params(mtp) == n_in);
	size_t p = 0;
	for (int i = 0, arity = get_irn_arity(node); i < arity; ++i) {
		ir_node *n = get_irn_n(node, i);
		if (get_irn_mode(n) == mode_M)
			continue;
		in[p++] = n;
	}
	assert(p == n_in);

	ir_graph *irg   = get_irn_irg(node);
	dbg_info *dbgi  = get_irn_dbg_info(node);
630
	ir_node  *addr  = new_r_Address(irg, mode_P_code, runtime_entity);
Matthias Braun's avatar
Matthias Braun committed
631
632
633
634
635
636
637
	ir_node  *block = get_nodes_block(node);
	ir_node  *mem   = get_memop_mem(node);
	ir_node  *call  = new_rd_Call(dbgi, block, mem, addr, n_in, in, mtp);
	set_irn_pinned(call, get_irn_pinned(node));
	int throws_exception = ir_throws_exception(node);
	ir_set_throws_exception(call, throws_exception);

638
639
640
641
	assert(pn_M < 2 && pn_res < 2 && pn_X_regular < 4 && pn_X_except < 4);
	int const         n_proj     = 4;
	int               n_operands = 2;
	ir_node   **const tuple_in   = ALLOCAN(ir_node*, n_proj);
Matthias Braun's avatar
Matthias Braun committed
642
643
644
645
	tuple_in[pn_M] = new_r_Proj(call, mode_M, pn_Call_M);
	ir_node *ress = new_r_Proj(call, mode_T, pn_Call_T_result);
	tuple_in[pn_res] = new_r_Proj(ress, res_mode, 0);
	if (throws_exception) {
646
647
648
		tuple_in[pn_X_regular]  = new_r_Proj(call, mode_X, pn_Call_X_regular);
		tuple_in[pn_X_except]   = new_r_Proj(call, mode_X, pn_Call_X_except);
		n_operands             += 2;
Matthias Braun's avatar
Matthias Braun committed
649
650
	}

651
	turn_into_tuple(node, n_operands, tuple_in);
Matthias Braun's avatar
Matthias Braun committed
652
}