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