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