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