4 * @author Sebastian Hack
6 * Copyright (C) 2005 Universitaet Karlsruhe
7 * Released under the GPL
19 #include "irgraph_t.h"
26 #include "bechordal_t.h"
28 #define MAX(x, y) ((x) > (y) ? (x) : (y))
30 typedef struct _ifg_std_t ifg_std_t;
33 const be_ifg_impl_t *impl;
34 const be_chordal_env_t *env;
37 static void ifg_std_free(void *self)
42 static int ifg_std_connected(const void *self, const ir_node *a, const ir_node *b)
44 const ifg_std_t *ifg = self;
45 be_lv_t *lv = ifg->env->birg->lv;
46 return values_interfere(lv, a, b);
49 typedef struct _nodes_iter_t {
50 const be_chordal_env_t *env;
57 static void nodes_walker(ir_node *bl, void *data)
59 nodes_iter_t *it = data;
60 struct list_head *head = get_block_border_head(it->env, bl);
64 foreach_border_head(head, b) {
65 if(b->is_def && b->is_real) {
66 obstack_ptr_grow(&it->obst, b->irn);
72 static void find_nodes(const void *self, void *iter) {
73 const ifg_std_t *ifg = self;
74 nodes_iter_t *it = iter;
76 obstack_init(&it->obst);
81 irg_block_walk_graph(ifg->env->irg, nodes_walker, NULL, iter);
82 obstack_ptr_grow(&it->obst, NULL);
83 it->nodes = obstack_finish(&it->obst);
86 static INLINE void node_break(nodes_iter_t *it, int force)
88 if((it->curr >= it->n || force) && it->nodes) {
89 obstack_free(&it->obst, NULL);
94 static ir_node *get_next_node(void *iter)
96 nodes_iter_t *it = iter;
100 res = it->nodes[it->curr++];
107 static ir_node *ifg_std_nodes_begin(const void *self, void *iter)
109 find_nodes(self, iter);
110 return get_next_node(iter);
113 static ir_node *ifg_std_nodes_next(const void *self, void *iter)
115 return get_next_node(iter);
118 static void ifg_std_nodes_break(const void *self, void *iter)
123 typedef struct _adj_iter_t {
124 const be_chordal_env_t *env;
130 static void find_neighbour_walker(ir_node *block, void *data)
132 adj_iter_t *it = data;
133 struct list_head *head = get_block_border_head(it->env, block);
138 if(!be_is_live_in(it->env->birg->lv, block, it->irn) && block != get_nodes_block(it->irn))
141 foreach_border_head(head, b) {
142 ir_node *irn = b->irn;
148 break; /* if we reached the end of the node's lifetime we can safely break */
151 /* if any other node than the one in question starts living, add it to the set */
152 pset_insert_ptr(it->neighbours, irn);
154 else if(!has_started) {
155 /* we only delete, if the live range in question has not yet started */
156 pset_remove_ptr(it->neighbours, irn);
162 static void find_neighbours(const ifg_std_t *ifg, adj_iter_t *it, const ir_node *irn)
166 it->neighbours = pset_new_ptr(16);
169 dom_tree_walk(get_nodes_block(irn), find_neighbour_walker, NULL, it);
172 static INLINE void neighbours_break(adj_iter_t *it, int force)
174 if((it->reached_end || force) && it->neighbours) {
175 del_pset(it->neighbours);
176 it->neighbours = NULL;
180 static ir_node *get_next_neighbour(adj_iter_t *it) {
181 ir_node *res = pset_next(it->neighbours);
183 it->reached_end = res == NULL;
184 neighbours_break(it, 0);
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 pset_first(it->neighbours);
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 = pset_count(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;