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