Added clique walker
[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                 var_add_value(raenv, nr, irn);
476 }
477
478
479 /******************************************************************************
480     _____
481    |  __ \
482    | |  | |_   _ _ __ ___  _ __   ___ _ __
483    | |  | | | | | '_ ` _ \| '_ \ / _ \ '__|
484    | |__| | |_| | | | | | | |_) |  __/ |
485    |_____/ \__,_|_| |_| |_| .__/ \___|_|
486                           | |
487                           |_|
488  *****************************************************************************/
489
490
491 static void extract_vars_of_cls(be_raext_env_t *raenv) {
492         int count = 0;
493         var_info_t *vi;
494
495         raenv->cls_vars = malloc(set_count(raenv->vars) * sizeof(*raenv->cls_vars));
496         assert(raenv->cls_vars);
497
498         set_foreach(raenv->vars, vi)
499                 if (is_res_in_reg_class(get_first_non_phi(vi->values)))
500                         raenv->cls_vars[count++] = vi;
501
502         raenv->cls_vars = realloc(raenv->cls_vars, count * sizeof(*raenv->cls_vars));
503         assert(raenv->cls_vars);
504
505         raenv->n_cls_vars = count;
506 }
507
508
509 /**
510  * Check if node irn has a limited-constraint at position pos.
511  * If yes, dump it to FILE raenv->f
512  */
513 static INLINE void dump_constraint(be_raext_env_t *raenv, ir_node *irn, int pos) {
514         bitset_t *bs = bitset_alloca(raenv->cls->n_regs);
515         arch_register_req_t req;
516
517         arch_get_register_req(raenv->aenv, &req, irn, pos);
518         if (arch_register_req_is(&req, limited)) {
519                 int reg_nr;
520                 req.limited(req.limited_env, bs);
521                 reg_nr = bitset_next_set(bs, 0);
522                 fprintf(raenv->f, "<%d>", reg_nr);
523                 assert(-1 == bitset_next_set(bs, reg_nr+1) && "Constraints with more than 1 possible register are not supported");
524         }
525 }
526
527 static INLINE unsigned int get_spill_costs(be_raext_env_t *raenv, var_info_t *vi) {
528         ir_node *irn;
529         int c_spills=0, c_reloads=0;
530
531         pset_foreach(vi->values, irn) {
532                 if (arch_irn_is_ignore(raenv->aenv, irn)) {
533                         pset_break(vi->values);
534                         return -1;
535                 }
536
537                 if (is_Phi(irn)) {
538                         /* number of reloads is the number of non-phi uses of all values of this var */
539                         const ir_edge_t *edge;
540                         foreach_out_edge(irn, edge)
541                                 if (!is_Phi(edge->src))
542                                         c_reloads += get_reload_weight(edge->src);
543                 } else {
544                         /* number of spills is the number of non-phi values for this var */
545                         c_spills += get_spill_weight(irn);
546                 }
547         }
548
549         return c_spills + c_reloads;
550 }
551
552 static void dump_nodes(be_raext_env_t *raenv) {
553         FILE *f = raenv->f;
554         int i;
555
556         fprintf(f, "\nnodes {\n");
557
558         for (i=0; i<raenv->n_cls_vars; ++i) {
559                 var_info_t *vi = raenv->cls_vars[i];
560
561                 if (vi->var_nr == SET_REMOVED)
562                         continue;
563
564                 fprintf(f, "%d %u", vi->var_nr, get_spill_costs(raenv, vi));
565                 dump_constraint(raenv, get_first_non_phi(vi->values), -1);
566                 fprintf(f, "\n");
567         }
568
569         fprintf(f, "}\n");
570 }
571
572
573 static void dump_interferences(be_raext_env_t *raenv) {
574         int i,o;
575         var_info_t *vi1, *vi2;
576         ir_node *irn1, *irn2;
577         FILE *f = raenv->f;
578
579         fprintf(f, "\ninterferences {\n");
580
581         for (i=0; i<raenv->n_cls_vars; ++i) {
582                 vi1 = raenv->cls_vars[i];
583
584                 if (vi1->var_nr == SET_REMOVED)
585                         continue;
586
587                 for (o=i+1; o<raenv->n_cls_vars; ++o) {
588                         vi2 = raenv->cls_vars[o];
589
590                         if (vi2->var_nr == SET_REMOVED)
591                                 continue;
592
593                         pset_foreach(vi1->values, irn1)
594                                 pset_foreach(vi2->values, irn2)
595                                         if (values_interfere(irn1, irn2)) {
596                                                 pset_break(vi1->values);
597                                                 pset_break(vi2->values);
598                                                 fprintf(f, "(%d, %d)\n", vi1->var_nr, vi2->var_nr);
599                                         }
600                 }
601         }
602         fprintf(f, "}\n");
603 }
604
605 static void dump_affinities_walker(ir_node *irn, void *env) {
606         be_raext_env_t *raenv = env;
607         arch_register_req_t req;
608         int pos, max;
609         var_info_t *vi1, *vi2;
610
611         if (arch_get_irn_reg_class(raenv->aenv, irn, -1) == NULL || arch_irn_is_ignore(raenv->aenv, irn))
612                 return;
613
614         vi1 = get_var_info(irn);
615
616         /* copies have affinities */
617         if (arch_irn_classify(raenv->aenv, irn) == arch_irn_class_copy) {
618                 ir_node *other = get_irn_n(irn, 0);
619
620                 if (! arch_irn_is_ignore(raenv->aenv, other)) {
621                         vi2 = get_var_info(other);
622
623                         fprintf(raenv->f, "(%d, %d, %d)\n",  vi1->var_nr, vi2->var_nr, get_affinity_weight(irn));
624                 }
625         }
626
627
628         /* should_be_equal constraints are affinites */
629         for (pos = 0, max = get_irn_arity(irn); pos<max; ++pos) {
630                 arch_get_register_req(raenv->aenv, &req, irn, pos);
631
632                 if (arch_register_req_is(&req, should_be_same) && arch_irn_is_ignore(raenv->aenv, req.other_same)) {
633                         vi2 = get_var_info(req.other_same);
634
635                         fprintf(raenv->f, "(%d, %d, %d)\n",  vi1->var_nr, vi2->var_nr, get_affinity_weight(irn));
636                 }
637         }
638 }
639
640
641 static void dump_affinities(be_raext_env_t *raenv) {
642         fprintf(raenv->f, "\naffinities {\n");
643         irg_walk_graph(raenv->irg, NULL, dump_affinities_walker, raenv);
644         fprintf(raenv->f, "}\n");
645 }
646
647 /**
648  * Dump all information needed by the external
649  * register allocator to a single file.
650  */
651 static void dump_to_file(be_raext_env_t *raenv, char *filename) {
652         FILE *f;
653
654         if (!(f = fopen(filename, "wt"))) {
655                 fprintf(stderr, "Could not open file %s for writing\n", filename);
656                 assert(0);
657                 exit(0xdeadbeef);
658         }
659         raenv->f = f;
660
661         /* dump register info */
662         fprintf(f, "regs %d\n", arch_register_class_n_regs(raenv->cls));
663
664         /* dump the interference graph */
665         dump_nodes(raenv);
666         dump_interferences(raenv);
667         dump_affinities(raenv);
668
669         fclose(f);
670 }
671
672 /******************************************************************************
673     ______                     _
674    |  ____|                   | |
675    | |__  __  _____  ___ _   _| |_ ___
676    |  __| \ \/ / _ \/ __| | | | __/ _ \
677    | |____ >  <  __/ (__| |_| | ||  __/
678    |______/_/\_\___|\___|\__,_|\__\___|
679  *****************************************************************************/
680
681 /**
682  * Execute the external register allocator specified in the
683  * firm-option firm.be.ra.ext.callee
684  */
685 static void execute(char *prog_to_call, char *out_file, char *result_file) {
686         char cmd_line[1024];
687         int ret_status;
688
689         snprintf(cmd_line, sizeof(cmd_line), "%s -i %s -o %s", prog_to_call, out_file, result_file);
690
691         ret_status = system(cmd_line);
692         assert(ret_status != -1 && "Invokation of external register allocator failed");
693 }
694
695 /******************************************************************************
696                          _         _____                 _ _
697        /\               | |       |  __ \               | | |
698       /  \   _ __  _ __ | |_   _  | |__) |___  ___ _   _| | |_
699      / /\ \ | '_ \| '_ \| | | | | |  _  // _ \/ __| | | | | __|
700     / ____ \| |_) | |_) | | |_| | | | \ \  __/\__ \ |_| | | |_
701    /_/    \_\ .__/| .__/|_|\__, | |_|  \_\___||___/\__,_|_|\__|
702             | |   | |       __/ |
703             |_|   |_|      |___/
704  *****************************************************************************/
705
706 /**
707  * Spill a variable and add reloads before all uses.
708  */
709 static INLINE void var_add_spills_and_reloads(be_raext_env_t *raenv, int var_nr) {
710         var_info_t *vi = var_find(raenv->vars, var_nr);
711         ir_node *spill=NULL, *ctx, *irn;
712         ir_mode *mode;
713         const ir_edge_t *edge, *ne;
714         pset *spills  = pset_new_ptr(4);        /* the spills of this variable */
715         pset *reloads = pset_new_ptr(4);        /* the reloads of this variable */
716         int new_size, n_spills, n_reloads;
717
718         assert(vi && "Variable nr does not exist!");
719         assert(pset_count(vi->values) && "There are no values associated to this variable");
720
721         /* the spill context is set to an arbitrary node of the phi-class,
722          * or the node itself if it is not member of a phi class
723          */
724         if (pset_count(vi->values) == 1)
725                 ctx = get_first_non_phi(vi->values);
726         else
727                 ctx = get_first_phi(vi->values);
728
729         DBG((raenv->dbg, LEVEL_2, "Spill context: %+F\n", ctx));
730
731         /* for each value of this variable insert the spills */
732         pset_foreach(vi->values, irn) {
733                 if (is_Phi(irn)) {
734                         sched_remove(irn);
735                         continue;
736                 }
737
738                 /* all ordinary nodes must be spilled */
739                 DBG((raenv->dbg, LEVEL_2, "  spilling %+F\n", irn));
740                 spill = be_spill(raenv->aenv, irn, ctx);
741
742                 /* remember the spill */
743                 pset_insert_ptr(spills, spill);
744         }
745
746         assert(spill && "There must be at least one non-phi-node");
747
748         mode = get_irn_mode(get_irn_n(spill, 0));
749
750         /* insert reloads and wire them arbitrary*/
751         pset_foreach(vi->values, irn)
752                 foreach_out_edge_safe(irn, edge, ne) {
753                         ir_node *reload, *src = edge->src;
754                         if (is_Phi(src) || be_is_Spill(src))
755                                 continue;
756
757                         /* all real uses must be reloaded */
758                         DBG((raenv->dbg, LEVEL_2, "  reloading before %+F\n", src));
759                         reload = be_reload(raenv->aenv, raenv->cls, edge->src, mode, spill);
760                         set_irn_n(edge->src, edge->pos, reload);
761
762                         /* remember the reload */
763                         pset_insert_ptr(reloads, reload);
764                 }
765
766         /* correct the reload->spill pointers... */
767         be_ssa_constr_set(raenv->dom_info, spills);
768
769
770         /****** correct the variable <--> values mapping: ******
771          *
772          *  - if we had a phi class it gets split into several new variables
773          *  - all reloads are new variables
774          */
775         n_spills = pset_count(spills);
776         n_reloads = pset_count(reloads);
777
778         /* first make room for new pointers in the cls_var array */
779         new_size = raenv->n_cls_vars + n_reloads + ((n_spills>1) ? n_spills : 0);
780         raenv->cls_vars = realloc(raenv->cls_vars, (new_size) * sizeof(*raenv->cls_vars));
781         assert(raenv->cls_vars && "Out of mem!?");
782
783         /* if we had a real phi-class, we must... */
784         if (pset_count(spills) > 1) {
785                 /* ...remove the old variable corresponding to the phi class */
786                 vi->var_nr = SET_REMOVED;
787
788                 /* ...add new vars for each non-phi-member */
789                 pset_foreach(spills, irn) {
790                         ir_node *spilled = get_irn_n(irn, 0);
791                         raenv->cls_vars[raenv->n_cls_vars++] = var_add_value(raenv, get_irn_node_nr(spilled), spilled);
792                 }
793         }
794
795         /* add new variables for all reloads */
796         pset_foreach(reloads, irn)
797                 raenv->cls_vars[raenv->n_cls_vars++] = var_add_value(raenv, get_irn_node_nr(irn), irn);
798
799         del_pset(spills);
800         del_pset(reloads);
801 }
802
803 #define INVALID_FILE_FORMAT assert(0 && "Invalid file format.")
804 #define BUFLEN 32
805 #define BUFCONV " %32s "
806
807 /**
808  * Read in the actions performed by the external allocator.
809  * Apply these transformations to the irg.
810  * @return 1 if an allocation was read in. 0 otherwise.
811  */
812 static int read_and_apply_results(be_raext_env_t *raenv, char *filename) {
813         FILE *f;
814         char buf[BUFLEN];
815         int is_allocation = 0;
816
817         if (!(f = fopen(filename, "rt"))) {
818                 fprintf(stderr, "Could not open file %s for reading\n", filename);
819                 assert(0);
820                 exit(0xdeadbeef);
821         }
822         raenv->f = f;
823
824         /* read the action */
825         if (fscanf(f, BUFCONV, buf) != 1)
826                 INVALID_FILE_FORMAT;
827
828         /* do we spill */
829         if (!strcmp(buf, "spills")) {
830                 int var_nr;
831                 while (fscanf(f, " %d ", &var_nr) == 1)
832                         var_add_spills_and_reloads(raenv, var_nr);
833         } else
834
835         /* or do we allocate */
836         if (!strcmp(buf, "allocs")) {
837                 int var_nr, reg_nr;
838
839                 is_allocation = 1;
840                 while (fscanf(f, " %d %d ", &var_nr, &reg_nr) == 2) {
841                         ir_node *irn;
842                         pset *vals = get_var_values(raenv, var_nr);
843
844                         assert(vals && "Variable nr does not exist!");
845                         pset_foreach(vals, irn)
846                                 arch_set_irn_register(raenv->aenv, irn, arch_register_for_index(raenv->cls, reg_nr));
847                 }
848         } else
849                 INVALID_FILE_FORMAT;
850
851         if (!feof(f))
852                 INVALID_FILE_FORMAT;
853
854         fclose(f);
855
856         return is_allocation;
857 }
858
859 static void check_allocation(be_raext_env_t *raenv) {
860         int i, o;
861
862         for (i=0; i<raenv->n_cls_vars; ++i) {
863                 var_info_t *vi1 = raenv->cls_vars[i];
864
865                 if (vi1->var_nr == SET_REMOVED)
866                         continue;
867
868                 for (o=0; o<i; ++o) {
869                         var_info_t *vi2 = raenv->cls_vars[o];
870                         ir_node *irn1, *irn2;
871
872                         if (vi2->var_nr == SET_REMOVED)
873                                 continue;
874
875                         pset_foreach(vi1->values, irn1)
876                                 pset_foreach(vi2->values, irn2)
877                                         if (values_interfere(irn1, irn2)) {
878                                                 dump_ir_block_graph_sched(raenv->irg, "ERROR");
879                                                 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);
880                                                 assert(0 && "ERROR graph dumped");
881                                         }
882                 }
883         }
884 }
885
886 /******************************************************************************
887     __  __       _
888    |  \/  |     (_)
889    | \  / | __ _ _ _ __
890    | |\/| |/ _` | | '_ \
891    | |  | | (_| | | | | |
892    |_|  |_|\__,_|_|_| |_|
893  *****************************************************************************/
894
895 /**
896  * Default values for options
897  */
898 static void (*ssa_destr)(be_raext_env_t*) = ssa_destr_simple;
899 static char callee[128] = "\"E:/user/kimohoff/ipd-registerallocator/win32/register allocator\"";
900 //static char callee[128] = "/ben/kimohoff/ipd-registerallocator/register_allocator";
901
902
903 /**
904  * Allocate registers with an external program using a text-file interface.
905  *
906  * Do some computations (SSA-destruction and mapping of values--vars)
907  * Write file
908  * Execute external program
909  * Read in results and apply them
910  *
911  */
912 static void be_ra_extern_main(const be_irg_t *bi) {
913         be_main_env_t *env = bi->main_env;
914         ir_graph *irg = bi->irg;
915
916         be_raext_env_t raenv;
917         int clsnr, clss;
918         var_info_t *vi;
919
920         compute_doms(irg);
921
922         raenv.irg      = irg;
923         raenv.aenv     = env->arch_env;
924         raenv.dom_info = be_compute_dominance_frontiers(irg);
925         raenv.vars     = new_set(compare_var_infos, 64);
926         raenv.dbg      = firm_dbg_register("ir.be.raextern");
927         firm_dbg_set_mask(raenv.dbg, DBG_LEVEL);
928
929         /* Insert copies for constraints */
930         handle_constraints(&raenv);
931         dump_ir_block_graph_sched(irg, "-extern-constr");
932
933         /* SSA destruction respectively transformation into "Conventional SSA" */
934         ssa_destr(&raenv);
935         dump_ir_block_graph_sched(irg, "-extern-ssadestr");
936
937         /* Mapping of SSA-Values <--> Variables */
938         phi_class_compute(irg);
939         be_clear_links(irg);
940         irg_walk_graph(irg, values_to_vars, NULL, &raenv);
941
942
943         /* For all register classes */
944         for(clsnr = 0, clss = arch_isa_get_n_reg_class(raenv.aenv->isa); clsnr < clss; ++clsnr) {
945                 int done, round = 1;
946                 char out[256], in[256];
947
948                 raenv.cls = arch_isa_get_reg_class(raenv.aenv->isa, clsnr);
949
950                 extract_vars_of_cls(&raenv);
951
952                 do {
953                         ir_snprintf(out, sizeof(out), "%F-%s-%d.ra", irg, raenv.cls->name, round);
954                         ir_snprintf(in, sizeof(in), "%F-%s-%d.ra.res", irg, raenv.cls->name, round);
955
956                         be_liveness(irg);
957
958                         dump_to_file(&raenv, out);
959                         execute(callee, out, in);
960                         done = read_and_apply_results(&raenv, in);
961
962                         ir_snprintf(in, sizeof(in), "-extern-%s-round-%d", raenv.cls->name, round);
963                         dump_ir_block_graph_sched(irg, in);
964
965                         round++;
966                 } while (!done);
967
968                 check_allocation(&raenv);
969
970                 free(raenv.cls_vars);
971         }
972
973         dump_ir_block_graph_sched(irg, "-extern-alloc");
974
975         /* Clean up */
976         set_foreach(raenv.vars, vi)
977                 del_pset(vi->values);
978         del_set(raenv.vars);
979         be_free_dominance_frontiers(raenv.dom_info);
980 }
981
982 /******************************************************************************
983      ____        _   _
984     / __ \      | | (_)
985    | |  | |_ __ | |_ _  ___  _ __  ___
986    | |  | | '_ \| __| |/ _ \| '_ \/ __|
987    | |__| | |_) | |_| | (_) | | | \__ \
988     \____/| .__/ \__|_|\___/|_| |_|___/
989           | |
990           |_|
991  *****************************************************************************/
992
993 #ifdef WITH_LIBCORE
994
995
996 static const lc_opt_enum_func_ptr_items_t ssa_destr_items[] = {
997         { "simple",     (int (*)()) ssa_destr_simple }, /* TODO make (void*) casts nicer */
998         { "rastello",   (int (*)()) ssa_destr_rastello },
999         { NULL,      NULL }
1000 };
1001
1002 static lc_opt_enum_func_ptr_var_t ssa_destr_var = {
1003          (int (**)()) &ssa_destr, ssa_destr_items
1004 };
1005
1006 static const lc_opt_table_entry_t be_ra_extern_options[] = {
1007         LC_OPT_ENT_ENUM_FUNC_PTR("ssa_destr", "SSA destruction flavor", &ssa_destr_var),
1008         LC_OPT_ENT_STR("callee", "The external program to call", callee, sizeof(callee)),
1009         { NULL }
1010 };
1011
1012 static void be_ra_extern_register_options(lc_opt_entry_t *root) {
1013         lc_opt_entry_t *grp = lc_opt_get_grp(root, "ext");
1014
1015         lc_opt_add_table(grp, be_ra_extern_options);
1016 }
1017
1018 #endif /* WITH_LIBCORE */
1019
1020 const be_ra_t be_ra_external_allocator = {
1021 #ifdef WITH_LIBCORE
1022         be_ra_extern_register_options,
1023 #endif
1024         be_ra_extern_main
1025 };