use maps to prevent teh generation of double types and entities for
[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 taking 2 arguments:
10  *   1) An input file in which the cfg is defined
11  *   2) An output file containing the essential actions performed during allocation
12  *
13
14
15 The input file format
16 ----------------------
17
18 inputfile       ::= regs nodes interf affinities .
19
20 regs            ::= 'regs' regcount .                                           // Anzahl der register (0..regcount-1), die zur Verfuegung stehen
21
22 nodes           ::= 'nodes' '{' node* '}' .                                     // All nodes in the graph
23
24 node            ::= node-info
25                           | node-info '<' reg-nr '>' .                          // Reg-nr is present in case of constraints
26
27 node-info       ::= node-nr spill-costs .
28
29 interf          ::= 'interferences' '{' edge* '}' .                     // Interference edges of the graph
30
31 affinities      ::= 'affinities' '{' edge* '}' .                        // Affinity edges of the graph
32
33 edge            ::= '(' node-nr ',' node-nr ')' .
34
35
36 spill-costs, regcount, node-nr ::= integer .
37
38
39 The output file format
40 -----------------------
41
42 outputfile      ::= spills | allocs .
43
44 spills          ::= 'spills' node-nr+ .
45
46 allocs          ::= 'allocs' alloc* .
47
48 alloc           ::= node-nr reg-nr .
49
50
51 ******** End of file format docu ********/
52
53 #ifdef HAVE_CONFIG_H
54 #include "config.h"
55 #endif
56
57 #ifdef WIN32
58 #include <malloc.h>
59 #else
60 #include <alloca.h>
61 #endif
62
63 #include <stdio.h>
64 #include <stdlib.h>
65 #ifdef WITH_LIBCORE
66 #include <libcore/lc_opts.h>
67 #include <libcore/lc_opts_enum.h>
68 #endif
69
70 #include "set.h"
71 #include "pset.h"
72 #include "pmap.h"
73 #include "bitset.h"
74
75 #include "irprintf_t.h"
76 #include "irnode_t.h"
77 #include "irgraph_t.h"
78 #include "irgwalk.h"
79 #include "iredges_t.h"
80 #include "irdom_t.h"
81 #include "phiclass.h"
82
83 #include "beraextern.h"
84 #include "bearch.h"
85 #include "benode_t.h"
86 #include "beirgmod.h"
87 #include "besched.h"
88 #include "beutil.h"
89
90 typedef struct _var_info_t var_info_t;
91
92 /**
93  * Environment with all the needed stuff
94  */
95 typedef struct _be_raext_env_t {
96         arch_env_t *aenv;
97         const arch_register_class_t *cls;
98         ir_graph *irg;
99         dom_front_info_t *dom_info;
100
101         FILE *f;                                /**< file handle used for out- and input file */
102         set *vars;                              /**< contains all var_info_t */
103         int n_cls_vars;                 /**< length of the array cls_vars */
104         var_info_t **cls_vars;  /**< only the var_infos for current cls. needed for double iterating */
105 } be_raext_env_t;
106
107
108
109 /******************************************************************************
110     _    _      _
111    | |  | |    | |
112    | |__| | ___| |_ __   ___ _ __ ___
113    |  __  |/ _ \ | '_ \ / _ \ '__/ __|
114    | |  | |  __/ | |_) |  __/ |  \__ \
115    |_|  |_|\___|_| .__/ \___|_|  |___/
116                  | |
117                  |_|
118  *****************************************************************************/
119
120
121 #define pset_foreach(pset, irn)  for(irn=pset_first(pset); irn; irn=pset_next(pset))
122 #define set_foreach(set, e)  for(e=set_first(set); e; e=set_next(set))
123
124 /**
125  * Checks if _the_ result of the irn belongs to the
126  * current register class (raenv->cls)
127  * NOTE: Only the first result is checked.
128  */
129 #define is_res_in_reg_class(irn) arch_irn_has_reg_class(raenv->aenv, irn, -1, raenv->cls)
130
131 static INLINE ir_node *get_first_non_phi(pset *s) {
132         ir_node *irn;
133
134         pset_foreach(s, irn)
135                 if (!is_Phi(irn)) {
136                         pset_break(s);
137                         return irn;
138                 }
139
140         assert(0 && "There must be a non-phi-irn in this");
141         return NULL;
142 }
143
144 static INLINE ir_node *get_first_phi(pset *s) {
145         ir_node *irn;
146
147         pset_foreach(s, irn)
148                 if (is_Phi(irn)) {
149                         pset_break(s);
150                         return irn;
151                 }
152
153         assert(0 && "There must be a phi in this");
154         return NULL;
155 }
156
157 /******************************************************************************
158     _____                _            _____            _
159    / ____|              | |          / ____|          (_)
160   | |     ___  _ __  ___| |_ _ __   | |     ___  _ __  _  ___  ___
161   | |    / _ \| '_ \/ __| __| '__|  | |    / _ \| '_ \| |/ _ \/ __|
162   | |___| (_) | | | \__ \ |_| |     | |___| (_) | |_) | |  __/\__ \
163    \_____\___/|_| |_|___/\__|_|      \_____\___/| .__/|_|\___||___/
164                                                 | |
165                                                 |_|
166  *****************************************************************************/
167
168 static void handle_constraints_walker(ir_node *irn, void *env) {
169         be_raext_env_t *raenv = env;
170         arch_register_req_t req;
171         int pos, max;
172
173         /* handle output constraints
174          * user -> irn    becomes    user -> cpy -> irn
175          */
176         arch_get_register_req(raenv->aenv, &req, irn, -1);
177         if (arch_register_req_is(&req, limited)) {
178                 ir_node *cpy = be_new_Copy(req.cls, raenv->irg, get_nodes_block(irn), irn);
179                 const ir_edge_t *edge;
180
181                 /* all users of the irn use the copy instead */
182                 sched_add_after(irn, cpy);
183                 foreach_out_edge(irn, edge)
184                         set_irn_n(edge->src, edge->pos, cpy);
185         }
186
187
188         /* handle input constraints by converting them into output constraints
189          * of copies of the former argument
190          * irn -> arg   becomes  irn -> copy -> arg
191      */
192         for (pos = 0, max = get_irn_arity(irn); pos<max; ++pos) {
193                 arch_get_register_req(raenv->aenv, &req, irn, pos);
194                 if (arch_register_req_is(&req, limited)) {
195                         ir_node *arg = get_irn_n(irn, pos);
196                         ir_node *cpy = be_new_Copy(req.cls, raenv->irg, get_nodes_block(irn), arg);
197
198                         /* use the copy instead */
199                         sched_add_before(irn, cpy);
200                         set_irn_n(irn, pos, cpy);
201
202                         /* set an out constraint for the copy */
203                         /* TODO: Insert right code here. *
204                         be_set_constr_single_reg(cpy, -1, &reg);
205                         */
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 %s %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_main_env_t *env, ir_graph *irg) {
835         be_raext_env_t raenv;
836         int clsnr, clss;
837         var_info_t *vi;
838
839         compute_doms(irg);
840
841         raenv.irg      = irg;
842         raenv.aenv     = env->arch_env;
843         raenv.dom_info = be_compute_dominance_frontiers(irg);
844         raenv.vars     = new_set(compare_var_infos, 64);
845
846         /* Insert copies for constraints */
847         handle_constraints(&raenv);
848         dump_ir_block_graph_sched(irg, "-extern-constr");
849
850         /* SSA destruction respectively transformation into "Conventional SSA" */
851         ssa_destr(&raenv);
852         dump_ir_block_graph_sched(irg, "-extern-ssadestr");
853
854
855         /* Mapping of SSA-Values <--> Variables */
856         phi_class_compute(irg);
857         be_clear_links(irg);
858         irg_walk_graph(irg, values_to_vars, NULL, &raenv);
859
860         /* For all register classes */
861         for(clsnr = 0, clss = arch_isa_get_n_reg_class(raenv.aenv->isa); clsnr < clss; ++clsnr) {
862                 int done = 0;
863                 char out[256], in[256];
864
865                 raenv.cls = arch_isa_get_reg_class(raenv.aenv->isa, clsnr);
866                 ir_snprintf(out, sizeof(out), "%F-%s.ra", irg, raenv.cls->name);
867                 ir_snprintf(in, sizeof(in), "%F-%s.ra.res", irg, raenv.cls->name);
868
869                 extract_vars_of_cls(&raenv);
870
871                 while (!done) {
872                         dump_to_file(&raenv, out);
873                         execute(callee, out, in);
874                         done = read_and_apply_results(&raenv, in);
875                 }
876
877                 free(raenv.cls_vars);
878         }
879
880         dump_ir_block_graph_sched(irg, "-extern-alloc");
881
882         /* Clean up */
883         set_foreach(raenv.vars, vi)
884                 del_pset(vi->values);
885         del_set(raenv.vars);
886         be_free_dominance_frontiers(raenv.dom_info);
887 }
888
889 /******************************************************************************
890      ____        _   _
891     / __ \      | | (_)
892    | |  | |_ __ | |_ _  ___  _ __  ___
893    | |  | | '_ \| __| |/ _ \| '_ \/ __|
894    | |__| | |_) | |_| | (_) | | | \__ \
895     \____/| .__/ \__|_|\___/|_| |_|___/
896           | |
897           |_|
898  *****************************************************************************/
899
900 #ifdef WITH_LIBCORE
901
902 static const lc_opt_enum_const_ptr_items_t ssa_destr_items[] = {
903         { "simple",    ssa_destr_simple },
904         { "rastello",  ssa_destr_rastello },
905         { NULL,      NULL }
906 };
907
908 static lc_opt_enum_const_ptr_var_t ssa_destr_var = {
909         (const void **) &ssa_destr, ssa_destr_items
910 };
911
912 static const lc_opt_table_entry_t be_ra_extern_options[] = {
913         LC_OPT_ENT_ENUM_FUNC_PTR("ssa_destr", "SSA destruction flavor", &ssa_destr_var),
914         LC_OPT_ENT_STR("callee", "The external program to call", callee, sizeof(callee)),
915         { NULL }
916 };
917
918 static void be_ra_extern_register_options(lc_opt_entry_t *root) {
919         lc_opt_entry_t *grp = lc_opt_get_grp(root, "ext");
920
921         lc_opt_add_table(grp, be_ra_extern_options);
922 }
923
924 #endif /* WITH_LIBCORE */
925
926 const be_ra_t be_ra_external_allocator = {
927 #ifdef WITH_LIBCORE
928         be_ra_extern_register_options,
929 #endif
930         be_ra_extern_main
931 };