825bd31928e9cf759974449212f50d2648447967
[libfirm] / ir / ana / irouts.c
1 /*
2  * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
3  *
4  * This file is part of libFirm.
5  *
6  * This file may be distributed and/or modified under the terms of the
7  * GNU General Public License version 2 as published by the Free Software
8  * Foundation and appearing in the file LICENSE.GPL included in the
9  * packaging of this file.
10  *
11  * Licensees holding valid libFirm Professional Edition licenses may use
12  * this file in accordance with the libFirm Commercial License.
13  * Agreement provided with the Software.
14  *
15  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE.
18  */
19
20 /**
21  * @file
22  * @brief    Compute and access out edges (also called def-use edges).
23  * @author   Goetz Lindenmaier, Michael Beck
24  * @date     1.2002
25  * @version  $Id$
26  */
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #ifdef HAVE_STRING_H
32 #include <string.h>
33 #endif
34
35 #include "xmalloc.h"
36 #include "irouts.h"
37 #include "irnode_t.h"
38 #include "irgraph_t.h"
39 #include "irprog_t.h"
40 #include "irgwalk.h"
41 #include "irtools.h"
42
43 #ifdef DEBUG_libfirm
44 /* Note:  ir_node.out_valid and ir_graph.n_outs are only present when DEBUG_libfirm is defined */
45 /* Accesses to out_valid and n_outs are fenced out to avoid breakage
46    when compiling with neither DEBUG_libfirm or NDEBUG defined */
47 #endif /* defined DEBUG_libfirm */
48
49 /*--------------------------------------------------------------------*/
50 /** Accessing the out datastructures                                 **/
51 /*--------------------------------------------------------------------*/
52
53 #ifdef DEBUG_libfirm
54 /** Clear the outs of a node */
55 static void reset_outs(ir_node *node, void *unused) {
56         (void) unused;
57         node->out       = NULL;
58         node->out_valid = 0;
59 }
60 #endif
61
62 int get_irn_outs_computed(const ir_node *node)
63 {
64         return node->out != NULL;
65 }
66
67 /* returns the number of successors of the node: */
68 int get_irn_n_outs(ir_node *node) {
69         assert(node && node->kind == k_ir_node);
70 #ifdef DEBUG_libfirm
71         /* assert(node->out_valid); */
72 #endif /* defined DEBUG_libfirm */
73         /* we misuse the first for the size info of the out array */
74         return node->out[0].pos;
75 }
76
77 /* Access successor n */
78 ir_node *get_irn_out(ir_node *def, int pos) {
79         assert(pos >= 0 && pos < get_irn_n_outs(def));
80 #ifdef DEBUG_libfirm
81         /* assert(def->out_valid); */
82 #endif /* defined DEBUG_libfirm */
83         return def->out[pos+1].use;
84 }
85
86 /* Access successor n */
87 ir_node *get_irn_out_ex(ir_node *def, int pos, int *in_pos) {
88         assert(pos >= 0 && pos < get_irn_n_outs(def));
89 #ifdef DEBUG_libfirm
90         /* assert(def->out_valid); */
91 #endif /* defined DEBUG_libfirm */
92         *in_pos = def->out[pos+1].pos;
93         return def->out[pos+1].use;
94 }
95
96 void set_irn_out(ir_node *def, int pos, ir_node *use, int in_pos) {
97         assert(def && use);
98         assert(pos >= 0 && pos < get_irn_n_outs(def));
99 #ifdef DEBUG_libfirm
100         def->out_valid = 1;          /* assume that this function is used correctly */
101 #endif /* defined DEBUG_libfirm */
102         def->out[pos+1].use = use;
103         def->out[pos+1].pos = in_pos;
104 }
105
106 /* Return the number of control flow successors, ignore keep-alives. */
107 int get_Block_n_cfg_outs(ir_node *bl) {
108         int i, n_cfg_outs = 0;
109         assert(bl && is_Block(bl));
110 #ifdef DEBUG_libfirm
111         assert(bl->out_valid);
112 #endif /* defined DEBUG_libfirm */
113         for (i = 1; i <= bl->out[0].pos; ++i) {
114                 ir_node *succ = bl->out[i].use;
115                 if (get_irn_mode(succ) == mode_X && !is_End(succ))
116                         n_cfg_outs += succ->out[0].pos;
117         }
118         return n_cfg_outs;
119 }
120
121 /* Return the number of control flow successors, honor keep-alives. */
122 int get_Block_n_cfg_outs_ka(ir_node *bl) {
123         int i, n_cfg_outs = 0;
124         assert(bl && is_Block(bl));
125 #ifdef DEBUG_libfirm
126         assert(bl->out_valid);
127 #endif /* defined DEBUG_libfirm */
128         for (i = 1; i <= bl->out[0].pos; ++i) {
129                 ir_node *succ = bl->out[i].use;
130                 if (get_irn_mode(succ) == mode_X) {
131
132                         if (is_End(succ)) {
133                                 /* ignore End if we are in the Endblock */
134                                 if (get_nodes_block(succ) == bl)
135                                         continue;
136                                 else /* count Keep-alive as one */
137                                         n_cfg_outs += 1;
138                         } else
139                                 n_cfg_outs += succ->out[0].pos;
140                 }
141         }
142         return n_cfg_outs;
143 }
144
145 /* Access predecessor n, ignore keep-alives. */
146 ir_node *get_Block_cfg_out(ir_node *bl, int pos) {
147         int i;
148         assert(bl && is_Block(bl));
149 #ifdef DEBUG_libfirm
150         assert(bl->out_valid);
151 #endif /* defined DEBUG_libfirm */
152         for (i = 1; i <= bl->out[0].pos; ++i) {
153                 ir_node *succ = bl->out[i].use;
154                 if (get_irn_mode(succ) == mode_X && !is_End(succ)) {
155                         int n_outs = succ->out[0].pos;
156                         if (pos < n_outs)
157                                 return succ->out[pos + 1].use;
158                         else
159                                 pos -= n_outs;
160                 }
161         }
162         return NULL;
163 }
164
165 /* Access predecessor n, honor keep-alives. */
166 ir_node *get_Block_cfg_out_ka(ir_node *bl, int pos) {
167         int i, n_outs;
168         assert(bl && is_Block(bl));
169 #ifdef DEBUG_libfirm
170         assert (bl->out_valid);
171 #endif /* defined DEBUG_libfirm */
172         for (i = 1; i <= bl->out[0].pos; ++i) {
173                 ir_node *succ = bl->out[i].use;
174                 if (get_irn_mode(succ) == mode_X) {
175                         if (is_End(succ)) {
176                                 ir_node *end_bl = get_nodes_block(succ);
177                                 if (end_bl == bl) {
178                                         /* ignore End if we are in the Endblock */
179                                         continue;
180                                 }
181                                 if (pos == 0) {
182                                         /* handle keep-alive here: return the Endblock instead of the End node */
183                                         return end_bl;
184                                 } else
185                                         --pos;
186                         } else {
187                                 n_outs = succ->out[0].pos;
188                                 if (pos < n_outs)
189                                         return succ->out[pos + 1].use;
190                                 else
191                                         pos -= n_outs;
192                         }
193                 }
194         }
195         return NULL;
196 }
197
198 static void irg_out_walk_2(ir_node *node, irg_walk_func *pre,
199             irg_walk_func *post, void *env) {
200         int     i, n;
201         ir_node *succ;
202
203         assert(node);
204         assert(get_irn_visited(node) < get_irg_visited(current_ir_graph));
205
206         set_irn_visited(node, get_irg_visited(current_ir_graph));
207
208         if (pre) pre(node, env);
209
210         for (i = 0, n = get_irn_n_outs(node); i < n; ++i) {
211                 succ = get_irn_out(node, i);
212                 if (get_irn_visited(succ) < get_irg_visited(current_ir_graph))
213                         irg_out_walk_2(succ, pre, post, env);
214         }
215
216         if (post) post(node, env);
217
218         return;
219 }
220
221 void irg_out_walk(ir_node *node,
222                   irg_walk_func *pre, irg_walk_func *post,
223                   void *env) {
224         assert(node);
225         if (get_irg_outs_state(current_ir_graph) != outs_none) {
226                 inc_irg_visited (current_ir_graph);
227                 irg_out_walk_2(node, pre, post, env);
228         }
229         return;
230 }
231
232 static void irg_out_block_walk2(ir_node *bl,
233                                 irg_walk_func *pre, irg_walk_func *post,
234                                 void *env) {
235         int i, n;
236
237         if (Block_not_block_visited(bl)) {
238                 mark_Block_block_visited(bl);
239
240                 if (pre)
241                         pre(bl, env);
242
243                 for (i = 0, n =  get_Block_n_cfg_outs(bl); i < n; ++i) {
244                         /* find the corresponding predecessor block. */
245                         ir_node *pred = get_Block_cfg_out(bl, i);
246                         /* recursion */
247                         irg_out_block_walk2(pred, pre, post, env);
248                 }
249
250                 if (post)
251                         post(bl, env);
252         }
253 }
254
255 /* Walks only over Block nodes in the graph.  Has it's own visited
256    flag, so that it can be interleaved with the other walker.         */
257 void irg_out_block_walk(ir_node *node,
258                         irg_walk_func *pre, irg_walk_func *post,
259                         void *env) {
260
261         assert(is_Block(node) || (get_irn_mode(node) == mode_X));
262
263         inc_irg_block_visited(current_ir_graph);
264
265         if (get_irn_mode(node) == mode_X) {
266                 int i, n;
267
268                 for (i = 0, n = get_irn_n_outs(node); i < n; ++i) {
269                         ir_node *succ = get_irn_out(node, i);
270                         if (get_irn_visited(succ) < get_irg_visited(current_ir_graph))
271                                 irg_out_walk_2(succ, pre, post, env);
272                 }
273         }
274         else {
275                 irg_out_block_walk2(node, pre, post, env);
276         }
277 }
278
279 /*--------------------------------------------------------------------*/
280 /** Building and Removing the out datastructure                      **/
281 /**                                                                  **/
282 /** The outs of a graph are allocated in a single, large array.      **/
283 /** This allows to allocate and deallocate the memory for the outs   **/
284 /** on demand.  The large array is separated into many small ones    **/
285 /** for each node.  Only a single field to reference the out array   **/
286 /** is stored in each node and a field referencing the large out     **/
287 /** array in irgraph.  The 0 field of each out array contains the    **/
288 /** size of this array.  This saves memory in the irnodes themselves.**/
289 /** The construction does two passes over the graph.  The first pass **/
290 /** counts the overall number of outs and the outs of each node.  It **/
291 /** stores the outs of each node in the out reference of the node.   **/
292 /** Then the large array is allocated.  The second iteration chops   **/
293 /** the large array into smaller parts, sets the out edges and       **/
294 /** recounts the out edges.                                          **/
295 /** Removes Tuple nodes!                                             **/
296 /*--------------------------------------------------------------------*/
297
298
299 /** Returns the amount of out edges for not yet visited successors. */
300 static int _count_outs(ir_node *n) {
301         int start, i, res, irn_arity;
302
303         mark_irn_visited(n);
304         n->out = INT_TO_PTR(1);     /* Space for array size. */
305
306         start = is_Block(n) ? 0 : -1;
307         irn_arity = get_irn_arity(n);
308         res = irn_arity - start + 1;  /* --1 or --0; 1 for array size. */
309
310         for (i = start; i < irn_arity; ++i) {
311                 /* Optimize Tuples.  They annoy if walking the cfg. */
312                 ir_node *pred = skip_Tuple(get_irn_n(n, i));
313                 set_irn_n(n, i, pred);
314
315                 /* count Def-Use edges for predecessors */
316                 if (irn_not_visited(pred))
317                         res += _count_outs(pred);
318
319                 /*count my Def-Use edges */
320                 pred->out = INT_TO_PTR(PTR_TO_INT(pred->out) + 1);
321         }
322         return res;
323 }
324
325
326 /** Returns the amount of out edges for not yet visited successors.
327  *  This version handles some special nodes like irg_frame, irg_args etc.
328  */
329 static int count_outs(ir_graph *irg) {
330         ir_node *n;
331         int     i, res;
332
333         inc_irg_visited(irg);
334         res = _count_outs(get_irg_end(irg));
335
336         /* Now handle anchored nodes. We need the out count of those
337            even if they are not visible. */
338         for (i = anchor_last - 1; i >= 0; --i) {
339                 n = get_irg_anchor(irg, i);
340                 if (irn_not_visited(n)) {
341                         mark_irn_visited(n);
342
343                         n->out = INT_TO_PTR(1);
344                         ++res;
345                 }
346         }
347         return res;
348 }
349
350 /**
351  * Enter memory for the outs to a node.
352  *
353  * @param use    current node
354  * @param free   current free address in the chunk allocated for the outs
355  *
356  * @return The next free address
357  */
358 static ir_def_use_edge *_set_out_edges(ir_node *use, ir_def_use_edge *free) {
359         int     n_outs, start, i, irn_arity, pos;
360
361         mark_irn_visited(use);
362
363         /* Allocate my array */
364         n_outs = PTR_TO_INT(use->out);
365         use->out = free;
366 #ifdef DEBUG_libfirm
367         use->out_valid = 1;
368 #endif /* defined DEBUG_libfirm */
369         free += n_outs;
370         /* We count the successors again, the space will be sufficient.
371            We use this counter to remember the position for the next back
372            edge. */
373         use->out[0].pos = 0;
374
375         start = is_Block(use) ? 0 : -1;
376         irn_arity = get_irn_arity(use);
377
378         for (i = start; i < irn_arity; ++i) {
379                 ir_node *def = get_irn_n(use, i);
380
381                 /* Recursion */
382                 if (irn_not_visited(def))
383                         free = _set_out_edges(def, free);
384
385                 /* Remember this Def-Use edge */
386                 pos = def->out[0].pos + 1;
387                 def->out[pos].use = use;
388                 def->out[pos].pos = i;
389
390                 /* increase the number of Def-Use edges so far */
391                 def->out[0].pos = pos;
392         }
393         return free;
394 }
395
396 /**
397  * Enter memory for the outs to a node. Handles special nodes
398  *
399  * @param irg    the graph
400  * @param free   current free address in the chunk allocated for the outs
401  *
402  * @return The next free address
403  */
404 static ir_def_use_edge *set_out_edges(ir_graph *irg, ir_def_use_edge *free) {
405         ir_node *n;
406         int     i, n_outs;
407
408         inc_irg_visited(irg);
409         free = _set_out_edges(get_irg_end(irg), free);
410
411         /* handle anchored nodes */
412         for (i = anchor_last - 1; i >= 0; --i) {
413                 n = get_irg_anchor(irg, i);
414                 if (irn_not_visited(n)) {
415                         mark_irn_visited(n);
416
417                         n_outs = PTR_TO_INT(n->out);
418                         n->out = free;
419 #ifdef DEBUG_libfirm
420                         n->out_valid = 1;
421 #endif /* defined DEBUG_libfirm */
422                         free += n_outs;
423                 }
424         }
425
426         return free;
427 }
428
429
430 /**
431  * We want that the out of ProjX from Start contains the next block at
432  * position 1, the Start block at position 2.  This is necessary for
433  * the out block walker.
434  */
435 static INLINE void fix_start_proj(ir_graph *irg) {
436         ir_node *proj    = NULL;
437         ir_node *irn;
438         ir_node *startbl = get_irg_start_block(irg);
439         int     i, block_pos, other_pos;
440
441         if (get_Block_n_cfg_outs(startbl)) {
442                 for (i = get_irn_n_outs(startbl) - 1; i >= 0; --i)
443                         if (get_irn_mode(get_irn_out(startbl, i)) == mode_X) {
444                                 proj = get_irn_out(startbl, i);
445                                 break;
446                         }
447
448                 if (get_irn_out_ex(proj, 0, &block_pos) == startbl) {
449                         assert(get_irn_n_outs(proj) == 2);
450                         irn = get_irn_out_ex(proj, 1, &other_pos);
451                         set_irn_out(proj, 0, irn, other_pos);
452                         set_irn_out(proj, 1, startbl, block_pos);
453                 }
454         }
455 }
456
457 /* compute the outs for a given graph */
458 void compute_irg_outs(ir_graph *irg) {
459         ir_graph        *rem = current_ir_graph;
460         int             n_out_edges = 0;
461         ir_def_use_edge *end = NULL;         /* Only for debugging */
462
463         current_ir_graph = irg;
464
465         /* Update graph state */
466         assert(get_irg_phase_state(current_ir_graph) != phase_building);
467
468         if (current_ir_graph->outs_state != outs_none)
469                 free_irg_outs(current_ir_graph);
470
471         /* This first iteration counts the overall number of out edges and the
472            number of out edges for each node. */
473         n_out_edges = count_outs(irg);
474
475         /* allocate memory for all out edges. */
476         irg->outs = xcalloc(n_out_edges, sizeof(irg->outs[0]));
477 #ifdef DEBUG_libfirm
478         irg->n_outs = n_out_edges;
479 #endif /* defined DEBUG_libfirm */
480
481         /* The second iteration splits the irg->outs array into smaller arrays
482            for each node and writes the back edges into this array. */
483         end = set_out_edges(irg, irg->outs);
484
485         /* Check how much memory we have used */
486         assert (end == (irg->outs + n_out_edges));
487
488         /* We want that the out of ProjX from Start contains the next block at
489            position 1, the Start block at position 2.  This is necessary for
490            the out block walker. */
491         fix_start_proj(irg);
492
493         current_ir_graph->outs_state = outs_consistent;
494         current_ir_graph = rem;
495 }
496
497 void assure_irg_outs(ir_graph *irg) {
498         if (get_irg_outs_state(irg) != outs_consistent)
499                 compute_irg_outs(irg);
500 }
501
502 void compute_irp_outs(void) {
503         int i;
504         for (i = get_irp_n_irgs() -1; i >= 0; --i)
505                 compute_irg_outs(get_irp_irg(i));
506 }
507
508 void free_irp_outs(void) {
509         int i;
510         for (i = get_irp_n_irgs() -1; i >= 0; --i)
511                 free_irg_outs(get_irp_irg(i));
512 }
513
514
515 /*------------------------------------------------------------*
516  *  This computes the outedges for in interprocedural graph.  *
517  *  There is one quirk:                                       *
518  *  The number of the outedges for each node is saved in      *
519  *  the first member of the ir_node** array. Maybe we should  *
520  *  change this to make it more portable...                   *
521  *------------------------------------------------------------*/
522
523
524 #ifdef INTERPROCEDURAL_VIEW
525 /**
526  * Inits the number of outedges for each node
527  * before counting.
528  */
529 static void init_count(ir_node * node, void *env) {
530         (void) env;
531         node->out = (ir_node **) 1; /* 1 for the array size */
532 }
533
534
535 /**
536  * Adjusts the out edge count for its predecessors
537  * and adds the current arity to the overall count,
538  * which is saved in "env"
539  */
540 static void node_arity_count(ir_node * node, void * env) {
541         int *anz = (int *) env, arity, n_outs, i, start;
542         ir_node *succ;
543
544         arity = get_irn_arity(node);
545         start = (is_Block(node)) ? 0 : -1;
546
547         n_outs = 1 + arity + (-start);  // ((is_Block(node)) ? 0 : 1);   // Why + 1??
548         *anz += n_outs;
549
550         for(i = start; i < arity; i++) {
551                 succ = get_irn_n(node, i);
552                 succ->out = (ir_node **)INT_TO_PTR(PTR_TO_INT(succ->out) + 1);
553         }
554 }
555
556 /*
557  * Inits all nodes for setting the outedges
558  * Returns the overall count of edges
559  */
560 int count_ip_outs(void) {
561         int res = 0;
562
563         cg_walk(init_count, node_arity_count, &res);
564
565         return(res);
566 }
567
568 static int dummy_count = 0, global_count; /* Only for debugging */
569
570 /**
571  * For each node: Sets the pointer to array
572  * in which the outedges are written later.
573  * The current array start is transported in env
574  */
575 static void set_array_pointer(ir_node *node, void *env) {
576         int n_outs;
577         ir_node ***free = (ir_node ***) env;
578
579         /* Allocate my array */
580         n_outs = PTR_TO_INT(node->out);  /* We wrote the count here in count_ip_outs */
581         dummy_count += n_outs;
582         assert(dummy_count <= global_count && "More outedges than initially counted!");
583         node -> out = *free;
584         *free = &((*free)[n_outs]);
585         /* We count the successors again, the space will be sufficient.
586            We use this counter to remember the position for the next back
587            edge. */
588         node -> out[0] = (ir_node *) 0;
589 }
590
591
592 /**
593  * Adds an outedge from the predecessor to the
594  * current node.
595  */
596 static void set_out_pointer(ir_node * node, void *env) {
597         int i, arity = get_irn_arity(node);
598         ir_node *succ;
599         int start = (!is_Block(node)) ? -1 : 0;
600         (void) env;
601
602         for (i = start; i < arity; ++i) {
603                 succ = get_irn_n(node, i);
604                 succ->out[get_irn_n_outs(succ)+1] = node;
605                 succ->out[0] = INT_TO_PTR(get_irn_n_outs(succ) + 1);
606         }
607 }
608
609
610 /*
611  * Sets the outedges for all nodes.
612  */
613 void set_ip_outs(void) {
614         ir_node **outedge_array = get_irp_ip_outedges();
615         cg_walk(set_array_pointer, set_out_pointer, (void *) &outedge_array);
616 }
617
618
619
620 /*
621  * Counts the outedges, allocates memory to save the
622  * outedges and fills this outedge array in interprocedural
623  * view!
624  */
625 void compute_ip_outs(void) {
626         int n_out_edges;
627         ir_node **out_edges;
628
629         assert(get_irp_ip_view_state() == ip_view_valid &&
630          "Cannot construct outs for invalid ip view.");
631
632         if (irp->outs_state != outs_none) {
633                 free_ip_outs();
634         }
635
636         global_count = n_out_edges = count_ip_outs();
637         out_edges = xcalloc(n_out_edges, sizeof(out_edges[0]));
638         set_irp_ip_outedges(out_edges);
639         set_ip_outs();
640 }
641
642 void free_ip_outs(void) {
643         ir_node **out_edges = get_irp_ip_outedges();
644         if (out_edges != NULL) {
645                 free(out_edges);
646                 set_irp_ip_outedges(NULL);
647         }
648         irp->outs_state = outs_none;
649 }
650 #endif
651
652
653 void free_irg_outs(ir_graph *irg) {
654         /*   current_ir_graph->outs_state = outs_none; */
655         irg->outs_state = outs_none;
656
657         if (irg->outs) {
658 #ifdef DEBUG_libfirm
659                 memset(irg->outs, 0, irg->n_outs);
660 #endif /* defined DEBUG_libfirm */
661                 free(irg->outs);
662                 irg->outs = NULL;
663 #ifdef DEBUG_libfirm
664                 irg->n_outs = 0;
665 #endif /* defined DEBUG_libfirm */
666         }
667
668 #ifdef DEBUG_libfirm
669         /* when debugging, *always* reset all nodes' outs!  irg->outs might
670            have been lying to us */
671         irg_walk_graph (irg, reset_outs, NULL, NULL);
672 #endif /* defined DEBUG_libfirm */
673 }