4 * @author Sebastian Hack
6 * Copyright (C) 2005 Universitaet Karlsruhe
7 * Released under the GPL
19 #include "irnodeset.h"
20 #include "irgraph_t.h"
27 #include "bechordal_t.h"
29 #define MAX(x, y) ((x) > (y) ? (x) : (y))
31 typedef struct _ifg_std_t ifg_std_t;
34 const be_ifg_impl_t *impl;
35 const be_chordal_env_t *env;
38 static void ifg_std_free(void *self)
43 static int ifg_std_connected(const void *self, const ir_node *a, const ir_node *b)
45 const ifg_std_t *ifg = self;
46 be_lv_t *lv = ifg->env->birg->lv;
47 return values_interfere(lv, a, b);
50 typedef struct _nodes_iter_t {
51 const be_chordal_env_t *env;
58 static void nodes_walker(ir_node *bl, void *data)
60 nodes_iter_t *it = data;
61 struct list_head *head = get_block_border_head(it->env, bl);
65 foreach_border_head(head, b) {
66 if(b->is_def && b->is_real) {
67 obstack_ptr_grow(&it->obst, b->irn);
73 static void find_nodes(const void *self, void *iter) {
74 const ifg_std_t *ifg = self;
75 nodes_iter_t *it = iter;
77 obstack_init(&it->obst);
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);
87 static INLINE void node_break(nodes_iter_t *it, int force)
89 if((it->curr >= it->n || force) && it->nodes) {
90 obstack_free(&it->obst, NULL);
95 static ir_node *get_next_node(void *iter)
97 nodes_iter_t *it = iter;
101 res = it->nodes[it->curr++];
108 static ir_node *ifg_std_nodes_begin(const void *self, void *iter)
110 find_nodes(self, iter);
111 return get_next_node(iter);
114 static ir_node *ifg_std_nodes_next(const void *self, void *iter)
116 return get_next_node(iter);
119 static void ifg_std_nodes_break(const void *self, void *iter)
124 typedef struct _adj_iter_t {
125 const be_chordal_env_t *env;
128 ir_nodeset_t neighbours;
129 ir_nodeset_iterator_t iter;
132 static void find_neighbour_walker(ir_node *block, void *data)
134 adj_iter_t *it = data;
135 struct list_head *head = get_block_border_head(it->env, block);
140 if(!be_is_live_in(it->env->birg->lv, block, it->irn) && block != get_nodes_block(it->irn))
143 foreach_border_head(head, b) {
144 ir_node *irn = b->irn;
150 break; /* if we reached the end of the node's lifetime we can safely break */
153 /* if any other node than the one in question starts living, add it to the set */
154 ir_nodeset_insert(&it->neighbours, irn);
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);
164 static void find_neighbours(const ifg_std_t *ifg, adj_iter_t *it, const ir_node *irn)
169 ir_nodeset_init(&it->neighbours);
171 dom_tree_walk(get_nodes_block(irn), find_neighbour_walker, NULL, it);
173 ir_nodeset_iterator_init(&it->iter, &it->neighbours);
176 static INLINE void neighbours_break(adj_iter_t *it, int force)
178 assert(it->valid == 1);
179 ir_nodeset_destroy(&it->neighbours);
183 static ir_node *get_next_neighbour(adj_iter_t *it) {
184 ir_node *res = ir_nodeset_iterator_next(&it->iter);
189 static ir_node *ifg_std_neighbours_begin(const void *self, void *iter, const ir_node *irn)
191 adj_iter_t *it = iter;
192 find_neighbours(self, iter, irn);
193 return ir_nodeset_iterator_next(&it->iter);
196 static ir_node *ifg_std_neighbours_next(const void *self, void *iter)
198 return get_next_neighbour(iter);
201 static void ifg_std_neighbours_break(const void *self, void *iter)
203 neighbours_break(iter, 1);
206 typedef struct _cliques_iter_t {
208 const be_chordal_env_t *cenv;
212 struct list_head *bor;
216 static INLINE void free_clique_iter(cliques_iter_t *it) {
218 obstack_free(&it->ob, NULL);
219 del_pset(it->living);
222 static void get_blocks_dom_order(ir_node *blk, void *env) {
223 cliques_iter_t *it = env;
224 obstack_ptr_grow(&it->ob, blk);
227 #define pset_foreach(pset, irn) for(irn=pset_first(pset); irn; irn=pset_next(pset))
231 * NOTE: Be careful when changing this function!
232 * First understand the control flow of consecutive calls.
234 static INLINE int get_next_clique(cliques_iter_t *it) {
236 /* continue in the block we left the last time */
237 for (; it->blk < it->n_blocks; it->blk++) {
238 int output_on_shrink = 0;
239 struct list_head *head = get_block_border_head(it->cenv, it->blocks[it->blk]);
241 /* on entry to a new block set the first border ... */
243 it->bor = head->prev;
245 /* ... otherwise continue with the border we left the last time */
246 for (; it->bor != head; it->bor = it->bor->prev) {
247 border_t *b = list_entry(it->bor, border_t, list);
249 /* if its a definition irn starts living */
251 pset_insert_ptr(it->living, b->irn);
253 output_on_shrink = 1;
256 /* if its the last usage the irn dies */
258 /* before shrinking the set, return the current maximal clique */
259 if (output_on_shrink) {
263 /* fill the output buffer */
264 pset_foreach(it->living, irn)
265 it->buf[count++] = irn;
267 assert(count > 0 && "We have a 'last usage', so there must be sth. in it->living");
272 pset_remove_ptr(it->living, b->irn);
277 assert(0 == pset_count(it->living) && "Something has survived! (At the end of the block it->living must be empty)");
280 if (it->n_blocks != -1)
281 free_clique_iter(it);
286 static int ifg_std_cliques_begin(const void *self, void *iter, ir_node **buf)
288 const ifg_std_t *ifg = self;
289 cliques_iter_t *it = iter;
290 ir_node *start_bl = get_irg_start_block(ifg->env->irg);
292 obstack_init(&it->ob);
293 dom_tree_walk(start_bl, get_blocks_dom_order, NULL, it);
297 it->n_blocks = obstack_object_size(&it->ob) / sizeof(void *);
298 it->blocks = obstack_finish(&it->ob);
301 it->living = pset_new_ptr(2 * arch_register_class_n_regs(it->cenv->cls));
303 return get_next_clique(it);
306 static int ifg_std_cliques_next(const void *self, void *iter)
308 return get_next_clique(iter);
311 static void ifg_std_cliques_break(const void *self, void *iter)
313 free_clique_iter(iter);
317 static int ifg_std_degree(const void *self, const ir_node *irn)
321 find_neighbours(self, &it, irn);
322 degree = ir_nodeset_size(&it.neighbours);
323 neighbours_break(&it, 1);
327 static const be_ifg_impl_t ifg_std_impl = {
328 sizeof(nodes_iter_t),
330 sizeof(cliques_iter_t),
334 ifg_std_neighbours_begin,
335 ifg_std_neighbours_next,
336 ifg_std_neighbours_break,
340 ifg_std_cliques_begin,
341 ifg_std_cliques_next,
342 ifg_std_cliques_break,
346 be_ifg_t *be_ifg_std_new(const be_chordal_env_t *env)
348 ifg_std_t *ifg = xmalloc(sizeof(*ifg));
350 ifg->impl = &ifg_std_impl;
353 return (be_ifg_t *) ifg;