irouts.c 16.9 KB
Newer Older
Götz Lindenmaier's avatar
Götz Lindenmaier committed
1
/*
2
 * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
Matthias Braun's avatar
Matthias Braun committed
3
4
 *
 * This file is part of libFirm.
Michael Beck's avatar
Michael Beck committed
5
 *
Matthias Braun's avatar
Matthias Braun committed
6
7
8
9
 * 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.
Michael Beck's avatar
Michael Beck committed
10
 *
Matthias Braun's avatar
Matthias Braun committed
11
12
13
14
15
16
17
 * 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
18
 */
19

Matthias Braun's avatar
Matthias Braun committed
20
21
22
23
24
25
26
/**
 * @file
 * @brief    Compute and access out edges (also called def-use edges).
 * @author   Goetz Lindenmaier, Michael Beck
 * @date     1.2002
 * @version  $Id$
 */
Michael Beck's avatar
Michael Beck committed
27
28
#ifdef HAVE_CONFIG_H
#include "config.h"
Michael Beck's avatar
Michael Beck committed
29
#endif
30

Michael Beck's avatar
Michael Beck committed
31
32
33
34
35
#ifdef HAVE_STRING_H
#include <string.h>
#endif

#include "xmalloc.h"
36
37
#include "irouts.h"
#include "irnode_t.h"
Götz Lindenmaier's avatar
Götz Lindenmaier committed
38
#include "irgraph_t.h"
39
#include "irprog_t.h"
40
#include "irgwalk.h"
41
#include "irtools.h"
42

43
44
45
46
47
48
#ifdef DEBUG_libfirm
/* Note:  ir_node.out_valid and ir_graph.n_outs are only present when DEBUG_libfirm is defined */
/* Accesses to out_valid and n_outs are fenced out to avoid breakage
   when compiling with neither DEBUG_libfirm or NDEBUG defined */
#endif /* defined DEBUG_libfirm */

Michael Beck's avatar
Michael Beck committed
49
/*--------------------------------------------------------------------*/
50
/** Accessing the out datastructures                                 **/
Michael Beck's avatar
Michael Beck committed
51
/*--------------------------------------------------------------------*/
52

Matthias Braun's avatar
Matthias Braun committed
53
#ifdef DEBUG_libfirm
Michael Beck's avatar
Michael Beck committed
54
/** Clear the outs of a node */
Michael Beck's avatar
Michael Beck committed
55
static void reset_outs(ir_node *node, void *unused) {
Matthias Braun's avatar
Matthias Braun committed
56
	(void) unused;
Michael Beck's avatar
Michael Beck committed
57
58
	node->out       = NULL;
	node->out_valid = 0;
59
}
Matthias Braun's avatar
Matthias Braun committed
60
#endif
61

62
/* returns the number of successors of the node: */
Michael Beck's avatar
Michael Beck committed
63
64
int get_irn_n_outs(ir_node *node) {
	assert(node && node->kind == k_ir_node);
65
#ifdef DEBUG_libfirm
Michael Beck's avatar
Michael Beck committed
66
	/* assert(node->out_valid); */
67
#endif /* defined DEBUG_libfirm */
Michael Beck's avatar
Michael Beck committed
68
	return PTR_TO_INT(node->out[0]);
69
70
71
}

/* Access successor n */
Michael Beck's avatar
Michael Beck committed
72
73
ir_node *get_irn_out(ir_node *node, int pos) {
	assert(pos >= 0 && pos < get_irn_n_outs(node));
74
#ifdef DEBUG_libfirm
Michael Beck's avatar
Michael Beck committed
75
	/* assert(node->out_valid); */
76
#endif /* defined DEBUG_libfirm */
Michael Beck's avatar
Michael Beck committed
77
return node->out[pos+1];
78
79
}

Michael Beck's avatar
Michael Beck committed
80
81
82
void set_irn_out(ir_node *node, int pos, ir_node *out) {
	assert(node && out);
	assert(pos >= 0 && pos < get_irn_n_outs(node));
83
#ifdef DEBUG_libfirm
Michael Beck's avatar
Michael Beck committed
84
	node->out_valid = 1;          /* assume that this function is used correctly */
85
#endif /* defined DEBUG_libfirm */
Michael Beck's avatar
Michael Beck committed
86
	node->out[pos+1] = out;
87
88
}

89
/* Return the number of control flow successors, ignore keep-alives. */
90
int get_Block_n_cfg_outs(ir_node *bl) {
Michael Beck's avatar
Michael Beck committed
91
92
	int i, n_cfg_outs = 0;
	assert(bl && is_Block(bl));
93
#ifdef DEBUG_libfirm
Michael Beck's avatar
Michael Beck committed
94
	assert(bl->out_valid);
95
#endif /* defined DEBUG_libfirm */
Michael Beck's avatar
Michael Beck committed
96
97
98
99
100
	for (i = 1; i <= PTR_TO_INT(bl->out[0]); ++i)
		if ((get_irn_mode(bl->out[i]) == mode_X) &&
		    (get_irn_op(bl->out[i]) != op_End))
			++n_cfg_outs;
	return n_cfg_outs;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
101
102
}

103
104
/* Return the number of control flow successors, honor keep-alives. */
int get_Block_n_cfg_outs_ka(ir_node *bl) {
Michael Beck's avatar
Michael Beck committed
105
106
	int i, n_cfg_outs = 0;
	assert(bl && is_Block(bl));
107
#ifdef DEBUG_libfirm
Michael Beck's avatar
Michael Beck committed
108
	assert(bl->out_valid);
109
#endif /* defined DEBUG_libfirm */
Michael Beck's avatar
Michael Beck committed
110
111
112
113
114
115
116
117
118
119
	for (i = 1; i <= PTR_TO_INT(bl->out[0]); ++i)
		if (get_irn_mode(bl->out[i]) == mode_X) {
			/* ignore End if we are in the Endblock */
			if (get_irn_op(bl->out[i]) == op_End &&
			    get_irn_n(bl->out[i], -1) == bl)
				continue;
			else
				++n_cfg_outs;
		}
	return n_cfg_outs;
120
}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
121

122
/* Access predecessor n, ignore keep-alives. */
123
ir_node *get_Block_cfg_out(ir_node *bl, int pos) {
Michael Beck's avatar
Michael Beck committed
124
125
	int i, out_pos = 0;
	assert(bl && is_Block(bl));
126
#ifdef DEBUG_libfirm
Michael Beck's avatar
Michael Beck committed
127
	assert (bl->out_valid);
128
#endif /* defined DEBUG_libfirm */
Michael Beck's avatar
Michael Beck committed
129
130
131
132
133
134
135
136
137
138
	for (i = 1; i <= PTR_TO_INT(bl->out[0]); ++i)
		if ((get_irn_mode(bl->out[i]) == mode_X)  &&
			(get_irn_op(bl->out[i]) != op_End)) {
			if (out_pos == pos) {
				ir_node *cfop = bl->out[i];
				return cfop->out[1];
			} else
				++out_pos;
		}
	return NULL;
Götz Lindenmaier's avatar
Götz Lindenmaier committed
139
140
}

141
142
/* Access predecessor n, honor keep-alives. */
ir_node *get_Block_cfg_out_ka(ir_node *bl, int pos) {
Michael Beck's avatar
Michael Beck committed
143
144
	int i, out_pos = 0;
	assert(bl && is_Block(bl));
145
#ifdef DEBUG_libfirm
Michael Beck's avatar
Michael Beck committed
146
	assert (bl->out_valid);
147
#endif /* defined DEBUG_libfirm */
Michael Beck's avatar
Michael Beck committed
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
	for (i = 1; i <= PTR_TO_INT(bl->out[0]); ++i)
		if (get_irn_mode(bl->out[i]) == mode_X) {
			/* ignore End if we are in the Endblock */
			if (get_irn_op(bl->out[i]) == op_End &&
				get_irn_n(bl->out[i], -1) == bl)
				continue;
			if (out_pos == pos) {
				ir_node *cfop = bl->out[i];
				/* handle keep-alive here */
				if (get_irn_op(cfop) == op_End)
					return get_irn_n(cfop, -1);
				return cfop->out[1];
			} else
				++out_pos;
		}
	return NULL;
164
165
}

Michael Beck's avatar
Michael Beck committed
166
static void irg_out_walk_2(ir_node *node, irg_walk_func *pre,
167
            irg_walk_func *post, void *env) {
Michael Beck's avatar
Michael Beck committed
168
169
	int     i, n;
	ir_node *succ;
170

Michael Beck's avatar
Michael Beck committed
171
172
	assert(node);
	assert(get_irn_visited(node) < get_irg_visited(current_ir_graph));
173

Michael Beck's avatar
Michael Beck committed
174
	set_irn_visited(node, get_irg_visited(current_ir_graph));
175

Michael Beck's avatar
Michael Beck committed
176
	if (pre) pre(node, env);
177

Michael Beck's avatar
Michael Beck committed
178
179
180
181
182
	for (i = 0, n = get_irn_n_outs(node); i < n; ++i) {
		succ = get_irn_out(node, i);
		if (get_irn_visited(succ) < get_irg_visited(current_ir_graph))
			irg_out_walk_2(succ, pre, post, env);
	}
183

Michael Beck's avatar
Michael Beck committed
184
	if (post) post(node, env);
185

Michael Beck's avatar
Michael Beck committed
186
	return;
187
188
189
}

void irg_out_walk(ir_node *node,
Michael Beck's avatar
Michael Beck committed
190
191
192
193
194
195
196
197
                  irg_walk_func *pre, irg_walk_func *post,
                  void *env) {
	assert(node);
	if (get_irg_outs_state(current_ir_graph) != outs_none) {
		inc_irg_visited (current_ir_graph);
		irg_out_walk_2(node, pre, post, env);
	}
	return;
198
199
}

Michael Beck's avatar
Michael Beck committed
200
static void irg_out_block_walk2(ir_node *bl,
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
                                irg_walk_func *pre, irg_walk_func *post,
                                void *env) {
	int i, n;

	if (Block_not_block_visited(bl)) {
		mark_Block_block_visited(bl);

		if (pre)
			pre(bl, env);

		for (i = 0, n =  get_Block_n_cfg_outs(bl); i < n; ++i) {
			/* find the corresponding predecessor block. */
			ir_node *pred = get_Block_cfg_out(bl, i);
			/* recursion */
			irg_out_block_walk2(pred, pre, post, env);
		}

		if (post)
			post(bl, env);
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
221
222
}

223
224
225
/* Walks only over Block nodes in the graph.  Has it's own visited
   flag, so that it can be interleaved with the other walker.         */
void irg_out_block_walk(ir_node *node,
Michael Beck's avatar
Michael Beck committed
226
227
                        irg_walk_func *pre, irg_walk_func *post,
                        void *env) {
Götz Lindenmaier's avatar
Götz Lindenmaier committed
228

Michael Beck's avatar
Michael Beck committed
229
	assert(is_Block(node) || (get_irn_mode(node) == mode_X));
Götz Lindenmaier's avatar
Götz Lindenmaier committed
230

Michael Beck's avatar
Michael Beck committed
231
	inc_irg_block_visited(current_ir_graph);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
232

Michael Beck's avatar
Michael Beck committed
233
234
	if (get_irn_mode(node) == mode_X)
		node = node->out[1];
Götz Lindenmaier's avatar
Götz Lindenmaier committed
235

Michael Beck's avatar
Michael Beck committed
236
	irg_out_block_walk2(node, pre, post, env);
237
238
}

Michael Beck's avatar
Michael Beck committed
239
/*--------------------------------------------------------------------*/
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
/** Building and Removing the out datasturcture                      **/
/**                                                                  **/
/** The outs of a graph are allocated in a single, large array.      **/
/** This allows to allocate and deallocate the memory for the outs   **/
/** on demand.  The large array is separated into many small ones    **/
/** for each node.  Only a single field to reference the out array   **/
/** is stored in each node and a field referencing the large out     **/
/** array in irgraph.  The 0 field of each out array contains the    **/
/** size of this array.  This saves memory in the irnodes themselves.**/
/** The construction does two passes over the graph.  The first pass **/
/** counts the overall number of outs and the outs of each node.  It **/
/** stores the outs of each node in the out reference of the node.   **/
/** Then the large array is allocated.  The second iteration chops   **/
/** the large array into smaller parts, sets the out edges and       **/
/** recounts the out edges.                                          **/
255
/** Removes Tuple nodes!                                             **/
Michael Beck's avatar
Michael Beck committed
256
/*--------------------------------------------------------------------*/
257
258


Michael Beck's avatar
Michael Beck committed
259
/** Returns the amount of out edges for not yet visited successors. */
260
static int _count_outs(ir_node *n) {
Michael Beck's avatar
Michael Beck committed
261
	int start, i, res, irn_arity;
262

Michael Beck's avatar
Michael Beck committed
263
264
	mark_irn_visited(n);
	n->out = (ir_node **) 1;     /* Space for array size. */
265

Michael Beck's avatar
Michael Beck committed
266
267
268
	start = is_Block(n) ? 0 : -1;
	irn_arity = get_irn_arity(n);
	res = irn_arity - start + 1;  /* --1 or --0; 1 for array size. */
Michael Beck's avatar
Michael Beck committed
269

Michael Beck's avatar
Michael Beck committed
270
271
272
273
	for (i = start; i < irn_arity; ++i) {
		/* Optimize Tuples.  They annoy if walking the cfg. */
		ir_node *pred = skip_Tuple(get_irn_n(n, i));
		set_irn_n(n, i, pred);
Michael Beck's avatar
Michael Beck committed
274

Michael Beck's avatar
Michael Beck committed
275
276
277
		/* count outs for successors */
		if (irn_not_visited(pred))
			res += _count_outs(pred);
278

Michael Beck's avatar
Michael Beck committed
279
280
281
282
		/* Count my outs */
		pred->out = (ir_node **)INT_TO_PTR(PTR_TO_INT(pred->out) + 1);
	}
	return res;
283
284
}

285
286

/** Returns the amount of out edges for not yet visited successors.
287
 *  This version handles some special nodes like irg_frame, irg_args etc.
288
289
 */
static int count_outs(ir_graph *irg) {
Michael Beck's avatar
Michael Beck committed
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
	ir_node *n;
	int res;

	inc_irg_visited(irg);
	res = _count_outs(get_irg_end(irg));

	/* now handle special nodes */
	n = get_irg_frame(irg);
	if (irn_not_visited(n)) {
		n->out = (ir_node **)1;
		++res;
	}

	n = get_irg_args(irg);
	if (irn_not_visited(n)) {
		n->out = (ir_node **)1;
		++res;
	}

	return res;
310
311
}

Michael Beck's avatar
Michael Beck committed
312
313
314
315
316
317
318
319
/**
 * Enter memory for the outs to a node.
 *
 * @param n      current node
 * @param free   current free address in the chunk allocated for the outs
 *
 * @return The next free address
 */
320
static ir_node **_set_out_edges(ir_node *n, ir_node **free) {
Michael Beck's avatar
Michael Beck committed
321
322
	int n_outs, start, i, irn_arity;
	ir_node *pred;
323

Michael Beck's avatar
Michael Beck committed
324
	set_irn_visited(n, get_irg_visited(current_ir_graph));
325

Michael Beck's avatar
Michael Beck committed
326
327
328
	/* Allocate my array */
	n_outs = PTR_TO_INT(n->out);
	n->out = free;
329
#ifdef DEBUG_libfirm
Michael Beck's avatar
Michael Beck committed
330
	n->out_valid = 1;
331
#endif /* defined DEBUG_libfirm */
Michael Beck's avatar
Michael Beck committed
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
	free += n_outs;
	/* We count the successors again, the space will be sufficient.
	   We use this counter to remember the position for the next back
	   edge. */
	n->out[0] = (ir_node *)0;

	start = is_Block(n) ? 0 : -1;
	irn_arity = get_irn_arity(n);

	for (i = start; i < irn_arity; ++i) {
		pred = get_irn_n(n, i);
		/* Recursion */
		if (get_irn_visited(pred) < get_irg_visited(current_ir_graph))
			free = _set_out_edges(pred, free);
		/* Remember our back edge */
		pred->out[get_irn_n_outs(pred)+1] = n;
		pred->out[0] = INT_TO_PTR(get_irn_n_outs(pred) + 1);
	}
	return free;
351
352
}

353
354
355
356
357
358
359
360
361
/**
 * Enter memory for the outs to a node. Handles special nodes
 *
 * @param irg    the graph
 * @param free   current free address in the chunk allocated for the outs
 *
 * @return The next free address
 */
static ir_node **set_out_edges(ir_graph *irg, ir_node **free) {
Michael Beck's avatar
Michael Beck committed
362
363
	ir_node *n, *special[2];
	int i, n_outs;
364

Michael Beck's avatar
Michael Beck committed
365
366
	inc_irg_visited(irg);
	free = _set_out_edges(get_irg_end(irg), free);
367

Michael Beck's avatar
Michael Beck committed
368
369
370
	/* handle special nodes */
	special[0] = get_irg_frame(irg);
	special[1] = get_irg_args(irg);
371

Michael Beck's avatar
Michael Beck committed
372
373
	for (i = 1; i >= 0; --i) {
		n = special[i];
374

Michael Beck's avatar
Michael Beck committed
375
376
377
		if (get_irn_visited(n) < get_irg_visited(current_ir_graph)) {
			n_outs = PTR_TO_INT(n->out);
			n->out = free;
378
#ifdef DEBUG_libfirm
Michael Beck's avatar
Michael Beck committed
379
			n->out_valid = 1;
380
#endif /* defined DEBUG_libfirm */
Michael Beck's avatar
Michael Beck committed
381
382
383
			free += n_outs;
		}
	}
384

Michael Beck's avatar
Michael Beck committed
385
	return free;
386
387
388
}


Michael Beck's avatar
Michael Beck committed
389
390
391
392
393
/**
 * We want that the out of ProjX from Start contains the next block at
 * position 1, the Start block at position 2.  This is necessary for
 * the out block walker.
 */
394
static INLINE void fix_start_proj(ir_graph *irg) {
Michael Beck's avatar
Michael Beck committed
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
	ir_node *proj    = NULL;
	ir_node *startbl = get_irg_start_block(irg);
	int i;

	if (get_Block_n_cfg_outs(startbl)) {
		for (i = get_irn_n_outs(startbl) - 1; i >= 0; --i)
			if (get_irn_mode(get_irn_out(startbl, i)) == mode_X) {
				proj = get_irn_out(startbl, i);
				break;
			}

		if (get_irn_out(proj, 0) == startbl) {
			assert(get_irn_n_outs(proj) == 2);
			set_irn_out(proj, 0, get_irn_out(proj, 1));
			set_irn_out(proj, 1, startbl);
		}
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
412
413
}

Michael Beck's avatar
Michael Beck committed
414
/* compute the outs for a given graph */
Götz Lindenmaier's avatar
Götz Lindenmaier committed
415
void compute_irg_outs(ir_graph *irg) {
Michael Beck's avatar
Michael Beck committed
416
417
418
	ir_graph *rem = current_ir_graph;
	int n_out_edges = 0;
	ir_node **end = NULL;         /* Only for debugging */
419

Michael Beck's avatar
Michael Beck committed
420
	current_ir_graph = irg;
421

Michael Beck's avatar
Michael Beck committed
422
423
	/* Update graph state */
	assert(get_irg_phase_state(current_ir_graph) != phase_building);
Michael Beck's avatar
Michael Beck committed
424

Michael Beck's avatar
Michael Beck committed
425
426
	if (current_ir_graph->outs_state != outs_none)
		free_irg_outs(current_ir_graph);
427

Michael Beck's avatar
Michael Beck committed
428
429
430
	/* This first iteration counts the overall number of out edges and the
	   number of out edges for each node. */
	n_out_edges = count_outs(irg);
431

Michael Beck's avatar
Michael Beck committed
432
433
	/* allocate memory for all out edges. */
	irg->outs = xcalloc(n_out_edges, sizeof(irg->outs[0]));
434
#ifdef DEBUG_libfirm
Michael Beck's avatar
Michael Beck committed
435
	irg->n_outs = n_out_edges;
436
#endif /* defined DEBUG_libfirm */
437

Michael Beck's avatar
Michael Beck committed
438
439
440
	/* The second iteration splits the irg->outs array into smaller arrays
	   for each node and writes the back edges into this array. */
	end = set_out_edges(irg, irg->outs);
441

Michael Beck's avatar
Michael Beck committed
442
443
	/* Check how much memory we have used */
	assert (end == (irg->outs + n_out_edges));
444

Michael Beck's avatar
Michael Beck committed
445
446
447
448
	/* We want that the out of ProjX from Start contains the next block at
	   position 1, the Start block at position 2.  This is necessary for
	   the out block walker. */
	fix_start_proj(irg);
Götz Lindenmaier's avatar
Götz Lindenmaier committed
449

Michael Beck's avatar
Michael Beck committed
450
451
	current_ir_graph->outs_state = outs_consistent;
	current_ir_graph = rem;
452
453
}

Michael Beck's avatar
Michael Beck committed
454
void assure_irg_outs(ir_graph *irg) {
Michael Beck's avatar
Michael Beck committed
455
456
	if (get_irg_outs_state(irg) != outs_consistent)
		compute_irg_outs(irg);
Michael Beck's avatar
Michael Beck committed
457
458
}

Götz Lindenmaier's avatar
Götz Lindenmaier committed
459
void compute_irp_outs(void) {
Michael Beck's avatar
Michael Beck committed
460
461
462
	int i;
	for (i = get_irp_n_irgs() -1; i >= 0; --i)
		compute_irg_outs(get_irp_irg(i));
Götz Lindenmaier's avatar
Götz Lindenmaier committed
463
}
Michael Beck's avatar
Michael Beck committed
464

Götz Lindenmaier's avatar
Götz Lindenmaier committed
465
void free_irp_outs(void) {
Michael Beck's avatar
Michael Beck committed
466
467
468
	int i;
	for (i = get_irp_n_irgs() -1; i >= 0; --i)
		free_irg_outs(get_irp_irg(i));
Götz Lindenmaier's avatar
Götz Lindenmaier committed
469
}
470
471


Michael Beck's avatar
Michael Beck committed
472
473
474
475
476
477
478
/*------------------------------------------------------------*
 *  This computes the outedges for in interprocedural graph.  *
 *  There is one quirk:                                       *
 *  The number of the outedges for each node is saved in      *
 *  the first member of the ir_node** array. Maybe we should  *
 *  change this to make it more portable...                   *
 *------------------------------------------------------------*/
479
480


Michael Beck's avatar
Michael Beck committed
481
482
483
484
485
/**
 * Inits the number of outedges for each node
 * before counting.
 */
static void init_count(ir_node * node, void *env) {
Matthias Braun's avatar
Matthias Braun committed
486
	(void) env;
Michael Beck's avatar
Michael Beck committed
487
	node->out = (ir_node **) 1; /* 1 for the array size */
488
}
489
490


Michael Beck's avatar
Michael Beck committed
491
492
493
494
495
/**
 * Adjusts the out edge count for its predecessors
 * and adds the current arity to the overall count,
 * which is saved in "env"
 */
Michael Beck's avatar
Michael Beck committed
496
497
498
static void node_arity_count(ir_node * node, void * env) {
	int *anz = (int *) env, arity, n_outs, i, start;
	ir_node *succ;
499

Michael Beck's avatar
Michael Beck committed
500
501
	arity = get_irn_arity(node);
	start = (is_Block(node)) ? 0 : -1;
502

Michael Beck's avatar
Michael Beck committed
503
504
	n_outs = 1 + arity + (-start);  // ((is_Block(node)) ? 0 : 1);   // Why + 1??
	*anz += n_outs;
505

Michael Beck's avatar
Michael Beck committed
506
507
508
509
	for(i = start; i < arity; i++) {
		succ = get_irn_n(node, i);
		succ->out = (ir_node **)INT_TO_PTR(PTR_TO_INT(succ->out) + 1);
	}
510
}
511

512

Michael Beck's avatar
Michael Beck committed
513
514
515
516
/*
 * Inits all nodes for setting the outedges
 * Returns the overall count of edges
 */
517
int count_ip_outs(void) {
Michael Beck's avatar
Michael Beck committed
518
	int res = 0;
519

Michael Beck's avatar
Michael Beck committed
520
	cg_walk(init_count, node_arity_count, &res);
521

Michael Beck's avatar
Michael Beck committed
522
	return(res);
523
524
}

Michael Beck's avatar
Michael Beck committed
525
static int dummy_count = 0, global_count; /* Only for debugging */
526

Michael Beck's avatar
Michael Beck committed
527
528
529
530
531
/**
 * For each node: Sets the pointer to array
 * in which the outedges are written later.
 * The current array start is transported in env
 */
532
static void set_array_pointer(ir_node *node, void *env) {
Michael Beck's avatar
Michael Beck committed
533
534
535
536
537
538
539
540
541
542
543
544
545
	int n_outs;
	ir_node ***free = (ir_node ***) env;

	/* Allocate my array */
	n_outs = PTR_TO_INT(node->out);  /* We wrote the count here in count_ip_outs */
	dummy_count += n_outs;
	assert(dummy_count <= global_count && "More outedges than initially counted!");
	node -> out = *free;
	*free = &((*free)[n_outs]);
	/* We count the successors again, the space will be sufficient.
	   We use this counter to remember the position for the next back
	   edge. */
	node -> out[0] = (ir_node *) 0;
546
547
548
}


Michael Beck's avatar
Michael Beck committed
549
550
551
552
/**
 * Adds an outedge from the predecessor to the
 * current node.
 */
Matthias Braun's avatar
Matthias Braun committed
553
static void set_out_pointer(ir_node * node, void *env) {
Michael Beck's avatar
Michael Beck committed
554
555
556
	int i, arity = get_irn_arity(node);
	ir_node *succ;
	int start = (!is_Block(node)) ? -1 : 0;
Matthias Braun's avatar
Matthias Braun committed
557
	(void) env;
Michael Beck's avatar
Michael Beck committed
558
559
560
561
562
563

	for (i = start; i < arity; ++i) {
		succ = get_irn_n(node, i);
		succ->out[get_irn_n_outs(succ)+1] = node;
		succ->out[0] = INT_TO_PTR(get_irn_n_outs(succ) + 1);
	}
564
}
565

566

Michael Beck's avatar
Michael Beck committed
567
568
569
/*
 * Sets the outedges for all nodes.
 */
Michael Beck's avatar
Michael Beck committed
570
571
572
void set_ip_outs(void) {
	ir_node **outedge_array = get_irp_ip_outedges();
	cg_walk(set_array_pointer, set_out_pointer, (void *) &outedge_array);
573
574
575
576
}



Michael Beck's avatar
Michael Beck committed
577
578
579
580
581
/*
 * Counts the outedges, allocates memory to save the
 * outedges and fills this outedge array in interprocedural
 * view!
 */
Götz Lindenmaier's avatar
bugfix    
Götz Lindenmaier committed
582
void compute_ip_outs(void) {
Michael Beck's avatar
Michael Beck committed
583
584
	int n_out_edges;
	ir_node **out_edges;
585

Michael Beck's avatar
Michael Beck committed
586
587
	assert(get_irp_ip_view_state() == ip_view_valid &&
	 "Cannot construct outs for invalid ip view.");
588

Michael Beck's avatar
Michael Beck committed
589
590
591
	if (irp->outs_state != outs_none) {
		free_ip_outs();
	}
Götz Lindenmaier's avatar
Götz Lindenmaier committed
592

Michael Beck's avatar
Michael Beck committed
593
594
595
596
	global_count = n_out_edges = count_ip_outs();
	out_edges = xcalloc(n_out_edges, sizeof(out_edges[0]));
	set_irp_ip_outedges(out_edges);
	set_ip_outs();
597
598
}

Michael Beck's avatar
Michael Beck committed
599
600
601
602
603
604
605
void free_ip_outs(void) {
	ir_node **out_edges = get_irp_ip_outedges();
	if (out_edges != NULL) {
		free(out_edges);
		set_irp_ip_outedges(NULL);
	}
	irp->outs_state = outs_none;
606
607
}

608

Götz Lindenmaier's avatar
Götz Lindenmaier committed
609
void free_irg_outs(ir_graph *irg) {
Michael Beck's avatar
Michael Beck committed
610
611
	/*   current_ir_graph->outs_state = outs_none; */
	irg->outs_state = outs_none;
612

Michael Beck's avatar
Michael Beck committed
613
	if (irg->outs) {
614
#ifdef DEBUG_libfirm
Michael Beck's avatar
Michael Beck committed
615
		memset(irg->outs, 0, irg->n_outs);
616
#endif /* defined DEBUG_libfirm */
Michael Beck's avatar
Michael Beck committed
617
618
		free(irg->outs);
		irg->outs = NULL;
619
#ifdef DEBUG_libfirm
Michael Beck's avatar
Michael Beck committed
620
		irg->n_outs = 0;
621
#endif /* defined DEBUG_libfirm */
Michael Beck's avatar
Michael Beck committed
622
	}
623

624
#ifdef DEBUG_libfirm
Michael Beck's avatar
Michael Beck committed
625
626
627
	/* when debugging, *always* reset all nodes' outs!  irg->outs might
	   have been lying to us */
	irg_walk_graph (irg, reset_outs, NULL, NULL);
628
#endif /* defined DEBUG_libfirm */
629
}