b0efa1c8814b1e0abb583d6336084c74765fc954
[libfirm] / ir / be / beifg_std.c
1 /**
2  * @file   beifg_std.c
3  * @date   18.11.2005
4  * @author Sebastian Hack
5  *
6  * Copyright (C) 2005 Universitaet Karlsruhe
7  * Released under the GPL
8  */
9
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13
14 #include <stdlib.h>
15
16 #include "list.h"
17
18 #include "irnode_t.h"
19 #include "irnodeset.h"
20 #include "irgraph_t.h"
21 #include "irgwalk.h"
22
23 #include "be_t.h"
24 #include "belive_t.h"
25 #include "bera.h"
26 #include "beifg_t.h"
27 #include "bechordal_t.h"
28
29 #define MAX(x, y) ((x) > (y) ? (x) : (y))
30
31 typedef struct _ifg_std_t ifg_std_t;
32
33 struct _ifg_std_t {
34         const be_ifg_impl_t *impl;
35         const be_chordal_env_t *env;
36 };
37
38 static void ifg_std_free(void *self)
39 {
40         free(self);
41 }
42
43 static int ifg_std_connected(const void *self, const ir_node *a, const ir_node *b)
44 {
45         const ifg_std_t *ifg = self;
46         be_lv_t *lv = ifg->env->birg->lv;
47         return values_interfere(lv, a, b);
48 }
49
50 typedef struct _nodes_iter_t {
51         const be_chordal_env_t *env;
52         struct obstack obst;
53         int n;
54         int curr;
55         ir_node **nodes;
56 } nodes_iter_t;
57
58 static void nodes_walker(ir_node *bl, void *data)
59 {
60         nodes_iter_t *it = data;
61         struct list_head *head = get_block_border_head(it->env, bl);
62
63         border_t *b;
64
65         foreach_border_head(head, b) {
66                 if(b->is_def && b->is_real) {
67                         obstack_ptr_grow(&it->obst, b->irn);
68                         it->n++;
69                 }
70         }
71 }
72
73 static void find_nodes(const void *self, void *iter) {
74         const ifg_std_t *ifg = self;
75         nodes_iter_t *it = iter;
76
77         obstack_init(&it->obst);
78         it->n     = 0;
79         it->curr  = 0;
80         it->env   = ifg->env;
81
82         irg_block_walk_graph(ifg->env->irg, nodes_walker, NULL, iter);
83         obstack_ptr_grow(&it->obst, NULL);
84         it->nodes = obstack_finish(&it->obst);
85 }
86
87 static INLINE void node_break(nodes_iter_t *it, int force)
88 {
89         if((it->curr >= it->n || force) && it->nodes) {
90                 obstack_free(&it->obst, NULL);
91                 it->nodes = NULL;
92         }
93 }
94
95 static ir_node *get_next_node(void *iter)
96 {
97         nodes_iter_t *it = iter;
98         ir_node *res     = NULL;
99
100         if(it->curr < it->n)
101                 res = it->nodes[it->curr++];
102
103         node_break(it, 0);
104
105         return res;
106 }
107
108 static ir_node *ifg_std_nodes_begin(const void *self, void *iter)
109 {
110         find_nodes(self, iter);
111         return get_next_node(iter);
112 }
113
114 static ir_node *ifg_std_nodes_next(const void *self, void *iter)
115 {
116         return get_next_node(iter);
117 }
118
119 static void ifg_std_nodes_break(const void *self, void *iter)
120 {
121         node_break(iter, 1);
122 }
123
124 typedef struct _adj_iter_t {
125         const be_chordal_env_t *env;
126         const ir_node        *irn;
127         int                   valid;
128         ir_nodeset_t          neighbours;
129         ir_nodeset_iterator_t iter;
130 } adj_iter_t;
131
132 static void find_neighbour_walker(ir_node *block, void *data)
133 {
134         adj_iter_t *it          = data;
135         struct list_head *head  = get_block_border_head(it->env, block);
136
137         border_t *b;
138         int has_started = 0;
139
140         if(!be_is_live_in(it->env->birg->lv, block, it->irn) && block != get_nodes_block(it->irn))
141                 return;
142
143         foreach_border_head(head, b) {
144                 ir_node *irn = b->irn;
145
146                 if(irn == it->irn) {
147                         if(b->is_def)
148                                 has_started = 1;
149                         else
150                                 break; /* if we reached the end of the node's lifetime we can safely break */
151                 }
152                 else if(b->is_def) {
153                         /* if any other node than the one in question starts living, add it to the set */
154                         ir_nodeset_insert(&it->neighbours, irn);
155                 }
156                 else if(!has_started) {
157                         /* we only delete, if the live range in question has not yet started */
158                         ir_nodeset_remove(&it->neighbours, irn);
159                 }
160
161         }
162 }
163
164 static void find_neighbours(const ifg_std_t *ifg, adj_iter_t *it, const ir_node *irn)
165 {
166         it->env         = ifg->env;
167         it->irn         = irn;
168         it->valid       = 1;
169         ir_nodeset_init(&it->neighbours);
170
171         dom_tree_walk(get_nodes_block(irn), find_neighbour_walker, NULL, it);
172
173         ir_nodeset_iterator_init(&it->iter, &it->neighbours);
174 }
175
176 static INLINE void neighbours_break(adj_iter_t *it, int force)
177 {
178         assert(it->valid == 1);
179         ir_nodeset_destroy(&it->neighbours);
180         it->valid = 0;
181 }
182
183 static ir_node *get_next_neighbour(adj_iter_t *it) {
184         ir_node *res = ir_nodeset_iterator_next(&it->iter);
185
186         if (res == NULL) {
187                 ir_nodeset_destroy(&it->neighbours);
188         }
189         return res;
190 }
191
192 static ir_node *ifg_std_neighbours_begin(const void *self, void *iter, const ir_node *irn)
193 {
194         adj_iter_t *it = iter;
195         find_neighbours(self, iter, irn);
196         return ir_nodeset_iterator_next(&it->iter);
197 }
198
199 static ir_node *ifg_std_neighbours_next(const void *self, void *iter)
200 {
201         return get_next_neighbour(iter);
202 }
203
204 static void ifg_std_neighbours_break(const void *self, void *iter)
205 {
206         neighbours_break(iter, 1);
207 }
208
209 typedef struct _cliques_iter_t {
210         struct obstack ob;
211         const be_chordal_env_t *cenv;
212         ir_node **buf;
213         ir_node **blocks;
214         int n_blocks, blk;
215         struct list_head *bor;
216         pset *living;
217 } cliques_iter_t;
218
219 static INLINE void free_clique_iter(cliques_iter_t *it) {
220         it->n_blocks = -1;
221         obstack_free(&it->ob, NULL);
222         del_pset(it->living);
223 }
224
225 static void get_blocks_dom_order(ir_node *blk, void *env) {
226         cliques_iter_t *it = env;
227         obstack_ptr_grow(&it->ob, blk);
228 }
229
230 #define pset_foreach(pset, irn)  for(irn=pset_first(pset); irn; irn=pset_next(pset))
231
232
233 /**
234  * NOTE: Be careful when changing this function!
235  *       First understand the control flow of consecutive calls.
236  */
237 static INLINE int get_next_clique(cliques_iter_t *it) {
238
239         /* continue in the block we left the last time */
240         for (; it->blk < it->n_blocks; it->blk++) {
241                 int output_on_shrink = 0;
242                 struct list_head *head = get_block_border_head(it->cenv, it->blocks[it->blk]);
243
244                 /* on entry to a new block set the first border ... */
245                 if (!it->bor)
246                         it->bor = head->prev;
247
248                 /* ... otherwise continue with the border we left the last time */
249                 for (; it->bor != head; it->bor = it->bor->prev) {
250                         border_t *b = list_entry(it->bor, border_t, list);
251
252                         /* if its a definition irn starts living */
253                         if (b->is_def) {
254                                 pset_insert_ptr(it->living, b->irn);
255                                 if (b->is_real)
256                                         output_on_shrink = 1;
257                         } else
258
259                         /* if its the last usage the irn dies */
260                         {
261                                 /* before shrinking the set, return the current maximal clique */
262                                 if (output_on_shrink) {
263                                         int count = 0;
264                                         ir_node *irn;
265
266                                         /* fill the output buffer */
267                                         pset_foreach(it->living, irn)
268                                                 it->buf[count++] = irn;
269
270                                         assert(count > 0 && "We have a 'last usage', so there must be sth. in it->living");
271
272                                         return count;
273                                 }
274
275                                 pset_remove_ptr(it->living, b->irn);
276                         }
277                 }
278
279                 it->bor = NULL;
280                 assert(0 == pset_count(it->living) && "Something has survived! (At the end of the block it->living must be empty)");
281         }
282
283         if (it->n_blocks != -1)
284                 free_clique_iter(it);
285
286         return -1;
287 }
288
289 static int ifg_std_cliques_begin(const void *self, void *iter, ir_node **buf)
290 {
291         const ifg_std_t *ifg = self;
292         cliques_iter_t *it = iter;
293         ir_node *start_bl = get_irg_start_block(ifg->env->irg);
294
295         obstack_init(&it->ob);
296         dom_tree_walk(start_bl, get_blocks_dom_order, NULL, it);
297
298         it->cenv     = ifg->env;
299         it->buf      = buf;
300         it->n_blocks = obstack_object_size(&it->ob) / sizeof(void *);
301         it->blocks   = obstack_finish(&it->ob);
302         it->blk      = 0;
303         it->bor      = NULL;
304         it->living   = pset_new_ptr(2 * arch_register_class_n_regs(it->cenv->cls));
305
306         return get_next_clique(it);
307 }
308
309 static int ifg_std_cliques_next(const void *self, void *iter)
310 {
311         return get_next_clique(iter);
312 }
313
314 static void ifg_std_cliques_break(const void *self, void *iter)
315 {
316         free_clique_iter(iter);
317 }
318
319
320 static int ifg_std_degree(const void *self, const ir_node *irn)
321 {
322         adj_iter_t it;
323         int degree;
324         find_neighbours(self, &it, irn);
325         degree = ir_nodeset_size(&it.neighbours);
326         neighbours_break(&it, 1);
327         return degree;
328 }
329
330 static const be_ifg_impl_t ifg_std_impl = {
331         sizeof(nodes_iter_t),
332         sizeof(adj_iter_t),
333         sizeof(cliques_iter_t),
334
335         ifg_std_free,
336         ifg_std_connected,
337         ifg_std_neighbours_begin,
338         ifg_std_neighbours_next,
339         ifg_std_neighbours_break,
340         ifg_std_nodes_begin,
341         ifg_std_nodes_next,
342         ifg_std_nodes_break,
343         ifg_std_cliques_begin,
344         ifg_std_cliques_next,
345         ifg_std_cliques_break,
346         ifg_std_degree
347 };
348
349 be_ifg_t *be_ifg_std_new(const be_chordal_env_t *env)
350 {
351         ifg_std_t *ifg = xmalloc(sizeof(*ifg));
352
353         ifg->impl = &ifg_std_impl;
354         ifg->env  = env;
355
356         return (be_ifg_t *) ifg;
357 }