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);
187 ir_nodeset_destroy(&it->neighbours);
192 static ir_node *ifg_std_neighbours_begin(const void *self, void *iter, const ir_node *irn)
194 adj_iter_t *it = iter;
195 find_neighbours(self, iter, irn);
196 return ir_nodeset_iterator_next(&it->iter);
199 static ir_node *ifg_std_neighbours_next(const void *self, void *iter)
201 return get_next_neighbour(iter);
204 static void ifg_std_neighbours_break(const void *self, void *iter)
206 neighbours_break(iter, 1);
209 typedef struct _cliques_iter_t {
211 const be_chordal_env_t *cenv;
215 struct list_head *bor;
219 static INLINE void free_clique_iter(cliques_iter_t *it) {
221 obstack_free(&it->ob, NULL);
222 del_pset(it->living);
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);
230 #define pset_foreach(pset, irn) for(irn=pset_first(pset); irn; irn=pset_next(pset))
234 * NOTE: Be careful when changing this function!
235 * First understand the control flow of consecutive calls.
237 static INLINE int get_next_clique(cliques_iter_t *it) {
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]);
244 /* on entry to a new block set the first border ... */
246 it->bor = head->prev;
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);
252 /* if its a definition irn starts living */
254 pset_insert_ptr(it->living, b->irn);
256 output_on_shrink = 1;
259 /* if its the last usage the irn dies */
261 /* before shrinking the set, return the current maximal clique */
262 if (output_on_shrink) {
266 /* fill the output buffer */
267 pset_foreach(it->living, irn)
268 it->buf[count++] = irn;
270 assert(count > 0 && "We have a 'last usage', so there must be sth. in it->living");
275 pset_remove_ptr(it->living, b->irn);
280 assert(0 == pset_count(it->living) && "Something has survived! (At the end of the block it->living must be empty)");
283 if (it->n_blocks != -1)
284 free_clique_iter(it);
289 static int ifg_std_cliques_begin(const void *self, void *iter, ir_node **buf)
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);
295 obstack_init(&it->ob);
296 dom_tree_walk(start_bl, get_blocks_dom_order, NULL, it);
300 it->n_blocks = obstack_object_size(&it->ob) / sizeof(void *);
301 it->blocks = obstack_finish(&it->ob);
304 it->living = pset_new_ptr(2 * arch_register_class_n_regs(it->cenv->cls));
306 return get_next_clique(it);
309 static int ifg_std_cliques_next(const void *self, void *iter)
311 return get_next_clique(iter);
314 static void ifg_std_cliques_break(const void *self, void *iter)
316 free_clique_iter(iter);
320 static int ifg_std_degree(const void *self, const ir_node *irn)
324 find_neighbours(self, &it, irn);
325 degree = ir_nodeset_size(&it.neighbours);
326 neighbours_break(&it, 1);
330 static const be_ifg_impl_t ifg_std_impl = {
331 sizeof(nodes_iter_t),
333 sizeof(cliques_iter_t),
337 ifg_std_neighbours_begin,
338 ifg_std_neighbours_next,
339 ifg_std_neighbours_break,
343 ifg_std_cliques_begin,
344 ifg_std_cliques_next,
345 ifg_std_cliques_break,
349 be_ifg_t *be_ifg_std_new(const be_chordal_env_t *env)
351 ifg_std_t *ifg = xmalloc(sizeof(*ifg));
353 ifg->impl = &ifg_std_impl;
356 return (be_ifg_t *) ifg;