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