4 * Copyright: (c) Universitaet Karlsruhe
5 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
7 * Implementation of the RA-Interface for an external, (non-SSA) register allocator.
9 * The external register allocator is a program taking 2 arguments:
10 * 1) An input file in which the cfg is defined
11 * 2) An output file containing the essential actions performed during allocation
16 ----------------------
18 inputfile ::= regs cfg .
20 regs ::= 'regs' regcount 'saved-by-caller' reg-list 'saved-by-callee' reg-list . // Anzahl der register (0..regcount-1), die zur Verfuegung stehen
25 cfg ::= 'cfg' ident '{' block* edge* '}' . // Steuerflussgraph der Prozedur
27 block ::= 'block' block-nr '{' insn* '}' . // Grundblock im cfg versehen mit einer nummer
29 edge ::= 'cf-edge' block-nr block-nr . // Steuerflusskante src-->tgt
31 insn ::= gen-insn // Befehl in einem block
34 gen-insn ::= 'insn' insn-nr '{' uses defs '}' .
35 copy-insn ::= 'copy' insn-nr '{' uses defs '}' .
36 call-insn ::= 'call' insn-nr '{' uses defs '}' .
38 defs ::= 'def' var-list . // Liste der definierten/verwendeten Variablen
39 uses ::= 'use' var-list .
45 | var-nr '<' reg-nr '>' . // reg-nr gibt register constraint an.
48 ident ::= non-whitespace-char* .
49 regcount, block-nr, insn-nr, reg-nr, var-nr ::= integer .
52 The output file format
53 -----------------------
55 outputfile ::= action* assign*.
57 action ::= 'spill' loc var-nr // insert a spill spill(var-nr);
58 | 'reload' loc new-var-nr var-nr // insert a reload new-var-nr := reload(var-nr);
59 | 'setarg' insn-nr pos var-nr // change a usage to insn(..., var-nr, ...) (equals set_irn_n)
60 | 'copy' loc var-nr var-nr // insert a copy var-nr[1] := var-nr[2];
62 assign ::= 'assign' var-nr reg-nr . // assign var-nr the register reg-nr
64 loc ::= 'before' insn-nr
68 Constraints for output file
69 ---------------------------
70 1) The returned actions must result in a non-ssa-program
71 equivalent to the former input.
72 2) All names (numbers) must be defined before their first use.
73 Numbers already occuring in the input file are implicitly defined in the output file.
74 3) All spills of a variable must precede the first reload of this variable
75 4) Each reload must define a new variable name
79 ******** End of file format docu ********/
94 #include <libcore/lc_opts.h>
95 #include <libcore/lc_opts_enum.h>
103 #include "irprintf_t.h"
104 #include "irnode_t.h"
105 #include "irgraph_t.h"
108 #include "phiclass.h"
110 #include "beraextern.h"
112 #include "benode_t.h"
113 #include "beirgmod.h"
117 typedef struct _var_info_t var_info_t;
120 * Environment with all the needed stuff
122 typedef struct _be_raext_env_t {
124 const arch_register_class_t *cls;
126 dom_front_info_t *dom_info;
128 FILE *f; /**< file handle used for out- and input file */
129 set *vars; /**< contains all var_info_t */
130 pmap *nodes; /**< maps nodes numbers (int) to the node (ir_node*) having that node_nr */
135 /******************************************************************************
138 | |__| | ___| |_ __ ___ _ __ ___
139 | __ |/ _ \ | '_ \ / _ \ '__/ __|
140 | | | | __/ | |_) | __/ | \__ \
141 |_| |_|\___|_| .__/ \___|_| |___/
144 *****************************************************************************/
147 #define pset_foreach(pset, irn) for(irn=pset_first(pset); irn; irn=pset_next(pset))
148 #define set_foreach(set, e) for(e=set_first(set); e; e=set_next(set))
152 * Checks if _the_ result of the irn belongs to the
153 * current register class (raenv->cls)
154 * NOTE: Only the first result is checked.
156 #define is_res_in_reg_class(irn) arch_irn_has_reg_class(raenv->aenv, irn, -1, raenv->cls)
160 * Checks if the irn uses or defines values of the
161 * current register class (raenv->cls)
163 static INLINE int is_sth_in_reg_class(be_raext_env_t *raenv, const ir_node *irn) {
166 /* check arguments */
167 for (i=0, max=get_irn_arity(irn); i<max; ++i)
168 if (arch_irn_has_reg_class(raenv->aenv, get_irn_n(irn, i), -1, raenv->cls))
171 /* check result(s) */
172 if (get_irn_mode(irn) == mode_T) {
174 for (proj = sched_next(irn); is_Proj(proj); proj = sched_next(proj))
175 if (arch_irn_has_reg_class(raenv->aenv, proj, -1, raenv->cls))
179 return arch_irn_has_reg_class(raenv->aenv, irn, -1, raenv->cls);
182 assert(0 && "Where did you come from???");
185 /******************************************************************************
187 / ____/ ____| /\ | __ \ | |
188 | (___| (___ / \ ______| | | | ___ ___| |_ _ __
189 \___ \\___ \ / /\ \______| | | |/ _ \/ __| __| '__|
190 ____) |___) / ____ \ | |__| | __/\__ \ |_| |
191 |_____/_____/_/ \_\ |_____/ \___||___/\__|_|
193 *****************************************************************************/
195 #define mark_as_done(irn, pos) set_irn_link(irn, INT_TO_PTR(pos+1))
196 #define has_been_done(irn, pos) (PTR_TO_INT(get_irn_link(irn)) > pos)
199 * Insert a copy for the argument of @p start_phi found at position @p pos.
200 * Also searches a phi-loop of arbitrary length to detect and resolve
201 * the class of phi-swap-problems. To search for a loop recursion is used.
203 * 1) Simplest case (phi with a non-phi arg):
204 * A single copy is inserted.
206 * 2) Phi chain (phi (with phi-arg)* with non=phi arg):
207 * Several copies are placed, each after returning from recursion.
210 * On detection a loop breaker is inserted, which is a copy of the start_phi.
211 * This copy then pretends beeing the argumnent of the last phi.
212 * Now case 2) can be used.
214 * The values of @p start_phi and @p pos never change during recursion.
216 * @p raenv Environment with all the stuff needed
217 * @p start_phi Phi node to process
218 * @p pos Argument position to insert copy/copies for
219 * @p curr_phi Phi node currently processed during recursion. Equals start_phi on initial call
221 * @return NULL If no copy is necessary
222 * NULL If the phi has already been processed at this pos
223 * Link field is used to keep track of processed positions
224 * In all other cases the ir_node *copy which was placed is returned.
226 static ir_node *insert_copies(be_raext_env_t *raenv, ir_node *start_phi, int pos, ir_node *curr_phi) {
227 ir_node *arg = get_irn_n(curr_phi, pos);
228 ir_node *arg_blk = get_nodes_block(arg);
229 ir_node *pred_blk = get_Block_cfgpred_block(get_nodes_block(curr_phi), pos);
230 ir_node *curr_cpy, *last_cpy;
232 assert(is_Phi(start_phi) && is_Phi(curr_phi));
234 if (has_been_done(start_phi, pos))
237 /* In case this is a 'normal' phi we insert into
238 * the schedule before the pred_blk irn */
241 /* If we detect a loop stop recursion. */
242 if (arg == start_phi) {
243 ir_node *loop_breaker;
244 if (start_phi == curr_phi) {
245 /* Phi directly uses itself. No copy necessary */
249 /* At least 2 phis are involved */
250 /* Insert a loop breaking copy (an additional variable T) */
251 loop_breaker = be_new_Copy(raenv->cls, raenv->irg, pred_blk, start_phi);
252 sched_add_before(pred_blk, loop_breaker);
257 /* If arg is a phi in the same block we have to continue search */
258 if (is_Phi(arg) && arg_blk == get_nodes_block(start_phi))
259 last_cpy = insert_copies(raenv, start_phi, pos, arg);
261 /* Insert copy of argument (may be the loop-breaker) */
262 curr_cpy = be_new_Copy(raenv->cls, raenv->irg, pred_blk, arg);
263 set_irn_n(curr_phi, pos, curr_cpy);
264 mark_as_done(curr_phi, pos);
265 sched_add_before(last_cpy, curr_cpy);
271 * Perform simple SSA-destruction with copies.
272 * The order of processing _must_ be
273 * for all positions {
278 * else the magic to keep track of processed phi-positions will fail in
279 * function 'insert_copies'
281 static void ssa_destr_simple_walker(ir_node *blk, void *env) {
282 be_raext_env_t *raenv = env;
286 /* for all argument positions of the phis */
287 for (pos=0, max=get_irn_arity(blk); pos<max; ++pos) {
289 /* for all phi nodes (which are scheduled first) */
290 sched_foreach(blk, phi) {
294 raenv->cls = arch_get_irn_reg_class(raenv->aenv, phi, -1);
295 insert_copies(raenv, phi, pos, phi);
301 static void ssa_destr_simple(be_raext_env_t *raenv) {
302 be_clear_links(raenv->irg);
303 irg_block_walk_graph(raenv->irg, ssa_destr_simple_walker, NULL, raenv);
307 static void ssa_destr_rastello(be_raext_env_t *raenv) {
310 phi_class_compute(raenv->irg);
311 irg_block_walk_graph(irg, ssa_destr_rastello, NULL, &raenv);
315 /******************************************************************************
317 \ \ / / | | |__ \ \ \ / /
318 \ \ / /_ _| |___ ) | \ \ / /_ _ _ __ ___
319 \ \/ / _` | / __| / / \ \/ / _` | '__/ __|
320 \ / (_| | \__ \ / /_ \ / (_| | | \__ \
321 \/ \__,_|_|___/ |____| \/ \__,_|_| |___/
322 *****************************************************************************/
325 * This struct maps a variable (nr) to
326 * 1) the values belonging to this variable
327 * 2) the spills of this variable
330 int var_nr; /* the key for comparesion */
331 pset *values; /* the ssa-values belonging to this variable */
332 pset *spills; /* the spills of this variable */
333 pset *reloads; /* the relaods of this variable */
334 unsigned reload_phase:1; /* 0 initially, 1 if a reload of this var has been inserted */
338 * The link field of an irn points to the var_info struct
339 * representing the corresponding variable.
341 #define set_var_info(irn, vi) set_irn_link(irn, vi)
342 #define get_var_info(irn) ((var_info_t *)get_irn_link(irn))
344 /* TODO insn-nr handling if ext defines new ones */
345 #define pmap_insert_sth(pmap, key, val) pmap_insert(pmap, (void *)key, (void *)val)
346 #define pmap_get_sth(pmap, key) pmap_get(pmap, (void *)key)
349 #define HASH_VAR_NR(var_nr) var_nr
353 static int compare_var_infos(const void *e1, const void *e2, size_t size) {
354 const var_info_t *v1 = e1;
355 const var_info_t *v2 = e2;
357 return v1->var_nr != v2->var_nr;
360 static INLINE var_info_t *var_find(set *vars, int var_nr) {
364 return set_find(vars, &vi, sizeof(vi), HASH_VAR_NR(var_nr));
367 static INLINE var_info_t *var_find_or_insert(set *vars, int var_nr) {
368 var_info_t vi, *found;
369 memset(&vi, 0, sizeof(vi));
372 found = set_insert(vars, &vi, sizeof(vi), HASH_VAR_NR(var_nr));
374 if (!found->values) {
375 found->values = pset_new_ptr(1);
376 found->spills = pset_new_ptr(1);
377 found->reloads = pset_new_ptr(1);
384 * Adds a value to a variable. Sets all pointers accordingly.
386 static INLINE var_info_t *var_add_value(be_raext_env_t *raenv, int var_nr, ir_node *irn) {
387 var_info_t *vi = var_find_or_insert(raenv->vars, var_nr);
389 /* var 2 value mapping */
390 pset_insert_ptr(vi->values, irn);
392 /* value 2 var mapping */
393 set_var_info(irn, vi);
399 * Adds a spill to a variable. Sets all pointers accordingly.
401 static INLINE var_info_t *var_add_spill(be_raext_env_t *raenv, int var_to_spill, ir_node *before) {
402 var_info_t *vi = var_find_or_insert(raenv->vars, var_to_spill);
403 ir_node *blk, *tospill, *spill;
405 assert(pset_count(vi->values) && "There are no values associated to this variable (yet?)");
406 assert(!vi->reload_phase && "I have already seen a reload for this variable, so you cant spill anymore!");
408 /* add spill to graph and schedule */
409 blk = get_nodes_block(before);
410 tospill = dom_up_search(vi->values, before); /* which value gets spilled */
411 spill = be_new_Spill(raenv->cls, raenv->irg, blk, tospill, tospill); /* the corresponding spill node */
413 sched_add_before(before, spill);
415 /* the spill also points to the var_info of the spilled node */
416 set_var_info(spill, vi);
418 /* remember the spill */
419 pset_insert_ptr(vi->spills, spill);
425 * Adds a reload to a variable. Sets all pointers accordingly.
427 static INLINE var_info_t *var_add_reload(be_raext_env_t *raenv, int var_to_reload, int var_nr_for_reload, ir_node *before) {
428 var_info_t *vi = var_find_or_insert(raenv->vars, var_to_reload);
429 ir_node *blk, *spill, *reload;
431 assert(pset_count(vi->spills) && "There are no spills associated to this variable (yet?)");
432 /* now we enter the reload phase, so no more spills are allowed */
433 vi->reload_phase = 1;
435 /* add reload to graph and schedule */
436 blk = get_nodes_block(before);
437 spill = pset_first(vi->spills); /* For now use an arbitrary spill node. This is corrected later in fix_reloads */
438 pset_break(vi->spills);
439 reload = be_new_Reload(raenv->cls, raenv->irg, blk, get_irn_mode(get_irn_n(spill, 0)), spill);
441 sched_add_before(before, reload);
443 /* create a new variable for the result of the reload */
444 assert(!var_find(raenv->vars, var_nr_for_reload) && "Each reload must define a new variable");
445 var_add_value(raenv, var_nr_for_reload, reload);
447 /* remember the reload */
448 pset_insert_ptr(vi->reloads, reload);
453 static INLINE pset *get_var_values(be_raext_env_t *raenv, int var_nr) {
454 var_info_t *vi = var_find(raenv->vars, var_nr);
455 assert(vi && "Variable does not (yet?) exist");
459 static INLINE pset *get_var_spills(be_raext_env_t *raenv, int var_nr) {
460 var_info_t *vi = var_find(raenv->vars, var_nr);
461 assert(vi && "Variable does not (yet?) exist");
465 static INLINE pset *get_var_reloads(be_raext_env_t *raenv, int var_nr) {
466 var_info_t *vi = var_find(raenv->vars, var_nr);
467 assert(vi && "Variable does not (yet?) exist");
472 * Define variables (numbers) for all SSA-values.
473 * All values in a phi class get assigned the same variable name.
474 * The link field maps values to the var-name
476 static void values_to_vars(ir_node *irn, void *env) {
477 be_raext_env_t *raenv = env;
482 vals = get_phi_class(irn);
485 /* not a phi class member, value == var */
486 vals = pset_new_ptr(1);
487 pset_insert_ptr(vals, irn);
490 /* values <--> var mapping */
491 n = pset_first(vals);
492 nr = get_irn_node_nr(n);
493 for (; n; n=pset_next(vals))
494 var_add_value(raenv, nr, n);
497 /******************************************************************************
500 / \ _ __ _ __ | |_ _ | |__) |___ ___ _ _| | |_
501 / /\ \ | '_ \| '_ \| | | | | | _ // _ \/ __| | | | | __|
502 / ____ \| |_) | |_) | | |_| | | | \ \ __/\__ \ |_| | | |_
503 /_/ \_\ .__/| .__/|_|\__, | |_| \_\___||___/\__,_|_|\__|
506 *****************************************************************************/
508 #define INVALID_FILE_FORMAT assert(0 && "Invalid file format.")
510 static INLINE int is_before(const char *s, size_t len) {
511 if (!strncmp(s, "before", len))
513 if (!strncmp(s, "after", len))
519 static void fix_reloads(be_raext_env_t *raenv) {
521 set_foreach(raenv->vars, vi)
522 be_introduce_copies_pset(raenv->dom_info, vi->spills);
526 * Read in the actions performed by the external allocator.
527 * Apply these transformations to the irg.
529 static void read_and_apply_results(be_raext_env_t *raenv, char *filename) {
534 if (!(f = fopen(filename, "rt"))) {
535 fprintf(stderr, "Could not open file %s for reading\n", filename);
544 int loc, var_use_ident, var_def_ident, pos;
548 if (fscanf(f, " spill %6s %d %d ", &where, &loc, &var_use_ident) == 3) {
550 /* determine the node to insert the spill before */
551 ir_node *anchor = pmap_get_sth(raenv->nodes, loc);
552 assert(anchor && "insn-nr does not exist");
553 if (!is_before(where, sizeof(where)))
554 anchor = sched_next(anchor);
556 var_add_spill(raenv, var_use_ident, anchor);
559 /* handle a reload */
560 else if (fscanf(f, " reload %s %d %d %d ", &where, &loc, &var_def_ident, &var_use_ident) == 4) {
562 /* determine the node to insert the spill before */
563 ir_node *anchor = pmap_get_sth(raenv->nodes, loc);
564 assert(anchor && "insn-nr does not exist");
565 if (!is_before(where, sizeof(where)))
566 anchor = sched_next(anchor);
568 var_add_reload(raenv, var_use_ident, var_def_ident, anchor);
571 /* handle a set_irn_n */
572 else if (fscanf(f, " setarg %d %d %d ", &loc, &pos, &var_use_ident) == 3) {
573 ir_node *to_change, *new_arg;
574 var_info_t *vi = var_find(raenv->vars, var_use_ident);
575 assert(vi && vi->values && "New argument does not exist");
577 to_change = pmap_get_sth(raenv->nodes, loc);
578 assert(to_change && "insn-nr does not exist");
580 new_arg = dom_up_search(vi->values, to_change);
581 set_irn_n(to_change, pos, new_arg);
584 /* handle a copy insertion */
585 else if (fscanf(f, " copy %s %d %d %d ", &where, &loc, &var_def_ident, &var_use_ident) == 4) {
587 Ziel der Kopie ist Variable die bereits existiert
588 Ziel der Kopie ist eine neue Variable
599 int var_use_ident, reg_nr;
601 /* assign register */
602 if (fscanf(f, " assign %d %d ", &var_use_ident, ®_nr) == 2) {
603 pset *vals = get_var_values(raenv, var_use_ident);
606 assert(vals && "Variable does not (yet?) exist!");
607 pset_foreach(vals, irn)
608 arch_set_irn_register(raenv->aenv, irn, arch_register_for_index(raenv->cls, var_use_ident));
619 /* Free the psets held in the variable-infos */
620 set_foreach(raenv->vars, vi) {
621 del_pset(vi->values);
622 del_pset(vi->spills);
623 del_pset(vi->reloads);
627 /******************************************************************************
630 | | | |_ _ _ __ ___ _ __ ___ _ __
631 | | | | | | | '_ ` _ \| '_ \ / _ \ '__|
632 | |__| | |_| | | | | | | |_) | __/ |
633 |_____/ \__,_|_| |_| |_| .__/ \___|_|
636 *****************************************************************************/
640 * Check if node irn has a limited-constraint at position pos.
641 * If yes, dump it to FILE raenv->f
643 static INLINE void dump_constraint(be_raext_env_t *raenv, ir_node *irn, int pos) {
644 bitset_t *bs = bitset_alloca(raenv->cls->n_regs);
645 arch_register_req_t req;
647 arch_get_register_req(raenv->aenv, &req, irn, pos);
648 if (arch_register_req_is(&req, limited)) {
650 req.limited(req.limited_env, bs);
651 reg_nr = bitset_next_set(bs, 0);
652 fprintf(raenv->f, " <%d>", reg_nr);
653 assert(-1 == bitset_next_set(bs, reg_nr+1) && "Constraints with more than 1 possible register are not supported");
659 * Dump all blocks and instructions in that block
661 static void dump_blocks(ir_node *blk, void *env) {
662 be_raext_env_t *raenv = env;
665 int nr = get_irn_node_nr(blk);
667 pmap_insert_sth(raenv->nodes, nr, blk);
669 /* begin block scope */
671 fprintf(f, " block %d {\n", nr);
673 /* for each instruction */
674 for(irn=sched_first(blk); !sched_is_end(irn); irn=sched_next(irn)) {
678 if (is_Phi(irn) || !is_sth_in_reg_class(raenv, irn))
681 /* kind of instruction */
682 if (arch_irn_classify(raenv->aenv, irn) == arch_irn_class_copy)
684 else if (arch_irn_classify(raenv->aenv, irn) == arch_irn_class_call)
690 node_nr = get_irn_node_nr(irn);
691 fprintf(f, " %ld {\n", node_nr);
693 pmap_insert_sth(raenv->nodes, node_nr, irn);
700 for (i=0, max=get_irn_arity(irn); i<max; ++i) {
701 ir_node *arg = get_irn_n(irn, i);
702 if (arch_irn_has_reg_class(raenv->aenv, arg, -1, raenv->cls)) {
703 fprintf(f, " %d", get_var_info(arg)->var_nr);
704 dump_constraint(raenv, irn, i);
713 /* special handling of projs */
714 if (get_irn_mode(irn) == mode_T) {
715 for (irn = sched_next(irn); is_Proj(irn); irn = sched_next(irn))
716 if (arch_irn_has_reg_class(raenv->aenv, irn, -1, raenv->cls)) {
717 fprintf(f, " %d", get_var_info(irn)->var_nr);
718 dump_constraint(raenv, irn, -1);
720 irn = sched_prev(irn); /* for outer loop */
722 if (arch_irn_has_reg_class(raenv->aenv, irn, -1, raenv->cls)) {
723 fprintf(f, " %d", get_var_info(irn)->var_nr);
724 dump_constraint(raenv, irn, -1);
729 /* end of insn scope */
733 /* end the block scope */
739 * Dump all control flow edges of this irg
741 static void dump_edges(ir_node *blk, void *env) {
742 be_raext_env_t *raenv = env;
745 if (get_irg_start_block(get_irn_irg(blk)) == blk)
748 /* dump cf edges in the flow-order "pred succ" */
749 for (i=0, max=get_irn_arity(blk); i<max; ++i) {
750 ir_node *pred = get_Block_cfgpred_block(blk, i);
751 fprintf(raenv->f, " cf_edge %ld %ld\n", get_irn_node_nr(pred), get_irn_node_nr(blk));
757 * Dump all information needed by the external
758 * register allocator to a single file.
760 static void dump_to_file(be_raext_env_t *raenv, char *filename) {
764 if (!(f = fopen(filename, "wt"))) {
765 fprintf(stderr, "Could not open file %s for writing\n", filename);
770 /* dump register info */
771 reg_count = arch_register_class_n_regs(raenv->cls);
772 fprintf(f, "regs %d", reg_count);
774 fprintf(f, " saved-by-caller");
775 for (i=0; i<reg_count; ++i)
776 if (arch_register_type_is(arch_register_for_index(raenv->cls, i), caller_saved))
777 fprintf(f, " %d", i);
779 fprintf(f, " saved-by-callee");
780 for (i=0; i<reg_count; ++i)
781 if (arch_register_type_is(arch_register_for_index(raenv->cls, i), callee_saved))
782 fprintf(f, " %d", i);
788 fprintf(f, "cfg %s {\n", filename);
789 irg_block_walk_graph(raenv->irg, NULL, dump_blocks, raenv);
790 irg_block_walk_graph(raenv->irg, NULL, dump_edges, raenv);
797 /******************************************************************************
800 | |__ __ _____ ___ _ _| |_ ___
801 | __| \ \/ / _ \/ __| | | | __/ _ \
802 | |____ > < __/ (__| |_| | || __/
803 |______/_/\_\___|\___|\__,_|\__\___|
804 *****************************************************************************/
807 * Execute the external register allocator specified in the
808 * firm-option firm.be.ra.ext.callee
810 static void execute(char *prog_to_call, char *out_file, char *result_file) {
814 snprintf(cmd_line, sizeof(cmd_line), "%s %s %s", prog_to_call, out_file, result_file);
816 ret_status = system(cmd_line);
817 assert(ret_status != -1 && "Invokation of external register allocator failed");
820 /******************************************************************************
824 | |\/| |/ _` | | '_ \
825 | | | | (_| | | | | |
826 |_| |_|\__,_|_|_| |_|
827 *****************************************************************************/
830 * Default values for options
832 static void (*ssa_destr)(be_raext_env_t*) = ssa_destr_simple;
833 static char callee[128] = "echo";
837 * Allocate registers with an external program using a text-file interface.
839 * Do some computations (SSA-destruction and mapping of values--vars)
841 * Execute external program
842 * Read in results and apply them
845 static void be_ra_extern_main(const be_main_env_t *env, ir_graph *irg) {
846 be_raext_env_t raenv;
852 raenv.aenv = env->arch_env;
853 raenv.dom_info = be_compute_dominance_frontiers(irg);
854 raenv.vars = new_set(compare_var_infos, 64);
855 raenv.nodes = pmap_create();
856 /* SSA destruction */
860 phi_class_compute(irg);
861 irg_walk_graph(irg, values_to_vars, NULL, &raenv);
863 dump_ir_block_graph_sched(irg, "-extern-ssadestr");
865 /* For all register classes */
866 for(clsnr = 0, clss = arch_isa_get_n_reg_class(raenv.aenv->isa); clsnr < clss; ++clsnr) {
867 char out[256], in[256];
869 raenv.cls = arch_isa_get_reg_class(raenv.aenv->isa, clsnr);
870 ir_snprintf(out, sizeof(out), "%F-%s.ra", irg, raenv.cls->name);
871 ir_snprintf(in, sizeof(in), "%F-%s.ra.res", irg, raenv.cls->name);
873 dump_to_file(&raenv, out);
875 execute(callee, out, in);
877 read_and_apply_results(&raenv, in);
881 pmap_destroy(raenv.nodes);
883 be_free_dominance_frontiers(raenv.dom_info);
887 /******************************************************************************
890 | | | |_ __ | |_ _ ___ _ __ ___
891 | | | | '_ \| __| |/ _ \| '_ \/ __|
892 | |__| | |_) | |_| | (_) | | | \__ \
893 \____/| .__/ \__|_|\___/|_| |_|___/
896 *****************************************************************************/
900 /* TODO: explicit cast to void * is ugly, but ISO-C forbids
901 assignment from func ptr to void ptr. This should probably be fixed
903 static const lc_opt_enum_const_ptr_items_t ssa_destr_items[] = {
904 { "simple", (void *)ssa_destr_simple },
905 { "rastello", (void *)ssa_destr_rastello },
909 static lc_opt_enum_const_ptr_var_t ssa_destr_var = {
910 (const void **) &ssa_destr, ssa_destr_items
913 static const lc_opt_table_entry_t be_ra_extern_options[] = {
914 LC_OPT_ENT_ENUM_FUNC_PTR("ssa_destr", "SSA destruction flavor", &ssa_destr_var),
915 LC_OPT_ENT_STR("callee", "The external program to call", callee, sizeof(callee)),
919 static void be_ra_extern_register_options(lc_opt_entry_t *root) {
920 lc_opt_entry_t *grp = lc_opt_get_grp(root, "ext");
922 lc_opt_add_table(grp, be_ra_extern_options);
925 #endif /* WITH_LIBCORE */
927 const be_ra_t be_ra_external_allocator = {
929 be_ra_extern_register_options,