Bugfixes
[libfirm] / ir / be / beraextern.c
1 /**
2  * Author:      Daniel Grund
3  * Date:                17.01.2006
4  * Copyright:   (c) Universitaet Karlsruhe
5  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
6  *
7  * Implementation of the RA-Interface for an external, (non-SSA) register allocator.
8  *
9  * The external register allocator is a program:
10  *    PROG -i INPUTFILE -o OUTPUTFILE
11  *
12  *   1) Input file defines the interference graph
13  *   2) Output file contains the instructions to perform
14  *
15
16
17 The input file format
18 ----------------------
19
20 inputfile       ::= regs nodes interf affinities .
21
22 regs            ::= 'regs' regcount .                                           // Anzahl der register (0..regcount-1), die zur Verfuegung stehen
23
24 nodes           ::= 'nodes' '{' node* '}' .                                     // All nodes in the graph
25
26 node            ::= node-info
27                           | node-info '<' reg-nr '>' .                          // Reg-nr is present in case of constraints
28
29 node-info       ::= node-nr spill-costs .
30
31 interf          ::= 'interferences' '{' edge* '}' .                     // Interference edges of the graph
32
33 affinities      ::= 'affinities' '{' edge* '}' .                        // Affinity edges of the graph
34
35 edge            ::= '(' node-nr ',' node-nr ')' .
36
37
38 regcount, node-nr ::= int32 .
39 spill-costs ::= uint32 .
40
41 The output file format
42 -----------------------
43
44 outputfile      ::= spills | allocs .
45
46 spills          ::= 'spills' node-nr+ .
47
48 allocs          ::= 'allocs' alloc* .
49
50 alloc           ::= node-nr reg-nr .
51
52
53 ******** End of file format docu ********/
54
55 #ifdef HAVE_CONFIG_H
56 #include "config.h"
57 #endif
58
59 #ifdef WIN32
60 #include <malloc.h>
61 #else
62 #include <alloca.h>
63 #endif
64
65 #include <stdio.h>
66 #include <stdlib.h>
67 #include <limits.h>
68 #ifdef WITH_LIBCORE
69 #include <libcore/lc_opts.h>
70 #include <libcore/lc_opts_enum.h>
71 #endif
72
73 #include "set.h"
74 #include "pset.h"
75 #include "pmap.h"
76 #include "bitset.h"
77
78 #include "irprintf_t.h"
79 #include "irnode_t.h"
80 #include "irgraph_t.h"
81 #include "irgwalk.h"
82 #include "iredges_t.h"
83 #include "irdom_t.h"
84 #include "phiclass.h"
85
86 #include "beraextern.h"
87 #include "bearch.h"
88 #include "benode_t.h"
89 #include "beirgmod.h"
90 #include "besched.h"
91 #include "beutil.h"
92 #include "belive_t.h"
93
94 #define DBG_LEVEL 2
95
96 typedef struct _var_info_t var_info_t;
97
98 /**
99  * Environment with all the needed stuff
100  */
101 typedef struct _be_raext_env_t {
102         firm_dbg_module_t *dbg;
103         arch_env_t *aenv;
104         const arch_register_class_t *cls;
105         ir_graph *irg;
106         dom_front_info_t *dom_info;
107
108         FILE *f;                                /**< file handle used for out- and input file */
109         set *vars;                              /**< contains all var_info_t */
110         int n_cls_vars;                 /**< length of the array cls_vars */
111         var_info_t **cls_vars;  /**< only the var_infos for current cls. needed for double iterating */
112 } be_raext_env_t;
113
114
115
116 /******************************************************************************
117     _    _      _
118    | |  | |    | |
119    | |__| | ___| |_ __   ___ _ __ ___
120    |  __  |/ _ \ | '_ \ / _ \ '__/ __|
121    | |  | |  __/ | |_) |  __/ |  \__ \
122    |_|  |_|\___|_| .__/ \___|_|  |___/
123                  | |
124                  |_|
125  *****************************************************************************/
126
127
128 #define pset_foreach(pset, irn)  for(irn=pset_first(pset); irn; irn=pset_next(pset))
129 #define set_foreach(set, e)  for(e=set_first(set); e; e=set_next(set))
130
131 /**
132  * Checks if _the_ result of the irn belongs to the
133  * current register class (raenv->cls)
134  * NOTE: Only the first result is checked.
135  */
136 #define is_res_in_reg_class(irn) arch_irn_has_reg_class(raenv->aenv, irn, -1, raenv->cls)
137
138 static INLINE ir_node *get_first_non_phi(pset *s) {
139         ir_node *irn;
140
141         pset_foreach(s, irn)
142                 if (!is_Phi(irn)) {
143                         pset_break(s);
144                         return irn;
145                 }
146
147         assert(0 && "There must be a non-phi-irn in this");
148         return NULL;
149 }
150
151 static INLINE ir_node *get_first_phi(pset *s) {
152         ir_node *irn;
153
154         pset_foreach(s, irn)
155                 if (is_Phi(irn)) {
156                         pset_break(s);
157                         return irn;
158                 }
159
160         assert(0 && "There must be a phi in this");
161         return NULL;
162 }
163
164 /******************************************************************************
165     _____                _            _____            _
166    / ____|              | |          / ____|          (_)
167   | |     ___  _ __  ___| |_ _ __   | |     ___  _ __  _  ___  ___
168   | |    / _ \| '_ \/ __| __| '__|  | |    / _ \| '_ \| |/ _ \/ __|
169   | |___| (_) | | | \__ \ |_| |     | |___| (_) | |_) | |  __/\__ \
170    \_____\___/|_| |_|___/\__|_|      \_____\___/| .__/|_|\___||___/
171                                                 | |
172                                                 |_|
173  *****************************************************************************/
174
175 static void handle_constraints_walker(ir_node *irn, void *env) {
176         be_raext_env_t *raenv = env;
177         arch_register_req_t req;
178         int pos, max;
179
180         /* handle output constraints
181          * user -> irn    becomes    user -> cpy -> irn
182          */
183         arch_get_register_req(raenv->aenv, &req, irn, -1);
184         if (arch_register_req_is(&req, limited)) {
185                 ir_node *cpy = be_new_Copy(req.cls, raenv->irg, get_nodes_block(irn), irn);
186                 const ir_edge_t *edge;
187
188                 /* all users of the irn use the copy instead */
189                 sched_add_after(irn, cpy);
190                 foreach_out_edge(irn, edge)
191                         set_irn_n(edge->src, edge->pos, cpy);
192         }
193
194
195         /* handle input constraints by converting them into output constraints
196          * of copies of the former argument
197          * irn -> arg   becomes  irn -> copy -> arg
198      */
199         for (pos = 0, max = get_irn_arity(irn); pos<max; ++pos) {
200                 arch_get_register_req(raenv->aenv, &req, irn, pos);
201                 if (arch_register_req_is(&req, limited)) {
202                         ir_node *arg = get_irn_n(irn, pos);
203                         ir_node *cpy = be_new_Copy(req.cls, raenv->irg, get_nodes_block(irn), arg);
204
205                         /* use the copy instead */
206                         sched_add_before(irn, cpy);
207                         set_irn_n(irn, pos, cpy);
208
209                         /* set an out constraint for the copy */
210                         be_set_constr_limited(cpy, -1, &req);
211                 }
212         }
213 }
214
215 static void handle_constraints(be_raext_env_t *raenv) {
216         irg_block_walk_graph(raenv->irg, NULL, handle_constraints_walker, raenv);
217 }
218
219
220 /******************************************************************************
221      _____ _____              _____            _
222     / ____/ ____|  /\        |  __ \          | |
223    | (___| (___   /  \ ______| |  | | ___  ___| |_ _ __
224     \___ \\___ \ / /\ \______| |  | |/ _ \/ __| __| '__|
225     ____) |___) / ____ \     | |__| |  __/\__ \ |_| |
226    |_____/_____/_/    \_\    |_____/ \___||___/\__|_|
227
228  *****************************************************************************/
229
230 #define mark_as_done(irn, pos)                  set_irn_link(irn, INT_TO_PTR(pos+1))
231 #define has_been_done(irn, pos)                 (PTR_TO_INT(get_irn_link(irn)) > pos)
232
233 /**
234  * Insert a copy for the argument of @p start_phi found at position @p pos.
235  * Also searches a phi-loop of arbitrary length to detect and resolve
236  *   the class of phi-swap-problems. To search for a loop recursion is used.
237  *
238  * 1) Simplest case (phi with a non-phi arg):
239  *     A single copy is inserted.
240  *
241  * 2) Phi chain (phi (with phi-arg)* with non=phi arg):
242  *     Several copies are placed, each after returning from recursion.
243  *
244  * 3) Phi-loop:
245  *     On detection a loop breaker is inserted, which is a copy of the start_phi.
246  *     This copy then pretends beeing the argumnent of the last phi.
247  *     Now case 2) can be used.
248  *
249  * The values of @p start_phi and @p pos never change during recursion.
250  *
251  * @p raenv      Environment with all the stuff needed
252  * @p start_phi  Phi node to process
253  * @p pos        Argument position to insert copy/copies for
254  * @p curr_phi   Phi node currently processed during recursion. Equals start_phi on initial call
255  *
256  * @return NULL  If no copy is necessary
257  *         NULL  If the phi has already been processed at this pos
258  *               Link field is used to keep track of processed positions
259  *         In all other cases the ir_node *copy which was placed is returned.
260  */
261 static ir_node *insert_copies(be_raext_env_t *raenv, ir_node *start_phi, int pos, ir_node *curr_phi) {
262         ir_node *arg = get_irn_n(curr_phi, pos);
263         ir_node *arg_blk = get_nodes_block(arg);
264         ir_node *pred_blk = get_Block_cfgpred_block(get_nodes_block(curr_phi), pos);
265         ir_node *curr_cpy, *last_cpy;
266
267         assert(is_Phi(start_phi) && is_Phi(curr_phi));
268
269         if (has_been_done(start_phi, pos))
270                 return NULL;
271
272         /* In case this is a 'normal' phi we insert into
273          * the schedule before the pred_blk irn */
274         last_cpy = pred_blk;
275
276         /* If we detect a loop stop recursion. */
277         if (arg == start_phi) {
278                 ir_node *loop_breaker;
279                 if (start_phi == curr_phi) {
280                         /* Phi directly uses itself. No copy necessary */
281                         return NULL;
282                 }
283
284                 /* At least 2 phis are involved */
285                 /* Insert a loop breaking copy (an additional variable T) */
286                 loop_breaker = be_new_Copy(raenv->cls, raenv->irg, pred_blk, start_phi);
287                 sched_add_before(pred_blk, loop_breaker);
288
289                 arg = loop_breaker;
290         }
291
292         /* If arg is a phi in the same block we have to continue search */
293         if (is_Phi(arg) && arg_blk == get_nodes_block(start_phi))
294                 last_cpy = insert_copies(raenv, start_phi, pos, arg);
295
296         /* Insert copy of argument (may be the loop-breaker) */
297         curr_cpy = be_new_Copy(raenv->cls, raenv->irg, pred_blk, arg);
298         set_irn_n(curr_phi, pos, curr_cpy);
299         mark_as_done(curr_phi, pos);
300         sched_add_before(last_cpy, curr_cpy);
301         return curr_cpy;
302 }
303
304
305 /**
306  * Perform simple SSA-destruction with copies.
307  * The order of processing _must_ be
308  *  for all positions {
309  *    for all phis {
310  *      doit
311  *    }
312  *  }
313  * else the magic to keep track of processed phi-positions will fail in
314  * function 'insert_copies'
315  */
316 static void ssa_destr_simple_walker(ir_node *blk, void *env) {
317         be_raext_env_t *raenv = env;
318         int pos, max;
319         ir_node *phi;
320
321         /* for all argument positions of the phis */
322         for (pos=0, max=get_irn_arity(blk); pos<max; ++pos) {
323
324                 /* for all phi nodes (which are scheduled first) */
325                 sched_foreach(blk, phi) {
326                         if (!is_Phi(phi))
327                                 break;
328
329                         raenv->cls = arch_get_irn_reg_class(raenv->aenv, phi, -1);
330                         insert_copies(raenv, phi, pos, phi);
331                 }
332         }
333 }
334
335
336 static void ssa_destr_simple(be_raext_env_t *raenv) {
337         be_clear_links(raenv->irg);
338         irg_block_walk_graph(raenv->irg, ssa_destr_simple_walker, NULL, raenv);
339 }
340
341
342 static void ssa_destr_rastello(be_raext_env_t *raenv) {
343         assert(0 && "NYI");
344         exit(0xDeadBeef);
345         /*
346         phi_class_compute(raenv->irg);
347         irg_block_walk_graph(irg, ssa_destr_rastello, NULL, &raenv);
348         */
349 }
350
351 /******************************************************************************
352    __      __   _       ___   __      __
353    \ \    / /  | |     |__ \  \ \    / /
354     \ \  / /_ _| |___     ) |  \ \  / /_ _ _ __ ___
355      \ \/ / _` | / __|   / /    \ \/ / _` | '__/ __|
356       \  / (_| | \__ \  / /_     \  / (_| | |  \__ \
357        \/ \__,_|_|___/ |____|     \/ \__,_|_|  |___/
358  *****************************************************************************/
359
360 /**
361  * This struct maps a variable (nr) to the values belonging to this variable
362  */
363 struct _var_info_t {
364         int var_nr;             /* the key */
365         pset *values;   /* the ssa-values belonging to this variable */
366 };
367
368 #define SET_REMOVED -1
369
370 /**
371  * The link field of an irn points to the var_info struct
372  * representing the corresponding variable.
373  */
374 #define set_var_info(irn, vi)                           set_irn_link(irn, vi)
375 #define get_var_info(irn)                                       ((var_info_t *)get_irn_link(irn))
376
377 #define HASH_VAR_NR(var_nr) var_nr
378
379 static int compare_var_infos(const void *e1, const void *e2, size_t size) {
380         const var_info_t *v1 = e1;
381         const var_info_t *v2 = e2;
382
383         if (v1->var_nr == SET_REMOVED || v2->var_nr == SET_REMOVED)
384                 return 1;
385
386         return v1->var_nr != v2->var_nr;
387 }
388
389 static INLINE var_info_t *var_find(set *vars, int var_nr) {
390         var_info_t vi;
391         vi.var_nr = var_nr;
392
393         return set_find(vars, &vi, sizeof(vi), HASH_VAR_NR(var_nr));
394 }
395
396 static INLINE var_info_t *var_find_or_insert(set *vars, int var_nr) {
397         var_info_t vi, *found;
398         memset(&vi, 0, sizeof(vi));
399         vi.var_nr = var_nr;
400
401         found = set_insert(vars, &vi, sizeof(vi), HASH_VAR_NR(var_nr));
402
403         if (!found->values)
404                 found->values  = pset_new_ptr(1);
405
406         return found;
407 }
408
409 /**
410  * Adds a value to a variable. Sets all pointers accordingly.
411  */
412 static INLINE var_info_t *var_add_value(be_raext_env_t *raenv, int var_nr, ir_node *irn) {
413         var_info_t *vi = var_find_or_insert(raenv->vars, var_nr);
414
415         /* var 2 value mapping */
416         pset_insert_ptr(vi->values, irn);
417
418         /* value 2 var mapping */
419         set_var_info(irn, vi);
420
421         return vi;
422 }
423
424 static INLINE pset *get_var_values(be_raext_env_t *raenv, int var_nr) {
425         var_info_t *vi = var_find(raenv->vars, var_nr);
426         assert(vi && "Variable does not exist");
427         return vi->values;
428 }
429
430 /**
431  * Define variables (numbers) for all SSA-values.
432  * All values in a phi class get assigned the same variable name.
433  * The link field maps values to the var-name
434  */
435 static void values_to_vars(ir_node *irn, void *env) {
436         be_raext_env_t *raenv = env;
437         int nr;
438         pset *vals;
439
440         if(arch_get_irn_reg_class(raenv->aenv, irn, -1) == NULL)
441                 return;
442
443         vals = get_phi_class(irn);
444
445         if (vals) {
446                 nr = get_irn_node_nr(get_first_phi(vals));
447         } else {
448                 /* not a phi class member, value == var */
449                 nr = get_irn_node_nr(irn);
450                 vals = pset_new_ptr(1);
451                 pset_insert_ptr(vals, irn);
452         }
453
454         /* values <--> var mapping */
455         pset_foreach(vals, irn)
456                 var_add_value(raenv, nr, irn);
457 }
458
459
460 /******************************************************************************
461     _____
462    |  __ \
463    | |  | |_   _ _ __ ___  _ __   ___ _ __
464    | |  | | | | | '_ ` _ \| '_ \ / _ \ '__|
465    | |__| | |_| | | | | | | |_) |  __/ |
466    |_____/ \__,_|_| |_| |_| .__/ \___|_|
467                           | |
468                           |_|
469  *****************************************************************************/
470
471
472 static void extract_vars_of_cls(be_raext_env_t *raenv) {
473         int count = 0;
474         var_info_t *vi;
475
476         raenv->cls_vars = malloc(set_count(raenv->vars) * sizeof(*raenv->cls_vars));
477         assert(raenv->cls_vars);
478
479         set_foreach(raenv->vars, vi)
480                 if (is_res_in_reg_class(get_first_non_phi(vi->values)))
481                         raenv->cls_vars[count++] = vi;
482
483         raenv->cls_vars = realloc(raenv->cls_vars, count * sizeof(*raenv->cls_vars));
484         assert(raenv->cls_vars);
485
486         raenv->n_cls_vars = count;
487 }
488
489
490 /**
491  * Check if node irn has a limited-constraint at position pos.
492  * If yes, dump it to FILE raenv->f
493  */
494 static INLINE void dump_constraint(be_raext_env_t *raenv, ir_node *irn, int pos) {
495         bitset_t *bs = bitset_alloca(raenv->cls->n_regs);
496         arch_register_req_t req;
497
498         arch_get_register_req(raenv->aenv, &req, irn, pos);
499         if (arch_register_req_is(&req, limited)) {
500                 int reg_nr;
501                 req.limited(req.limited_env, bs);
502                 reg_nr = bitset_next_set(bs, 0);
503                 fprintf(raenv->f, "<%d>", reg_nr);
504                 assert(-1 == bitset_next_set(bs, reg_nr+1) && "Constraints with more than 1 possible register are not supported");
505         }
506 }
507
508 static INLINE unsigned int get_spill_costs(be_raext_env_t *raenv, var_info_t *vi) {
509         ir_node *irn;
510         int n_spills=0, n_reloads=0;
511
512         pset_foreach(vi->values, irn) {
513                 if (arch_irn_is_ignore(raenv->aenv, irn)) {
514                         pset_break(vi->values);
515                         return UINT_MAX;
516                 }
517
518                 if (is_Phi(irn)) {
519                         /* number of reloads is the number of non-phi uses of all values of this var */
520                         const ir_edge_t *edge;
521                         foreach_out_edge(irn, edge)
522                                 if (!is_Phi(edge->src))
523                                         n_reloads++;
524                 } else {
525                         /* number of spills is the number of non-phi values for this var */
526                         n_spills++;
527                 }
528         }
529
530         return n_spills + n_reloads;
531 }
532
533 static void dump_nodes(be_raext_env_t *raenv) {
534         FILE *f = raenv->f;
535         int i;
536
537         fprintf(f, "\nnodes {\n");
538
539         for (i=0; i<raenv->n_cls_vars; ++i) {
540                 var_info_t *vi = raenv->cls_vars[i];
541
542                 if (vi->var_nr == SET_REMOVED)
543                         continue;
544
545                 fprintf(f, "%d %u", vi->var_nr, get_spill_costs(raenv, vi));
546                 dump_constraint(raenv, get_first_non_phi(vi->values), -1);
547                 fprintf(f, "\n");
548         }
549
550         fprintf(f, "}\n");
551 }
552
553
554 static void dump_interferences(be_raext_env_t *raenv) {
555         int i,o;
556         var_info_t *vi1, *vi2;
557         ir_node *irn1, *irn2;
558         FILE *f = raenv->f;
559
560         fprintf(f, "\ninterferences {\n");
561
562         for (i=0; i<raenv->n_cls_vars; ++i) {
563                 vi1 = raenv->cls_vars[i];
564
565                 if (vi1->var_nr == SET_REMOVED)
566                         continue;
567
568                 for (o=i+1; o<raenv->n_cls_vars; ++o) {
569                         vi2 = raenv->cls_vars[o];
570
571                         if (vi2->var_nr == SET_REMOVED)
572                                 continue;
573
574                         pset_foreach(vi1->values, irn1)
575                                 pset_foreach(vi2->values, irn2)
576                                         if (values_interfere(irn1, irn2)) {
577                                                 pset_break(vi1->values);
578                                                 pset_break(vi2->values);
579                                                 fprintf(f, "(%d, %d)\n", vi1->var_nr, vi2->var_nr);
580                                         }
581                 }
582         }
583         fprintf(f, "}\n");
584 }
585
586
587 static void dump_affinities_walker(ir_node *irn, void *env) {
588         be_raext_env_t *raenv = env;
589         arch_register_req_t req;
590         int pos, max;
591         var_info_t *vi1, *vi2;
592
593         vi1 = get_var_info(irn);
594
595         /* copies have affinities */
596         /* TODO? remove this case by adding should_be_equal requirements */
597         if (arch_irn_classify(raenv->aenv, irn) == arch_irn_class_copy) {
598                 vi2 = get_var_info(get_irn_n(irn, 0));
599
600                 fprintf(raenv->f, "(%d, %d)\n",  vi1->var_nr, vi2->var_nr);
601         }
602
603
604         /* should_be_equal constraints are affinites */
605         for (pos = 0, max = get_irn_arity(irn); pos<max; ++pos) {
606                 arch_get_register_req(raenv->aenv, &req, irn, pos);
607
608                 if (arch_register_req_is(&req, should_be_same)) {
609                         vi2 = get_var_info(req.other_same);
610
611                         fprintf(raenv->f, "(%d, %d)\n",  vi1->var_nr, vi2->var_nr);
612                 }
613         }
614 }
615
616
617 static void dump_affinities(be_raext_env_t *raenv) {
618         fprintf(raenv->f, "\naffinities {\n");
619         irg_walk_graph(raenv->irg, NULL, dump_affinities_walker, raenv);
620         fprintf(raenv->f, "}\n");
621 }
622
623 /**
624  * Dump all information needed by the external
625  * register allocator to a single file.
626  */
627 static void dump_to_file(be_raext_env_t *raenv, char *filename) {
628         FILE *f;
629
630         if (!(f = fopen(filename, "wt"))) {
631                 fprintf(stderr, "Could not open file %s for writing\n", filename);
632                 assert(0);
633                 exit(0xdeadbeef);
634         }
635         raenv->f = f;
636
637         /* dump register info */
638         fprintf(f, "regs %d\n", arch_register_class_n_regs(raenv->cls));
639
640         /* dump the interference graph */
641         dump_nodes(raenv);
642         dump_interferences(raenv);
643         dump_affinities(raenv);
644
645         fclose(f);
646 }
647
648 /******************************************************************************
649     ______                     _
650    |  ____|                   | |
651    | |__  __  _____  ___ _   _| |_ ___
652    |  __| \ \/ / _ \/ __| | | | __/ _ \
653    | |____ >  <  __/ (__| |_| | ||  __/
654    |______/_/\_\___|\___|\__,_|\__\___|
655  *****************************************************************************/
656
657 /**
658  * Execute the external register allocator specified in the
659  * firm-option firm.be.ra.ext.callee
660  */
661 static void execute(char *prog_to_call, char *out_file, char *result_file) {
662         char cmd_line[1024];
663         int ret_status;
664
665         snprintf(cmd_line, sizeof(cmd_line), "%s -i %s -o %s", prog_to_call, out_file, result_file);
666
667         ret_status = system(cmd_line);
668         assert(ret_status != -1 && "Invokation of external register allocator failed");
669 }
670
671 /******************************************************************************
672                          _         _____                 _ _
673        /\               | |       |  __ \               | | |
674       /  \   _ __  _ __ | |_   _  | |__) |___  ___ _   _| | |_
675      / /\ \ | '_ \| '_ \| | | | | |  _  // _ \/ __| | | | | __|
676     / ____ \| |_) | |_) | | |_| | | | \ \  __/\__ \ |_| | | |_
677    /_/    \_\ .__/| .__/|_|\__, | |_|  \_\___||___/\__,_|_|\__|
678             | |   | |       __/ |
679             |_|   |_|      |___/
680  *****************************************************************************/
681
682 /**
683  * Spill a variable and add reloads before all uses.
684  */
685 static INLINE void var_add_spills_and_reloads(be_raext_env_t *raenv, int var_nr) {
686         var_info_t *vi = var_find(raenv->vars, var_nr);
687         ir_node *spill=NULL, *ctx, *irn;
688         const ir_edge_t *edge, *ne;
689         pset *spills  = pset_new_ptr(4);        /* the spills of this variable */
690         pset *reloads = pset_new_ptr(4);        /* the reloads of this variable */
691         int new_size, n_spills, n_reloads;
692
693         assert(vi && "Variable nr does not exist!");
694         assert(pset_count(vi->values) && "There are no values associated to this variable");
695
696         /* the spill context is set to an arbitrary node of the phi-class,
697          * or the node itself if it is not member of a phi class
698          */
699         if (pset_count(vi->values) == 1)
700                 ctx = get_first_non_phi(vi->values);
701         else
702                 ctx = get_first_phi(vi->values);
703
704         DBG((raenv->dbg, LEVEL_2, "Spill context: %+F\n", ctx));
705
706         /* for each value of this variable insert the spills */
707         pset_foreach(vi->values, irn) {
708                 if (is_Phi(irn)) {
709                         sched_remove(irn);
710                         continue;
711                 }
712
713                 /* all ordinary nodes must be spilled */
714                 DBG((raenv->dbg, LEVEL_2, "  spilling %+F\n", irn));
715                 spill = be_spill(raenv->aenv, irn, ctx);
716
717                 /* remember the spill */
718                 pset_insert_ptr(spills, spill);
719         }
720
721         assert(spill && "There must be at least one non-phi-node");
722
723         /* insert reloads and wire them arbitrary*/
724         pset_foreach(vi->values, irn)
725                 foreach_out_edge_safe(irn, edge, ne) {
726                         ir_node *reload, *src = edge->src;
727                         if (is_Phi(src) || be_is_Spill(src))
728                                 continue;
729
730                         /* all real uses must be reloaded */
731                         DBG((raenv->dbg, LEVEL_2, "  reloading before %+F\n", src));
732                         reload = be_reload(raenv->aenv, raenv->cls, edge->src, edge->pos, get_irn_mode(get_irn_n(spill, 0)), spill);
733
734                         /* remember the reload */
735                         pset_insert_ptr(reloads, reload);
736                 }
737
738         /* correct the reload->spill pointers... */
739         be_ssa_constr_set(raenv->dom_info, spills);
740
741
742         /****** correct the variable <--> values mapping: ******
743          *
744          *  - if we had a phi class it gets split into several new variables
745          *  - all reloads are new variables
746          */
747         n_spills = pset_count(spills);
748         n_reloads = pset_count(reloads);
749
750         /* first make room for new pointers in the cls_var array */
751         new_size = raenv->n_cls_vars + n_reloads + ((n_spills>1) ? n_spills : 0);
752         raenv->cls_vars = realloc(raenv->cls_vars, (new_size) * sizeof(*raenv->cls_vars));
753         assert(raenv->cls_vars && "Out of mem!?");
754
755         /* if we had a real phi-class, we must... */
756         if (pset_count(spills) > 1) {
757                 /* ...remove the old variable corresponding to the phi class */
758                 vi->var_nr = SET_REMOVED;
759
760                 /* ...add new vars for each non-phi-member */
761                 pset_foreach(spills, irn) {
762                         ir_node *spilled = get_irn_n(irn, 0);
763                         raenv->cls_vars[raenv->n_cls_vars++] = var_add_value(raenv, get_irn_node_nr(spilled), spilled);
764                 }
765         }
766
767         /* add new variables for all reloads */
768         pset_foreach(reloads, irn)
769                 raenv->cls_vars[raenv->n_cls_vars++] = var_add_value(raenv, get_irn_node_nr(irn), irn);
770
771         del_pset(spills);
772         del_pset(reloads);
773 }
774
775 #define INVALID_FILE_FORMAT assert(0 && "Invalid file format.")
776 #define BUFLEN 32
777 #define BUFCONV " %32s "
778
779 /**
780  * Read in the actions performed by the external allocator.
781  * Apply these transformations to the irg.
782  * @return 1 if an allocation was read in. 0 otherwise.
783  */
784 static int read_and_apply_results(be_raext_env_t *raenv, char *filename) {
785         FILE *f;
786         char buf[BUFLEN];
787         int is_allocation = 0;
788
789         if (!(f = fopen(filename, "rt"))) {
790                 fprintf(stderr, "Could not open file %s for reading\n", filename);
791                 assert(0);
792                 exit(0xdeadbeef);
793         }
794         raenv->f = f;
795
796         /* read the action */
797         if (fscanf(f, BUFCONV, buf) != 1)
798                 INVALID_FILE_FORMAT;
799
800         /* do we spill */
801         if (!strcmp(buf, "spills")) {
802                 int var_nr;
803                 while (fscanf(f, " %d ", &var_nr) == 1)
804                         var_add_spills_and_reloads(raenv, var_nr);
805                 be_liveness(raenv->irg);
806         } else
807
808         /* or do we allocate */
809         if (!strcmp(buf, "allocs")) {
810                 int var_nr, reg_nr;
811
812                 is_allocation = 1;
813                 while (fscanf(f, " %d %d ", &var_nr, &reg_nr) == 2) {
814                         ir_node *irn;
815                         pset *vals = get_var_values(raenv, var_nr);
816
817                         assert(vals && "Variable nr does not exist!");
818                         pset_foreach(vals, irn)
819                                 arch_set_irn_register(raenv->aenv, irn, arch_register_for_index(raenv->cls, reg_nr));
820                 }
821         } else
822                 INVALID_FILE_FORMAT;
823
824         if (!feof(f))
825                 INVALID_FILE_FORMAT;
826
827         fclose(f);
828
829         return is_allocation;
830 }
831
832 /******************************************************************************
833     __  __       _
834    |  \/  |     (_)
835    | \  / | __ _ _ _ __
836    | |\/| |/ _` | | '_ \
837    | |  | | (_| | | | | |
838    |_|  |_|\__,_|_|_| |_|
839  *****************************************************************************/
840
841 /**
842  * Default values for options
843  */
844 static void (*ssa_destr)(be_raext_env_t*) = ssa_destr_simple;
845 static char callee[128] = "\"E:/user/kimohoff/ipd-registerallocator/win32/register allocator\"";
846 //static char callee[128] = "/ben/kimohoff/ipd-registerallocator/register_allocator";
847
848
849 /**
850  * Allocate registers with an external program using a text-file interface.
851  *
852  * Do some computations (SSA-destruction and mapping of values--vars)
853  * Write file
854  * Execute external program
855  * Read in results and apply them
856  *
857  */
858 static void be_ra_extern_main(const be_irg_t *bi) {
859         be_main_env_t *env = bi->main_env;
860         ir_graph *irg = bi->irg;
861
862         be_raext_env_t raenv;
863         int clsnr, clss;
864         var_info_t *vi;
865
866         compute_doms(irg);
867
868         raenv.irg      = irg;
869         raenv.aenv     = env->arch_env;
870         raenv.dom_info = be_compute_dominance_frontiers(irg);
871         raenv.vars     = new_set(compare_var_infos, 64);
872         raenv.dbg      = firm_dbg_register("ir.be.raextern");
873         firm_dbg_set_mask(raenv.dbg, DBG_LEVEL);
874
875         /* Insert copies for constraints */
876         handle_constraints(&raenv);
877         dump_ir_block_graph_sched(irg, "-extern-constr");
878
879         /* SSA destruction respectively transformation into "Conventional SSA" */
880         ssa_destr(&raenv);
881         dump_ir_block_graph_sched(irg, "-extern-ssadestr");
882
883         /* Mapping of SSA-Values <--> Variables */
884         phi_class_compute(irg);
885         be_clear_links(irg);
886         irg_walk_graph(irg, values_to_vars, NULL, &raenv);
887         be_liveness(irg);
888
889         /* For all register classes */
890         for(clsnr = 0, clss = arch_isa_get_n_reg_class(raenv.aenv->isa); clsnr < clss; ++clsnr) {
891                 int done, round = 1;
892                 char out[256], in[256];
893
894                 raenv.cls = arch_isa_get_reg_class(raenv.aenv->isa, clsnr);
895
896                 extract_vars_of_cls(&raenv);
897
898                 do {
899                         ir_snprintf(out, sizeof(out), "%F-%s-%d.ra", irg, raenv.cls->name, round);
900                         ir_snprintf(in, sizeof(in), "%F-%s-%d.ra.res", irg, raenv.cls->name, round);
901
902                         dump_to_file(&raenv, out);
903                         execute(callee, out, in);
904                         done = read_and_apply_results(&raenv, in);
905
906                         ir_snprintf(in, sizeof(in), "-extern-%s-round-%d", raenv.cls->name, round);
907                         dump_ir_block_graph_sched(irg, in);
908
909                         round++;
910                 } while (!done);
911
912                 free(raenv.cls_vars);
913         }
914
915         dump_ir_block_graph_sched(irg, "-extern-alloc");
916
917         /* Clean up */
918         set_foreach(raenv.vars, vi)
919                 del_pset(vi->values);
920         del_set(raenv.vars);
921         be_free_dominance_frontiers(raenv.dom_info);
922 }
923
924 /******************************************************************************
925      ____        _   _
926     / __ \      | | (_)
927    | |  | |_ __ | |_ _  ___  _ __  ___
928    | |  | | '_ \| __| |/ _ \| '_ \/ __|
929    | |__| | |_) | |_| | (_) | | | \__ \
930     \____/| .__/ \__|_|\___/|_| |_|___/
931           | |
932           |_|
933  *****************************************************************************/
934
935 #ifdef WITH_LIBCORE
936
937
938 static const lc_opt_enum_func_ptr_items_t ssa_destr_items[] = {
939         { "simple",     (int (*)()) ssa_destr_simple }, /* TODO make (void*) casts nicer */
940         { "rastello",   (int (*)()) ssa_destr_rastello },
941         { NULL,      NULL }
942 };
943
944 static lc_opt_enum_func_ptr_var_t ssa_destr_var = {
945          (int (**)()) &ssa_destr, ssa_destr_items
946 };
947
948 static const lc_opt_table_entry_t be_ra_extern_options[] = {
949         LC_OPT_ENT_ENUM_FUNC_PTR("ssa_destr", "SSA destruction flavor", &ssa_destr_var),
950         LC_OPT_ENT_STR("callee", "The external program to call", callee, sizeof(callee)),
951         { NULL }
952 };
953
954 static void be_ra_extern_register_options(lc_opt_entry_t *root) {
955         lc_opt_entry_t *grp = lc_opt_get_grp(root, "ext");
956
957         lc_opt_add_table(grp, be_ra_extern_options);
958 }
959
960 #endif /* WITH_LIBCORE */
961
962 const be_ra_t be_ra_external_allocator = {
963 #ifdef WITH_LIBCORE
964         be_ra_extern_register_options,
965 #endif
966         be_ra_extern_main
967 };