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