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 return values_interfere(ifg->env->lv, a, b);
48 typedef struct _nodes_iter_t {
49 const be_chordal_env_t *env;
56 static void nodes_walker(ir_node *bl, void *data)
58 nodes_iter_t *it = data;
59 struct list_head *head = get_block_border_head(it->env, bl);
63 foreach_border_head(head, b) {
64 if(b->is_def && b->is_real) {
65 obstack_ptr_grow(&it->obst, b->irn);
71 static void find_nodes(const void *self, void *iter) {
72 const ifg_std_t *ifg = self;
73 nodes_iter_t *it = iter;
75 obstack_init(&it->obst);
80 irg_block_walk_graph(ifg->env->irg, nodes_walker, NULL, iter);
81 obstack_ptr_grow(&it->obst, NULL);
82 it->nodes = obstack_finish(&it->obst);
85 static INLINE void node_break(nodes_iter_t *it, int force)
87 if((it->curr >= it->n || force) && it->nodes) {
88 obstack_free(&it->obst, NULL);
93 static ir_node *get_next_node(void *iter)
95 nodes_iter_t *it = iter;
99 res = it->nodes[it->curr++];
106 static ir_node *ifg_std_nodes_begin(const void *self, void *iter)
108 find_nodes(self, iter);
109 return get_next_node(iter);
112 static ir_node *ifg_std_nodes_next(const void *self, void *iter)
114 return get_next_node(iter);
117 static void ifg_std_nodes_break(const void *self, void *iter)
122 typedef struct _adj_iter_t {
123 const be_chordal_env_t *env;
129 static void find_neighbour_walker(ir_node *block, void *data)
131 adj_iter_t *it = data;
132 struct list_head *head = get_block_border_head(it->env, block);
137 if(!be_is_live_in(it->env->lv, block, it->irn) && block != get_nodes_block(it->irn))
140 foreach_border_head(head, b) {
141 ir_node *irn = b->irn;
147 break; /* if we reached the end of the node's lifetime we can safely break */
150 /* if any other node than the one in question starts living, add it to the set */
151 pset_insert_ptr(it->neighbours, irn);
153 else if(!has_started) {
154 /* we only delete, if the live range in question has not yet started */
155 pset_remove_ptr(it->neighbours, irn);
161 static void find_neighbours(const ifg_std_t *ifg, adj_iter_t *it, const ir_node *irn)
165 it->neighbours = pset_new_ptr(16);
168 dom_tree_walk(get_nodes_block(irn), find_neighbour_walker, NULL, it);
171 static INLINE void neighbours_break(adj_iter_t *it, int force)
173 if((it->reached_end || force) && it->neighbours) {
174 del_pset(it->neighbours);
175 it->neighbours = NULL;
179 static ir_node *get_next_neighbour(adj_iter_t *it) {
180 ir_node *res = pset_next(it->neighbours);
182 it->reached_end = res == NULL;
183 neighbours_break(it, 0);
188 static ir_node *ifg_std_neighbours_begin(const void *self, void *iter, const ir_node *irn)
190 adj_iter_t *it = iter;
191 find_neighbours(self, iter, irn);
192 return pset_first(it->neighbours);
195 static ir_node *ifg_std_neighbours_next(const void *self, void *iter)
197 return get_next_neighbour(iter);
200 static void ifg_std_neighbours_break(const void *self, void *iter)
202 neighbours_break(iter, 1);
205 typedef struct _cliques_iter_t {
207 const be_chordal_env_t *cenv;
211 struct list_head *bor;
215 static INLINE void free_clique_iter(cliques_iter_t *it) {
217 obstack_free(&it->ob, NULL);
218 del_pset(it->living);
221 static void get_blocks_dom_order(ir_node *blk, void *env) {
222 cliques_iter_t *it = env;
223 obstack_ptr_grow(&it->ob, blk);
226 #define pset_foreach(pset, irn) for(irn=pset_first(pset); irn; irn=pset_next(pset))
230 * NOTE: Be careful when changing this function!
231 * First understand the control flow of consecutive calls.
233 static INLINE int get_next_clique(cliques_iter_t *it) {
235 /* continue in the block we left the last time */
236 for (; it->blk < it->n_blocks; it->blk++) {
237 int output_on_shrink = 0;
238 struct list_head *head = get_block_border_head(it->cenv, it->blocks[it->blk]);
240 /* on entry to a new block set the first border ... */
242 it->bor = head->prev;
244 /* ... otherwise continue with the border we left the last time */
245 for (; it->bor != head; it->bor = it->bor->prev) {
246 border_t *b = list_entry(it->bor, border_t, list);
248 /* if its a definition irn starts living */
250 pset_insert_ptr(it->living, b->irn);
252 output_on_shrink = 1;
255 /* if its the last usage the irn dies */
257 /* before shrinking the set, return the current maximal clique */
258 if (output_on_shrink) {
262 /* fill the output buffer */
263 pset_foreach(it->living, irn)
264 it->buf[count++] = irn;
266 assert(count > 0 && "We have a 'last usage', so there must be sth. in it->living");
271 pset_remove_ptr(it->living, b->irn);
276 assert(0 == pset_count(it->living) && "Something has survived! (At the end of the block it->living must be empty)");
279 if (it->n_blocks != -1)
280 free_clique_iter(it);
285 static int ifg_std_cliques_begin(const void *self, void *iter, ir_node **buf)
287 const ifg_std_t *ifg = self;
288 cliques_iter_t *it = iter;
289 ir_node *start_bl = get_irg_start_block(ifg->env->irg);
291 obstack_init(&it->ob);
292 dom_tree_walk(start_bl, get_blocks_dom_order, NULL, it);
296 it->n_blocks = obstack_object_size(&it->ob) / sizeof(void *);
297 it->blocks = obstack_finish(&it->ob);
300 it->living = pset_new_ptr(2 * arch_register_class_n_regs(it->cenv->cls));
302 return get_next_clique(it);
305 static int ifg_std_cliques_next(const void *self, void *iter)
307 return get_next_clique(iter);
310 static void ifg_std_cliques_break(const void *self, void *iter)
312 free_clique_iter(iter);
316 static int ifg_std_degree(const void *self, const ir_node *irn)
320 find_neighbours(self, &it, irn);
321 degree = pset_count(it.neighbours);
322 neighbours_break(&it, 1);
326 static const be_ifg_impl_t ifg_std_impl = {
327 sizeof(nodes_iter_t),
329 sizeof(cliques_iter_t),
333 ifg_std_neighbours_begin,
334 ifg_std_neighbours_next,
335 ifg_std_neighbours_break,
339 ifg_std_cliques_begin,
340 ifg_std_cliques_next,
341 ifg_std_cliques_break,
345 be_ifg_t *be_ifg_std_new(const be_chordal_env_t *env)
347 ifg_std_t *ifg = xmalloc(sizeof(*ifg));
349 ifg->impl = &ifg_std_impl;
352 return (be_ifg_t *) ifg;