cadaf20bf75eb8caf4e93e6eaa8712312431b43d
[libfirm] / ir / be / bechordal.c
1 /**
2  * Chordal register allocation.
3  * @author Sebastian Hack
4  * @date 8.12.2004
5  *
6  * Copyright (C) Universitaet Karlsruhe
7  * Released under the GPL
8  */
9
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13
14 #include <ctype.h>
15
16 #include "obst.h"
17 #include "list.h"
18 #include "bitset.h"
19 #include "iterator.h"
20
21 #include "irmode_t.h"
22 #include "irgraph_t.h"
23 #include "irprintf_t.h"
24 #include "irgwalk.h"
25 #include "irdump.h"
26 #include "irdom.h"
27 #include "debug.h"
28 #include "xmalloc.h"
29
30 #include "beutil.h"
31 #include "besched.h"
32 #include "bera_t.h"
33 #include "benumb_t.h"
34 #include "besched_t.h"
35 #include "belive_t.h"
36 #include "bechordal_t.h"
37 #include "bearch.h"
38
39 #define BUILD_GRAPH
40 #undef DUMP_INTERVALS
41 #undef DUMP_PRESSURE
42 #undef DUMP_IFG
43
44 #if defined(DUMP_IFG) && !defined(BUILD_GRAPH)
45 #define BUILD_GRAPH
46 #endif
47
48
49 #ifdef DEBUG_libfirm
50 #include "fourcc.h"
51
52 /* Make a fourcc for border checking. */
53 #define BORDER_FOURCC                           FOURCC('B', 'O', 'R', 'D')
54
55 #endif /* DEBUG_libfirm */
56
57 #define TEST_COLORS 2048
58
59 static firm_dbg_module_t *dbg;
60
61 /**
62  * Environment for each of the chordal register allocator phases
63  */
64 typedef struct _env_t {
65         struct obstack obst;    /**< An obstack for temporary storage. */
66   ir_graph *irg;        /**< The graph the reg alloc is running on. */
67 #ifdef BUILD_GRAPH
68         set *nodes;                                             /**< The interference graph nodes. */
69         set *edges;                                             /**< The interference graph edges. */
70 #endif
71
72         bitset_t *live;                         /**< A liveness bitset. */
73         bitset_t *colors;                       /**< The color mask. */
74         bitset_t *in_colors;    /**< Colors used by live in values. */
75         int colors_n;                                   /**< The number of colors. */
76   const arch_env_t *arch_env;         /**< The arch interface environment. */
77   const arch_register_class_t *cls;   /**< The current register class. */
78   void *data;           /**< Some pointer, to which different
79                           phases can attach data to. */
80 } env_t;
81
82
83 typedef struct _be_chordal_dump_params_t {
84         int x_dist;
85         int y_dist;
86         double font_scale;
87 } be_chordal_dump_params_t;
88
89 static const be_chordal_dump_params_t dump_params = {
90         10,
91         10,
92         4
93 };
94
95 #ifdef DUMP_INTERVALS
96
97 static INLINE void intv_filename(char *s, size_t n,
98     const env_t *env, ir_node *block)
99 {
100         ir_snprintf(s, n, "intv_%F_%s_bl%N.eps",
101       env->irg, env->cls->name, block);
102 }
103
104 static void draw_interval_graph(const env_t *env,
105     ir_node *block, const be_chordal_dump_params_t *params)
106 {
107         int i;
108         int x_dist = params->x_dist;
109         int y_dist = params->y_dist;
110         ir_graph *irg = env->irg;
111   struct list_head *border_head = get_block_border_head(block);
112
113         FILE *f;
114         char buf[1024];
115
116   intv_filename(buf, sizeof(buf), env, block);
117
118         if((f = fopen(buf, "wt")) != NULL) {
119                 border_t *b;
120                 int *seen = xcalloc(get_graph_node_count(irg), sizeof(seen[0]));
121                 int last_pos = list_empty(border_head) ? 0 : list_entry(border_head->prev, border_t, list)->step;
122                 int max_col = 0;
123
124                 list_for_each_entry_reverse(border_t, b, border_head, list) {
125                         const ir_node *irn = b->irn;
126                         int col = get_irn_color(irn);
127                         max_col = max_col > col ? max_col : col;
128                 }
129
130                 fprintf(f, "%%!PS-Adobe-2.0\n");
131                 fprintf(f, "%%%%BoundingBox: -10 -10 %d %d\n",
132                                 x_dist * last_pos + x_dist, y_dist * max_col + y_dist);
133                 fprintf(f, "/mainfont /Courier findfont %f scalefont def\n", params->font_scale);
134                 fprintf(f, "mainfont setfont\n");
135                 fprintf(f, "0.2 setlinewidth\n");
136
137                 for(i = 0; i <= last_pos; ++i) {
138                         fprintf(f, "0 0 0 setrgbcolor\n");
139                         fprintf(f, "%d %d moveto\n", i * x_dist, -2);
140                         fprintf(f, "%d %d lineto\n", i * x_dist, max_col * y_dist + 2);
141                         fprintf(f, "stroke\n");
142                 }
143                 fprintf(f, "0.5 setlinewidth\n");
144
145                 list_for_each_entry_reverse(border_t, b, border_head, list) {
146                         const ir_node *irn = b->irn;
147                         int nr = get_irn_graph_nr(irn);
148
149                         if(b->is_def)
150                                 seen[nr] = b->step;
151                         else {
152                                 int col = get_irn_color(irn);
153
154                                 int pos = last_pos - seen[nr];
155                                 int end_pos = last_pos - b->step;
156                                 int live_in = is_live_in(block, irn);
157                                 int live_end = is_live_end(block, irn);
158                                 int y_val = y_dist * col;
159
160                                 int red = 0;
161                                 int green = live_end;
162                                 int blue = live_in;
163
164                                 fprintf(f, "0 0 0 setrgbcolor\n");
165                                 fprintf(f, "%d %d moveto\n", x_dist * pos + 2, y_val + 2);
166                                 ir_fprintf(f, "(%n/%d%s) show\n", irn, nr, is_phi_operand(irn) ? "*" : "");
167                                 fprintf(f, "%d %d %d setrgbcolor\n", red, green, blue);
168                                 fprintf(f, "%d %d moveto\n", x_dist * pos, y_val);
169                                 fprintf(f, "%d %d lineto\n", (x_dist * end_pos) - 5, y_val);
170                                 fprintf(f, "stroke\n");
171                         }
172                 }
173
174                 free(seen);
175                 fclose(f);
176         }
177 }
178
179 static void dump_block(ir_node *bl, void *data)
180 {
181   const env_t *env = data;
182   FILE *f = env->data;
183   char buf[128];
184
185   draw_interval_graph(env, bl, &dump_params);
186
187   intv_filename(buf, sizeof(buf), env, bl);
188   ir_fprintf(f, "\tb%N [shape=\"epsf\" shapefile=\"%s\"];\n", bl, buf);
189 }
190
191 static void dump_edges(ir_node *bl, void *data)
192 {
193   const env_t *env = data;
194   FILE *f = env->data;
195   int i, n;
196   ir_node *dom;
197
198 #if 0
199   for(i = 0, n = get_irn_arity(bl); i < n; ++i) {
200     ir_node *pred = get_irn_n(bl, i);
201     ir_fprintf(f, "\tb%N -> b%N;\n", get_nodes_block(pred), bl);
202   }
203 #endif
204
205   for(dom = get_Block_dominated_first(bl); dom;
206       dom = get_Block_dominated_next(dom)) {
207
208     ir_fprintf(f, "\tb%N -> b%N;\n", dom, bl);
209   }
210 }
211
212 static void dump_intv_cfg(env_t *env)
213 {
214   FILE *f;
215   char buf[128];
216
217   ir_snprintf(buf, sizeof(buf), "intv_cfg_%s_%F.dot",
218       env->cls->name, env->irg);
219
220   if((f = fopen(buf, "wt")) != NULL) {
221     void *old_data = env->data;
222
223     env->data = f;
224     ir_fprintf(f, "digraph G {\n");
225     ir_fprintf(f, "\tgraph [rankdir=\"LR\", ordering=\"out\"];\n");
226     dom_tree_walk_irg(env->irg, dump_block, dump_edges, env);
227     // irg_block_walk_graph(env->irg, dump_block, dump_edges, env);
228     ir_fprintf(f, "}\n");
229     fclose(f);
230
231     env->data = old_data;
232   }
233 }
234
235 #endif
236
237 #ifdef BUILD_GRAPH
238
239 #define IF_EDGE_HASH(e) ((e)->src)
240 #define IF_NODE_HASH(n) ((n)->nnr)
241
242 static int if_edge_cmp(const void *p1, const void *p2, size_t size)
243 {
244         const if_edge_t *e1 = p1;
245         const if_edge_t *e2 = p2;
246
247         return !(e1->src == e2->src && e1->tgt == e2->tgt);
248 }
249
250 static int if_node_cmp(const void *p1, const void *p2, size_t size)
251 {
252         const if_node_t *n1 = p1;
253         const if_node_t *n2 = p2;
254
255         return n1->nnr != n2->nnr;
256 }
257
258 static INLINE if_edge_t *edge_init(if_edge_t *edge, int src, int tgt)
259 {
260         /* Bring the smaller entry to src. */
261         if(src > tgt) {
262                 edge->src = tgt;
263                 edge->tgt = src;
264         } else {
265                 edge->src = src;
266                 edge->tgt = tgt;
267         }
268
269         return edge;
270 }
271
272 static INLINE void add_if(const env_t *env, int src, int tgt)
273 {
274         if_edge_t edge;
275         if_node_t node, *src_node, *tgt_node;
276         /* insert edge */
277         edge_init(&edge, src, tgt);
278         set_insert(env->edges, &edge, sizeof(edge), IF_EDGE_HASH(&edge));
279
280         /* insert nodes */
281         node.nnr = src;
282         node.neighb = pset_new_ptr(8);
283         src_node = set_insert(env->nodes, &node, sizeof(node), IF_NODE_HASH(&node));
284         node.nnr = tgt;
285         node.neighb = pset_new_ptr(8);
286         tgt_node = set_insert(env->nodes, &node, sizeof(node), IF_NODE_HASH(&node));
287
288         /* insert neighbors into nodes */
289         pset_insert_ptr(src_node->neighb, tgt_node);
290         pset_insert_ptr(tgt_node->neighb, src_node);
291 }
292
293 static INLINE int are_connected(const env_t *env, int src, int tgt)
294 {
295         if_edge_t edge;
296         edge_init(&edge, src, tgt);
297         return set_find(env->edges, &edge, sizeof(edge), IF_EDGE_HASH(&edge)) != NULL;
298 }
299
300 int ifg_has_edge(const ir_graph *irg, if_node_t *n1, if_node_t* n2) {
301         return are_connected(get_irg_ra_link(irg), n1->nnr, n2->nnr);
302 }
303
304 static void dump_ifg(ir_graph *irg, set *edges, const char *filename)
305 {
306         static const char *colors[] = {
307                 "coral",
308                 "azure",
309                 "bisque",
310                 "aliceblue",
311                 "blanchedalmond",
312                 "deeppink",
313                 "cornsilk",
314                 "blueviolet",
315                 "floralwhite",
316                 "hotpink",
317                 "gainsboro",
318                 "indianred",
319                 "cornflowerblue",
320                 "ghostwhite",
321                 "lightpink",
322                 "palegoldenrod",
323                 "darkslateblue",
324                 "honeydew",
325                 "ivory",
326                 "lavender",
327                 "mediumvioletred",
328                 "indigo",
329                 "lavenderblush",
330                 "lemonchiffon",
331                 "linen",
332                 "pink",
333                 "mintcream",
334                 "red",
335                 "mediumblue",
336                 "mistyrose",
337                 "mediumslateblue",
338                 "moccasin",
339                 "tomato",
340                 "forestgreen",
341                 "midnightblue",
342                 "navajowhite",
343                 "navy",
344                 "oldlace",
345                 "greenyellow",
346                 "navyblue",
347                 "papayawhip",
348                 "lawngreen",
349                 "powderblue",
350                 "peachpuff",
351                 "seashell",
352                 "snow",
353                 "thistle",
354                 "wheat",
355                 "darkkhaki",
356                 "mintcream",
357                 "khaki",
358                 "Magentas",
359                 "whitesmoke",
360                 "peru",
361                 "palegreen",
362                 "blueviolet",
363                 "rosybrown",
364                 "saddlebrown",
365                 "springgreen",
366                 "darkviolet",
367                 "darkslategray",
368                 "dimgray",
369                 "sienna",
370                 "gray",
371                 "tan",
372                 "gray",
373                 "mediumvioletred",
374                 "lightgray",
375                 "Oranges",
376                 "cyan",
377                 "lightslategray",
378                 "darkorange",
379                 "slategray",
380                 "orangered",
381                 "mediumturquoise",
382                 "violet",
383                 "paleturquoise"
384         };
385
386         static const int n_colors = sizeof(colors) / sizeof(colors[0]);
387
388         FILE *f;
389
390         if((f = fopen(filename, "wt")) != NULL) {
391                 bitset_pos_t pos;
392                 int n_edges = 0;
393                 if_edge_t *edge;
394                 bitset_t *bs = bitset_malloc(get_graph_node_count(irg));
395
396                 ir_fprintf(f, "graph \"%F\" {\n", irg);
397                 fprintf(f, "\tnode [shape=box,style=filled]\n");
398
399                 for(edge = set_first(edges); edge; edge = set_next(edges)) {
400                         bitset_set(bs, edge->src);
401                         bitset_set(bs, edge->tgt);
402                         n_edges++;
403                 }
404
405                 fprintf(f, "\tx [label=\"nodes: %u, edges: %d\"]\n", bitset_popcnt(bs), n_edges);
406
407                 bitset_foreach(bs, pos) {
408                         int nr = (int) pos;
409                         ir_node *irn = get_irn_for_graph_nr(irg, nr);
410                         int color = get_irn_color(irn);
411
412                         ir_fprintf(f, "\tn%d [label=\"%n\",color=\"%s\"]\n", nr, irn,
413                                         color >= 0 && color < n_colors ? colors[color] : "black");
414                 }
415
416                 for(edge = set_first(edges); edge; edge = set_next(edges)) {
417                         fprintf(f, "\tn%d -- n%d [len=5]\n", edge->src, edge->tgt);
418                 }
419
420                 fprintf(f, "}\n");
421                 fclose(f);
422
423                 bitset_free(bs);
424         }
425
426 }
427
428 #endif /* BUILD_GRAPH */
429
430
431 /**
432  * Add an interval border to the list of a block's list
433  * of interval border.
434  * @note You always have to create the use before the def.
435  * @param env The environment.
436  * @param head The list head to enqueue the borders.
437  * @param irn The node (value) the border belongs to.
438  * @param pressure The pressure at this point in time.
439  * @param step A time step for the border.
440  * @param is_def Is the border a use or a def.
441  * @return The created border.
442  */
443 static INLINE border_t *border_add(env_t *env, struct list_head *head,
444                         ir_node *irn, unsigned step, unsigned pressure,
445                         unsigned is_def, unsigned is_real)
446 {
447         border_t *b;
448
449         if(!is_def) {
450                 border_t *def;
451
452                 b = obstack_alloc(&env->obst, sizeof(*b));
453
454                 /* also allocate the def and tie it to the use. */
455                 def = obstack_alloc(&env->obst, sizeof(*def));
456                 b->other_end = def;
457                 def->other_end = b;
458
459                 /*
460                  * Set the link field of the irn to the def.
461                  * This strongly relies on the fact, that the use is always
462                  * made before the def.
463                  */
464                 set_irn_link(irn, def);
465
466 #ifdef DEBUG_libfirm
467                 b->magic = BORDER_FOURCC;
468                 def->magic = BORDER_FOURCC;
469 #endif
470         }
471
472         /*
473          * If the def is encountered, the use was made and so was the
474          * the def node (see the code above). It was placed into the
475          * link field of the irn, so we can get it there.
476          */
477         else {
478                 b = get_irn_link(irn);
479
480 #ifdef DEBUG_libfirm
481                 assert(b && b->magic == BORDER_FOURCC && "Illegal border encountered");
482 #endif
483         }
484
485         b->pressure = pressure;
486         b->is_def = is_def;
487         b->is_real = is_real;
488         b->irn = irn;
489         b->step = step;
490         list_add_tail(&b->list, head);
491         DBG((dbg, LEVEL_5, "\t\t%s adding %n, step: %d\n",
492                                 is_def ? "def" : "use", irn, step));
493
494         return b;
495 }
496
497 /**
498  * Annotate the register pressure to the nodes and compute
499  * the liveness intervals.
500  * @param block The block to do it for.
501  * @param env_ptr The environment.
502  */
503 static void pressure(ir_node *block, void *env_ptr)
504 {
505 /* Convenience macro for a def */
506 #define border_def(irn, step, real) \
507         border_add(env, head, irn, step, pressure--, 1, real)
508
509 /* Convenience macro for a use */
510 #define border_use(irn, step, real) \
511         border_add(env, head, irn, step, ++pressure, 0, real)
512
513         env_t *env = env_ptr;
514         bitset_t *live = env->live;
515         ir_node *irn;
516
517         int i, n;
518         unsigned step = 0;
519         unsigned pressure = 0;
520         struct list_head *head;
521         pset *live_in = get_live_in(block);
522         pset *live_end = get_live_end(block);
523   const arch_register_class_t *cls = env->cls;
524
525         DBG((dbg, LEVEL_1, "Computing pressure in block %n\n", block));
526         bitset_clear_all(live);
527
528         /* Set up the border list in the block info */
529         head = &get_ra_block_info(block)->border_head;
530         INIT_LIST_HEAD(head);
531
532         /*
533          * Make final uses of all values live out of the block.
534          * They are neccessary to build up real intervals.
535          */
536         for(irn = pset_first(live_end); irn; irn = pset_next(live_end)) {
537                 DBG((dbg, LEVEL_3, "\tMaking live: %n/%d\n", irn, get_irn_graph_nr(irn)));
538                 bitset_set(live, get_irn_graph_nr(irn));
539     if(arch_irn_has_reg_class(env->arch_env, irn, 0, cls))
540       border_use(irn, step, 0);
541         }
542
543         ++step;
544
545         /*
546          * Determine the last uses of a value inside the block, since they are
547          * relevant for the interval borders.
548          */
549         sched_foreach_reverse(block, irn) {
550                 DBG((dbg, LEVEL_1, "\tinsn: %n, pressure: %d\n", irn, pressure));
551                 DBG((dbg, LEVEL_2, "\tlive: %b\n", live));
552
553                 /* Erase the color of each node encountered. */
554                 set_irn_color(irn, NO_COLOR);
555
556     /*
557      * If the node defines some value, which can put into a
558      * register of the current class, make a border for it.
559      */
560                 if(arch_irn_has_reg_class(env->arch_env, irn, 0, cls)) {
561       bitset_pos_t elm;
562                         int nr = get_irn_graph_nr(irn);
563
564                         bitset_clear(live, nr);
565                         border_def(irn, step, 1);
566
567 #ifdef BUILD_GRAPH
568       bitset_foreach(live, elm)
569         add_if(env, nr, (int) elm);
570 #endif
571                 }
572
573                 /*
574                  * If the node is no phi node we can examine the uses.
575                  */
576                 if(!is_Phi(irn)) {
577                         for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
578                                 ir_node *op = get_irn_n(irn, i);
579
580                                 if(arch_irn_has_reg_class(env->arch_env, op, 0, cls)) {
581                                         int nr = get_irn_graph_nr(op);
582
583                                         DBG((dbg, LEVEL_4, "\t\tpos: %d, use: %n\n", i, op));
584
585                                         if(!bitset_is_set(live, nr)) {
586                                                 border_use(op, step, 1);
587                                                 bitset_set(live, nr);
588                                         }
589                                 }
590                         }
591                 }
592
593                 ++step;
594         }
595
596         /*
597          * Add initial defs for all values live in.
598          */
599         for(irn = pset_first(live_in); irn; irn = pset_next(live_in)) {
600                 if(arch_irn_has_reg_class(env->arch_env, irn, 0, cls)) {
601
602                         /* Mark the value live in. */
603                         bitset_set(live, get_irn_graph_nr(irn));
604
605                         /* Add the def */
606                         border_def(irn, step, 0);
607                 }
608         }
609 }
610
611 static void assign(ir_node *block, void *env_ptr)
612 {
613         env_t *env = env_ptr;
614         struct obstack *obst = &env->obst;
615         bitset_t *live = env->live;
616         bitset_t *colors = env->colors;
617         bitset_t *in_colors = env->in_colors;
618   const arch_register_class_t *cls = env->cls;
619
620         /* Mark the obstack level and allocate the temporary tmp_colors */
621         void *obstack_level = obstack_base(obst);
622         /*bitset_t *tmp_colors = bitset_obstack_alloc(obst, env->colors_n);*/
623
624         const ir_node *irn;
625         border_t *b;
626         struct list_head *head = &get_ra_block_info(block)->border_head;
627         pset *live_in = get_live_in(block);
628
629         bitset_clear_all(live);
630         bitset_clear_all(colors);
631         bitset_clear_all(in_colors);
632
633         DBG((dbg, LEVEL_4, "Assigning colors for block %n\n", block));
634         DBG((dbg, LEVEL_4, "\tusedef chain for block\n"));
635         list_for_each_entry(border_t, b, head, list) {
636                 DBG((dbg, LEVEL_4, "\t%s %n/%d\n", b->is_def ? "def" : "use",
637                                         b->irn, get_irn_graph_nr(b->irn)));
638         }
639
640         /*
641          * Add initial defs for all values live in.
642          * Since their colors have already been assigned (The dominators were
643          * allocated before), we have to mark their colors as used also.
644          */
645         for(irn = pset_first(live_in); irn; irn = pset_next(live_in)) {
646                 if(arch_irn_has_reg_class(env->arch_env, irn, 0, cls)) {
647       const arch_register_t *reg = arch_get_irn_register(env->arch_env, irn, 0);
648       int col;
649
650       assert(reg && "Nodfe must have been assigned a register");
651                         col = arch_register_get_index(reg);
652
653                         /* Mark the color of the live in value as used. */
654                         bitset_set(colors, col);
655                         bitset_set(in_colors, col);
656
657                         /* Mark the value live in. */
658                         bitset_set(live, get_irn_graph_nr(irn));
659                 }
660         }
661
662         /*
663          * Mind that the sequence of defs from back to front defines a perfect
664          * elimination order. So, coloring the definitions from first to last
665          * will work.
666          */
667         list_for_each_entry_reverse(border_t, b, head, list) {
668                 ir_node *irn = b->irn;
669                 int nr = get_irn_graph_nr(irn);
670
671                 /*
672                  * Assign a color, if it is a local def. Global defs already have a
673                  * color.
674                  */
675                 if(b->is_def && !is_live_in(block, irn)) {
676       const arch_register_t *reg;
677                         int col = NO_COLOR;
678
679                         DBG((dbg, LEVEL_4, "\tcolors in use: %b\n", colors));
680
681       col = bitset_next_clear(colors, 0);
682       reg = arch_register_for_index(env->cls, col);
683
684       assert(arch_get_irn_register(env->arch_env, irn, 0) == NULL
685           && "This node must not have been assigned a register yet");
686                         assert(!bitset_is_set(live, nr) && "Value's definition must not have been encountered");
687
688                         bitset_set(colors, col);
689                         bitset_set(live, nr);
690
691                         arch_set_irn_register(env->arch_env, irn, 0, reg);
692                         DBG((dbg, LEVEL_1, "\tassigning register %s(%d) to %n\n",
693             arch_register_get_name(reg), col, irn));
694                 }
695
696                 /* Clear the color upon a use. */
697                 else if(!b->is_def) {
698       const arch_register_t *reg = arch_get_irn_register(env->arch_env, irn, 0);
699                         int col;
700
701       assert(reg && "Register must have been assigned");
702
703       col = arch_register_get_index(reg);
704                         assert(bitset_is_set(live, nr) && "Cannot have a non live use");
705
706                         bitset_clear(colors, col);
707                         bitset_clear(live, nr);
708                 }
709         }
710
711         /* Free the auxillary data on the obstack. */
712         obstack_free(obst, obstack_level);
713 }
714
715 void be_ra_chordal_init(void)
716 {
717         dbg = firm_dbg_register(DBG_BERA);
718         firm_dbg_set_mask(dbg, 0);
719 }
720
721 void be_ra_chordal(ir_graph *irg,
722     const arch_env_t *arch_env,
723     const arch_register_class_t *cls)
724 {
725         int node_count = get_graph_node_count(irg);
726   int colors_n = arch_register_class_n_regs(cls);
727         env_t *env = malloc(sizeof(*env));
728
729         if(get_irg_dom_state(irg) != dom_consistent)
730                 compute_doms(irg);
731
732         obstack_init(&env->obst);
733
734 #ifdef BUILD_GRAPH
735         env->edges = new_set(if_edge_cmp, node_count);
736         env->nodes = new_set(if_node_cmp, node_count);
737 #endif
738
739         env->live = bitset_obstack_alloc(&env->obst, node_count);
740         env->colors = bitset_obstack_alloc(&env->obst, colors_n);
741         env->in_colors = bitset_obstack_alloc(&env->obst, colors_n);
742         env->colors_n = colors_n;
743   env->cls = cls;
744   env->arch_env = arch_env;
745   env->irg = irg;
746
747         /* First, determine the pressure */
748         dom_tree_walk_irg(irg, pressure, NULL, env);
749
750         /* Insert probable spills */
751         be_ra_chordal_spill(irg);
752
753         /* Assign the colors */
754         dom_tree_walk_irg(irg, assign, NULL, env);
755
756 #ifdef DUMP_IFG
757         {
758                 char buf[128];
759
760                 ir_snprintf(buf, sizeof(buf), "ifg_%F.dot", irg);
761                 dump_ifg(irg, env->edges, buf);
762         }
763 #endif
764
765 #ifdef DUMP_INTERVALS
766   dump_intv_cfg(env);
767 #endif
768
769         set_irg_ra_link(irg, env);
770 }
771
772 void be_ra_chordal_done(ir_graph *irg)
773 {
774         env_t *env = get_irg_ra_link(irg);
775
776 #ifdef BUILD_GRAPH
777         {
778                 if_node_t *ifn;
779                 for(ifn = set_first(env->nodes); ifn; ifn = set_next(env->nodes))
780                         free(ifn->neighb);
781                 free(env->nodes);
782                 free(env->edges);
783         }
784 #endif
785
786         obstack_free(&env->obst, NULL);
787         free(env);
788 }
789
790 int phi_ops_interfere(const ir_node *a, const ir_node *b)
791 {
792 #ifdef BUILD_GRAPH
793         ir_graph *irg = get_irn_irg(a);
794         env_t *env = get_irg_ra_link(irg);
795
796         assert(irg == get_irn_irg(b) && "Both nodes must be in the same graph");
797
798         return are_connected(env, get_irn_graph_nr(a), get_irn_graph_nr(b));
799 #else
800         return values_interfere(a, b);
801 #endif /* BUILD_GRAPH */
802 }
803
804 #ifdef BUILD_GRAPH
805 /** TODO remove this
806  * Deprecated. Use be_ra_get_ifg_edges instead.
807  */
808 set *be_ra_get_ifg(ir_graph *irg) {
809         return ((env_t *)get_irg_ra_link(irg))->edges;
810 }
811
812 set *be_ra_get_ifg_edges(ir_graph *irg) {
813         return ((env_t *)get_irg_ra_link(irg))->edges;
814 }
815
816 set *be_ra_get_ifg_nodes(ir_graph *irg) {
817         return ((env_t *)get_irg_ra_link(irg))->nodes;
818 }
819
820 #endif