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