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