- add support for statistics and merge debug info
[libfirm] / ir / ana / irbackedge.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     Access function for backedges.
23  * @author    Goetz Lindenmaier
24  * @date      7.2002
25  * @version   $Id$
26  */
27 #include "config.h"
28
29 #include "irnode_t.h"
30 #include "irgraph_t.h"
31 #include "array.h"
32 #include "irbackedge_t.h"
33 #include "raw_bitset.h"
34
35 /*--------------------------------------------------------------------*/
36 /* Backedge information.                                              */
37 /*--------------------------------------------------------------------*/
38
39
40 /**
41  * Returns backarray if the node can have backedges, else returns
42  * NULL.
43  *
44  * Does not assert whether the backarray is correct -- use
45  * very careful!
46  */
47 static unsigned *mere_get_backarray(ir_node *n) {
48         switch (get_irn_opcode(n)) {
49         case iro_Block:
50                 if (!get_Block_matured(n)) return NULL;
51                 if (get_interprocedural_view() && n->attr.block.in_cg) {
52                         assert(n->attr.block.cg_backedge && "backedge array not allocated!");
53                         return n->attr.block.cg_backedge;
54                 } else {
55                         assert(n->attr.block.backedge && "backedge array not allocated!");
56                         return n->attr.block.backedge;
57                 }
58                 break;
59         case iro_Phi:
60                 assert(n->attr.phi.u.backedge && "backedge array not allocated!");
61                 return n->attr.phi.u.backedge;
62                 break;
63         case iro_Filter:
64                 if (get_interprocedural_view()) {
65                         assert(n->attr.filter.backedge && "backedge array not allocated!");
66                         return n->attr.filter.backedge;
67                 }
68                 break;
69         default: ;
70         }
71         return NULL;
72 }
73
74 /**
75  * Returns backarray if the node can have backedges, else returns
76  * NULL.
77  */
78 static unsigned *get_backarray(ir_node *n) {
79         unsigned *ba = mere_get_backarray(n);
80
81 #ifndef NDEBUG
82         if (ba) {
83                 int bal = rbitset_size(ba);  /* avoid macro expansion in assertion. */
84                 int inl = get_irn_arity(n);
85                 assert(bal == inl && "backedge array with faulty length");
86         }
87 #endif
88
89         return ba;
90 }
91
92 #ifndef NDEBUG
93 /**
94  * Returns non-zero if node has no backarray, or
95  *                  if size of backarray == size of in array.
96  */
97 static int legal_backarray(ir_node *n) {
98         unsigned *ba = mere_get_backarray(n);
99         if (ba && (rbitset_size(ba) != (unsigned) get_irn_arity(n)))
100                 return 0;
101         return 1;
102 }
103 #endif
104
105 void fix_backedges(struct obstack *obst, ir_node *n) {
106         unsigned *arr = mere_get_backarray(n);
107         ir_opcode opc;
108         int arity;
109
110         if (! arr)
111                 return;
112
113         arity = get_irn_arity(n);
114         if (rbitset_size(arr) != (unsigned) arity) {
115                 arr = new_backedge_arr(obst, arity);
116
117                 opc = get_irn_opcode(n);
118                 if (opc == iro_Phi)
119                         n->attr.phi.u.backedge = arr;
120                 else if (opc == iro_Block) {
121                         if (!get_interprocedural_view())
122                                 n->attr.block.backedge = arr;
123                         else
124                                 n->attr.block.cg_backedge = arr;
125                 }
126                 else if (opc == iro_Filter)
127                         n->attr.filter.backedge = arr;
128         }
129
130         assert(legal_backarray(n));
131 }
132
133 #ifdef INTERPROCEDURAL_VIEW
134 int is_inter_backedge(ir_node *n, int pos) {
135         int res;
136         int rem = get_interprocedural_view();
137         set_interprocedural_view(0);
138         res = is_backedge(n, pos);
139         set_interprocedural_view(rem);
140         return res;
141 }
142
143 int is_intra_backedge(ir_node *n, int pos) {
144         int res;
145         int rem = get_interprocedural_view();
146         set_interprocedural_view(1);
147         res = is_backedge(n, pos);
148         set_interprocedural_view(rem);
149         return res;
150 }
151 #endif
152
153
154 /* Returns non-zero if the predecessor pos is a backedge. */
155 int is_backedge(ir_node *n, int pos) {
156         unsigned *ba = get_backarray(n);
157         if (ba)
158                 return rbitset_is_set(ba, pos);
159         return 0;
160 }
161
162 /* Remarks that edge pos is a backedge. */
163 void set_backedge(ir_node *n, int pos) {
164         unsigned *ba = get_backarray(n);
165         assert(ba && "can only set backedges at Phi, Filter, Block nodes.");
166         rbitset_set(ba, pos);
167 }
168
169 /* Remarks that edge pos is a backedge. */
170 void set_not_backedge(ir_node *n, int pos) {
171         unsigned *ba = get_backarray(n);
172         assert(ba && "can only set backedges at Phi, Filter, Block nodes.");
173         rbitset_clear(ba, pos);
174 }
175
176 /* Returns non-zero if n has backedges. */
177 int has_backedges(ir_node *n) {
178         unsigned *ba = get_backarray(n);
179         if (ba) {
180                 int arity = get_irn_arity(n);
181                 return !rbitset_is_empty(ba, arity);
182         }
183         return 0;
184 }
185
186 /** Sets all backedge information to zero. */
187 void clear_backedges(ir_node *n) {
188         int i, arity;
189         unsigned *ba;
190 #ifdef INTERPROCEDURAL_VIEW
191         int rem = get_interprocedural_view();
192         set_interprocedural_view(0);
193 #endif
194         ba = get_backarray(n);
195         if (ba) {
196                 arity = get_irn_arity(n);
197                 for (i = 0; i < arity; i++)
198                         rbitset_clear(ba, i);
199         }
200 #ifdef INTERPROCEDURAL_VIEW
201         set_interprocedural_view(1);
202         ba = get_backarray (n);
203         if (ba) {
204                 arity = get_irn_arity(n);
205                 for (i = 0; i < arity; i++)
206                         rbitset_clear(ba, i);
207         }
208         set_interprocedural_view(rem);
209 #endif
210 }
211
212 /* Allocate a new backedge array on the obstack for given size. */
213 unsigned *new_backedge_arr(struct obstack *obst, unsigned size) {
214         return rbitset_w_size_obstack_alloc(obst, size);
215 }
216
217 /* TODO: add an ir_op operation */
218 void new_backedge_info(ir_node *n) {
219         switch (get_irn_opcode(n)) {
220         case iro_Block:
221                 n->attr.block.cg_backedge = NULL;
222                 n->attr.block.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
223                 break;
224         case iro_Phi:
225                 n->attr.phi.u.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
226                 break;
227         case iro_Filter:
228                 n->attr.filter.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
229                 break;
230         default: ;
231         }
232 }