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