added new licence header
[libfirm] / ir / be / beifg_list.c
1 /*
2  * Copyright (C) 1995-2007 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   beifg_list.c
22  * @date   18.11.2005
23  * @author Sebastian Hack
24  *
25  * Copyright (C) 2005 Universitaet Karlsruhe
26  * Released under the GPL
27  */
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32
33 #include <stdlib.h>
34
35 #include "benodesets.h"
36 #include "list.h"
37
38 #include "irnode_t.h"
39 #include "irgraph_t.h"
40 #include "irgwalk.h"
41
42 #include "be_t.h"
43 #include "bera.h"
44 #include "beifg_t.h"
45 #include "bechordal_t.h"
46
47
48 typedef struct _adj_head_t adj_head_t;
49
50 typedef struct _ifg_list_t {
51         const be_ifg_impl_t *impl;
52         const be_chordal_env_t *env;
53         struct obstack obst;
54         adj_head_t **adj_heads;
55 } ifg_list_t;
56
57 typedef struct _adj_element_t adj_element_t;
58
59 struct _adj_element_t {
60         adj_element_t *next_adj_element;
61         ir_node *neighbour;
62 };
63
64 struct _adj_head_t {
65         ir_node *irn; /* the node you search neighbours for */
66         adj_element_t *first_adj_element;
67         int degree;
68 };
69
70 typedef struct _nodes_iter_t {
71         const ifg_list_t *ifg;
72         unsigned int curr_node_idx;
73 } nodes_iter_t;
74
75 typedef struct _adj_iter_t {
76         const ifg_list_t *ifg;
77         adj_element_t *curr_adj_element;
78 } adj_iter_t;
79
80 /* PRIVATE FUNCTIONS */
81
82 static void create_node (ifg_list_t *ifg, ir_node *irn) /* add node to the array of all nodes in this ifg implementation, if the node isn't already in the ifg */
83 {
84         adj_head_t *adj_head = NULL;
85
86         adj_head = ifg->adj_heads[irn->node_idx];
87         if (!adj_head)
88         {
89                 adj_head = obstack_alloc(&ifg->obst, sizeof(*adj_head));
90                 adj_head->irn = irn;
91                 adj_head->first_adj_element = NULL;
92                 adj_head->degree = 0;
93                 ifg->adj_heads[irn->node_idx] = adj_head;
94         }
95 }
96
97 static adj_element_t *create_adj_element(ifg_list_t *ifg, ir_node *irn)
98 {
99         adj_element_t *element = NULL;
100
101         element = obstack_alloc(&ifg->obst, sizeof(*element));
102         element->next_adj_element = NULL;
103         element->neighbour = irn;
104
105         return element;
106 }
107
108 static void add_edge(ifg_list_t *ifg, ir_node *node_a, ir_node *node_b) /* write the information about the edge between a and b */
109 {
110         adj_head_t *adj_head = NULL;
111         adj_element_t *curr_element = NULL;
112         adj_element_t *new_element = NULL;
113
114         adj_head = ifg->adj_heads[node_a->node_idx]; /* find the neighbours list of a */
115
116         assert (adj_head && "There is no entry for node a");
117         curr_element = adj_head->first_adj_element;
118
119         if (curr_element)
120         {
121                 while (curr_element->neighbour != node_b && curr_element->next_adj_element)
122                 {
123                         curr_element = curr_element->next_adj_element;
124                 }
125
126                 if (curr_element->neighbour != node_b && curr_element->next_adj_element == NULL)
127                 {
128                         adj_head->degree++;
129                         new_element = create_adj_element(ifg, node_b); /* if b isn't in list, add b */
130                         curr_element->next_adj_element = new_element;
131                 }
132         }
133         else
134         {
135                 adj_head->degree++;
136                 new_element = create_adj_element(ifg, node_b); /* a has no neighbours, add b as the first one*/
137                 adj_head->first_adj_element = new_element;
138         }
139
140         /* do the same vice versa */
141         adj_head = ifg->adj_heads[node_b->node_idx];
142
143         assert (adj_head && "There is no entry for node a");
144         curr_element = adj_head->first_adj_element;
145
146         if (curr_element)
147         {
148                 while (curr_element->neighbour != node_a && curr_element->next_adj_element)
149                 {
150                         curr_element = curr_element->next_adj_element;
151                 }
152
153                 if (curr_element->neighbour != node_a && curr_element->next_adj_element == NULL)
154                 {
155                         adj_head->degree++;
156                         new_element = create_adj_element(ifg, node_a);
157                         curr_element->next_adj_element = new_element;
158                 }
159         }
160         else
161         {
162                 adj_head->degree++;
163                 new_element = create_adj_element(ifg, node_a);
164                 adj_head->first_adj_element = new_element;
165         }
166 }
167
168 static void find_neighbour_walker(ir_node *bl, void *data) /* find all adjacent nodes in the irg */
169 {
170         ifg_list_t *ifg = data;
171         struct list_head *head  = get_block_border_head(ifg->env, bl);
172
173         nodeset *live = new_nodeset(ifg->env->cls->n_regs);
174         ir_node *live_irn = NULL;
175         border_t *b = NULL;
176
177         assert (is_Block(bl) && "There is no block to work on");
178
179         foreach_border_head(head, b) /* follow the borders of each block */
180         {
181                 if (b->is_def)
182                 {
183                         create_node(ifg, b->irn); /* add the node to the array of all nodes of this ifg implementation */
184                         nodeset_insert(live, b->irn);
185                         if (b->is_real) /* this is a new node */
186                         {
187                                 foreach_nodeset(live, live_irn)
188                                 {
189                                         if (b->irn != live_irn) /* add a as a neighbour to b and vice versa */
190                                                 add_edge(ifg, b->irn, live_irn);
191                                 }
192                         }
193                 }
194                 else /* b->irn is now dead */
195                 {
196                         if (nodeset_find(live, b->irn))
197                                 nodeset_remove(live, b->irn);
198                 }
199         }
200
201         if (live)
202                 del_nodeset(live);
203 }
204
205 static ir_node *get_first_node(const ifg_list_t *ifg, nodes_iter_t *it)
206 {
207         ir_node *res = NULL;
208         adj_head_t *adj_head= NULL;
209         int curr_idx = -1;
210
211         it->ifg = ifg;
212         it->curr_node_idx = 0;
213
214         while (adj_head == NULL)
215         {
216                 curr_idx++;
217                 adj_head = ifg->adj_heads[curr_idx];
218         }
219
220         if (adj_head == NULL) /* there are no nodes in this ifg */
221                 return NULL;
222         else
223         {
224                 res = adj_head->irn;
225                 it->curr_node_idx = curr_idx;
226         }
227
228         return res;
229 }
230
231 static ir_node *get_next_node(nodes_iter_t *it)
232 {
233         const ifg_list_t *ifg = it->ifg;
234         ir_node *res = NULL;
235         adj_head_t *adj_head= NULL;
236         unsigned int curr_idx = it->curr_node_idx;
237
238         while (adj_head == NULL && curr_idx < it->ifg->env->irg->last_node_idx - 1)
239         {
240                 curr_idx++;
241                 adj_head = ifg->adj_heads[curr_idx];
242         }
243
244         if (adj_head == NULL) /* there are no more nodes in this ifg */
245                 return NULL;
246         else
247         {
248                 res = adj_head->irn;
249                 it->curr_node_idx = curr_idx;
250         }
251
252         return res;
253 }
254
255 static ir_node *get_first_neighbour(const ifg_list_t *ifg, adj_iter_t *it, const ir_node *curr_irn)
256 {
257         ir_node *res = NULL;
258         adj_head_t *adj_head = NULL;
259
260         adj_head = ifg->adj_heads[curr_irn->node_idx];
261         assert (adj_head && "There is no entry for this node");
262
263         it->curr_adj_element = NULL;
264         it->ifg = ifg;
265
266         if (adj_head->first_adj_element) /* return first neighbour */
267         {
268                 res = adj_head->first_adj_element->neighbour;
269                 it->curr_adj_element = adj_head->first_adj_element;
270         }
271         else /* node has no neighbours */
272                 return NULL;
273
274         return res;
275 }
276
277 static ir_node *get_next_neighbour(adj_iter_t *it)
278 {
279         ir_node *res = NULL;
280         adj_element_t *element = it->curr_adj_element;
281
282         if (element->next_adj_element) /* return next neighbour */
283         {
284                 res = element->next_adj_element->neighbour;
285                 it->curr_adj_element = element->next_adj_element;
286         }
287         else /* was last neighbour */
288                 return NULL;
289
290         return res;
291 }
292
293 /* PUBLIC FUNCTIONS */
294
295 static void ifg_list_free(void *self)
296 {
297         ifg_list_t *ifg = self;
298         obstack_free(&ifg->obst, NULL);
299         free(ifg->adj_heads);
300         free(ifg);
301 }
302
303 static int ifg_list_connected(const void *self, const ir_node *a, const ir_node *b)
304 {
305         const ifg_list_t *ifg = self;
306         int res = -1;
307         adj_head_t *adj_head = NULL;
308         adj_element_t *curr_element = NULL;
309
310         /* first try: find b in the neigbours of a */
311         adj_head = ifg->adj_heads[a->node_idx];
312
313         assert(adj_head && "There is no entry for the node a");
314         curr_element = adj_head->first_adj_element;
315
316         if(curr_element)
317         {
318                 while (curr_element->neighbour != b && curr_element->next_adj_element)
319                 {
320                         curr_element = curr_element->next_adj_element;
321                 }
322                 if (curr_element->neighbour == b)
323                         return 1;
324                 else
325                         res = 0;
326         }
327         else /* node a has no neighbours */
328                 res = 0;
329
330         /* second try, this should not be necessary... only to check the solution */
331         adj_head = ifg->adj_heads[b->node_idx];
332
333         assert(adj_head && "There is no entry for the node b");
334         curr_element = adj_head->first_adj_element;
335
336         if(curr_element)
337         {
338                 while (curr_element->neighbour != a && curr_element->next_adj_element)
339                 {
340                         curr_element = curr_element->next_adj_element;
341                 }
342                 if (curr_element->neighbour == a)
343                 {
344                         assert ("Found the neighbour only in the second try.");
345                         return 1;
346                 }
347                 else
348                         res = 0;
349         }
350         else /* node b has no neighbours */
351                 res = 0;
352
353         return res;
354 }
355
356 static ir_node *ifg_list_nodes_begin(const void *self, void *iter)
357 {
358         nodes_iter_t *it = iter;
359         return get_first_node(self, it);
360 }
361
362 static ir_node *ifg_list_nodes_next(const void *self, void *iter)
363 {
364         return get_next_node(iter);
365 }
366
367 static void ifg_list_nodes_break(const void *self, void *iter)
368 {
369         nodes_iter_t *it = iter;
370         it->curr_node_idx = 0;
371         it->ifg = NULL;
372 }
373
374 static ir_node *ifg_list_neighbours_begin(const void *self, void *iter,const ir_node *irn)
375 {
376         adj_iter_t *it = iter;
377         return get_first_neighbour(self, it, irn);
378 }
379
380 static ir_node *ifg_list_neighbours_next(const void *self, void *iter)
381 {
382         return get_next_neighbour(iter);
383 }
384
385 static void ifg_list_neighbours_break(const void *self, void *iter)
386 {
387         adj_iter_t *it= iter;
388         it->curr_adj_element = NULL;
389         it->ifg = NULL;
390 }
391
392 static int ifg_list_degree(const void *self, const ir_node *irn)
393 {
394         const ifg_list_t *ifg = self;
395         adj_head_t *adj_head = NULL;
396
397         adj_head = ifg->adj_heads[irn->node_idx];
398
399         assert (adj_head && "There is no entry for this node");
400
401         return adj_head->degree;
402 }
403
404 static const be_ifg_impl_t ifg_list_impl = {
405         sizeof(nodes_iter_t),
406         sizeof(adj_iter_t),
407         0,
408         ifg_list_free,
409         ifg_list_connected,
410         ifg_list_neighbours_begin,
411         ifg_list_neighbours_next,
412         ifg_list_neighbours_break,
413         ifg_list_nodes_begin,
414         ifg_list_nodes_next,
415         ifg_list_nodes_break,
416         NULL,
417         NULL,
418         NULL,
419         ifg_list_degree
420 };
421
422 be_ifg_t *be_ifg_list_new(const be_chordal_env_t *env)
423 {
424         ifg_list_t *ifg = xmalloc(sizeof(*ifg));
425         adj_head_t **adj_heads_array = xmalloc(env->irg->last_node_idx * sizeof(adj_heads_array[0]));
426
427         ifg->impl = &ifg_list_impl;
428         ifg->env  = env;
429
430         memset(adj_heads_array, 0, env->irg->last_node_idx * sizeof(adj_heads_array[0]));
431         ifg->adj_heads = adj_heads_array;
432
433         obstack_init(&ifg->obst);
434         dom_tree_walk_irg(env->irg, find_neighbour_walker, NULL, ifg);
435         obstack_finish(&ifg->obst);
436
437         return (be_ifg_t *) ifg;
438 }