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