Do not mark the transformed as visited. It makes no sense at all.
[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 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "irnode_t.h"
32 #include "irgraph_t.h"
33 #include "array.h"
34 #include "irbackedge_t.h"
35 #include "raw_bitset.h"
36
37 /*--------------------------------------------------------------------*/
38 /* Backedge information.                                              */
39 /*--------------------------------------------------------------------*/
40
41
42 /**
43  * Returns backarray if the node can have backedges, else returns
44  * NULL.
45  *
46  * Does not assert whether the backarray is correct -- use
47  * very careful!
48  */
49 static unsigned *mere_get_backarray(ir_node *n) {
50         switch (get_irn_opcode(n)) {
51         case iro_Block:
52                 if (!get_Block_matured(n)) return NULL;
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                 } else {
57                         assert(n->attr.block.backedge && "backedge array not allocated!");
58                         return n->attr.block.backedge;
59                 }
60                 break;
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                 if (get_interprocedural_view()) {
67                         assert(n->attr.filter.backedge && "backedge array not allocated!");
68                         return n->attr.filter.backedge;
69                 }
70                 break;
71         default: ;
72         }
73         return NULL;
74 }
75
76 /**
77  * Returns backarray if the node can have backedges, else returns
78  * NULL.
79  */
80 static unsigned *get_backarray(ir_node *n) {
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         unsigned *ba = mere_get_backarray(n);
101         if (ba && (rbitset_size(ba) != (unsigned) get_irn_arity(n)))
102                 return 0;
103         return 1;
104 }
105 #endif
106
107 void fix_backedges(struct obstack *obst, ir_node *n) {
108         unsigned *arr = mere_get_backarray(n);
109         ir_opcode opc;
110         int arity;
111
112         if (! arr)
113                 return;
114
115         arity = get_irn_arity(n);
116         if (rbitset_size(arr) != (unsigned) arity) {
117                 arr = new_backedge_arr(obst, arity);
118
119                 opc = get_irn_opcode(n);
120                 if (opc == iro_Phi)
121                         n->attr.phi.u.backedge = arr;
122                 else if (opc == iro_Block) {
123                         if (!get_interprocedural_view())
124                                 n->attr.block.backedge = arr;
125                         else
126                                 n->attr.block.cg_backedge = arr;
127                 }
128                 else if (opc == iro_Filter)
129                         n->attr.filter.backedge = arr;
130         }
131
132         assert(legal_backarray(n));
133 }
134
135 #ifdef INTERPROCEDURAL_VIEW
136 int is_inter_backedge(ir_node *n, int pos) {
137         int res;
138         int rem = get_interprocedural_view();
139         set_interprocedural_view(0);
140         res = is_backedge(n, pos);
141         set_interprocedural_view(rem);
142         return res;
143 }
144
145 int is_intra_backedge(ir_node *n, int pos) {
146         int res;
147         int rem = get_interprocedural_view();
148         set_interprocedural_view(1);
149         res = is_backedge(n, pos);
150         set_interprocedural_view(rem);
151         return res;
152 }
153 #endif
154
155
156 /* Returns non-zero if the predecessor pos is a backedge. */
157 int is_backedge(ir_node *n, int pos) {
158         unsigned *ba = get_backarray(n);
159         if (ba)
160                 return rbitset_is_set(ba, pos);
161         return 0;
162 }
163
164 /* Remarks that edge pos is a backedge. */
165 void set_backedge(ir_node *n, int pos) {
166         unsigned *ba = get_backarray(n);
167         assert(ba && "can only set backedges at Phi, Filter, Block nodes.");
168         rbitset_set(ba, pos);
169 }
170
171 /* Remarks that edge pos is a backedge. */
172 void set_not_backedge(ir_node *n, int pos) {
173         unsigned *ba = get_backarray(n);
174         assert(ba && "can only set backedges at Phi, Filter, Block nodes.");
175         rbitset_clear(ba, pos);
176 }
177
178 /* Returns non-zero if n has backedges. */
179 int has_backedges(ir_node *n) {
180         unsigned *ba = get_backarray(n);
181         if (ba) {
182                 int arity = get_irn_arity(n);
183                 return !rbitset_is_empty(ba, arity);
184         }
185         return 0;
186 }
187
188 /** Sets all backedge information to zero. */
189 void clear_backedges(ir_node *n) {
190         int i, arity;
191         unsigned *ba;
192 #ifdef INTERPROCEDURAL_VIEW
193         int rem = get_interprocedural_view();
194         set_interprocedural_view(0);
195 #endif
196         ba = get_backarray(n);
197         if (ba) {
198                 arity = get_irn_arity(n);
199                 for (i = 0; i < arity; i++)
200                         rbitset_clear(ba, i);
201         }
202 #ifdef INTERPROCEDURAL_VIEW
203         set_interprocedural_view(1);
204         ba = get_backarray (n);
205         if (ba) {
206                 arity = get_irn_arity(n);
207                 for (i = 0; i < arity; i++)
208                         rbitset_clear(ba, i);
209         }
210         set_interprocedural_view(rem);
211 #endif
212 }
213
214 /* Allocate a new backedge array on the obstack for given size. */
215 unsigned *new_backedge_arr(struct obstack *obst, unsigned size) {
216         return rbitset_w_size_obstack_alloc(obst, size);
217 }
218
219 /* TODO: add an ir_op operation */
220 void new_backedge_info(ir_node *n) {
221         switch (get_irn_opcode(n)) {
222         case iro_Block:
223                 n->attr.block.cg_backedge = NULL;
224                 n->attr.block.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
225                 break;
226         case iro_Phi:
227                 n->attr.phi.u.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
228                 break;
229         case iro_Filter:
230                 n->attr.filter.backedge = new_backedge_arr(current_ir_graph->obst, get_irn_arity(n));
231                 break;
232         default: ;
233         }
234 }