Remove the attribute const arch_env_t *arch_env from struct ia32_code_gen_t. We...
[libfirm] / ir / be / bespillbelady2.c
index 3cb4126..74a6e6c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1995-2007 University of Karlsruhe.  All right reserved.
+ * Copyright (C) 1995-2008 University of Karlsruhe.  All right reserved.
  *
  * This file is part of libFirm.
  *
@@ -32,9 +32,7 @@
  *   capacity of the blocks to let global variables live through
  *   them.
  */
-#ifdef HAVE_CONFIG_H
 #include "config.h"
-#endif
 
 #include <math.h>
 #include <limits.h>
@@ -54,7 +52,6 @@
 #include "irprintf.h"
 #include "execfreq.h"
 #include "dfs_t.h"
-#include "xmalloc.h"
 
 #include "beutil.h"
 #include "bearch_t.h"
@@ -69,9 +66,8 @@
 #include "bemodule.h"
 #include "bespill.h"
 
-#include <libcore/lc_opts.h>
-#include <libcore/lc_opts_enum.h>
-#include <libcore/lc_timing.h>
+#include "lc_opts.h"
+#include "lc_opts_enum.h"
 
 #define DBG_SPILL     1
 #define DBG_WSETS     2
@@ -128,15 +124,16 @@ typedef struct _belady_env_t {
        be_lv_t *lv;
        ir_exec_freq *ef;
 
-       ir_node **blocks;   /**< Array of all blocks. */
-       int n_blocks;       /**< Number of blocks in the graph. */
-       int n_regs;                     /**< number of regs in this reg-class */
-       workset_t *ws;          /**< the main workset used while processing a block. ob-allocated */
-       ir_node *instr;         /**< current instruction */
-       int instr_nr;           /**< current instruction number (relative to block start) */
+       ir_node **blocks;            /**< Array of all blocks. */
+       int n_blocks;                /**< Number of blocks in the graph. */
+       int n_regs;                              /**< number of regs in this reg-class */
+       workset_t *ws;                   /**< the main workset used while processing a block. ob-allocated */
+       ir_node *instr;                  /**< current instruction */
+       int instr_nr;                    /**< current instruction number (relative to block start) */
 
-       spill_env_t *senv;      /**< see bespill.h */
-       bitset_t *spilled;  /**< bitset to keep all the irns which have already been spilled. */
+       spill_env_t *senv;               /**< see bespill.h */
+       bitset_t *spilled;           /**< bitset to keep all the irns which have already been spilled. */
+       ir_nodeset_t *extra_spilled; /** All nodes for which a special spill location has been computed. */
 } belady_env_t;
 
 
@@ -205,7 +202,7 @@ static INLINE void workset_bulk_fill(workset_t *workset, int count, const loc_t
 static INLINE void workset_insert(belady_env_t *env, workset_t *ws, ir_node *val) {
        int i;
        /* check for current regclass */
-       if (!arch_irn_consider_in_reg_alloc(env->arch, env->cls, val)) {
+       if (!arch_irn_consider_in_reg_alloc(env->cls, val)) {
                // DBG((dbg, DBG_WORKSET, "Skipped %+F\n", val));
                return;
        }
@@ -307,7 +304,7 @@ static INLINE void *new_block_info(belady_env_t *bel, int id)
        res->bl  = bl;
        res->id  = id;
        res->exec_freq    = get_block_execfreq(bel->ef, bl);
-       res->reload_cost  = bel->arch->isa->reload_cost * res->exec_freq;
+       res->reload_cost  = bel->arch->reload_cost * res->exec_freq;
        res->free_at_jump = bel->n_regs;
        INIT_LIST_HEAD(&res->br_head);
        set_irn_link(bl, res);
@@ -336,7 +333,7 @@ typedef struct _next_use_t {
                                                                 or NULL. */
 } next_use_t;
 
-static void *next_use_init(ir_phase *phase, ir_node *irn, void *old)
+static void *next_use_init(ir_phase *phase, const ir_node *irn, void *old)
 {
        (void) phase;
        (void) irn;
@@ -504,7 +501,7 @@ static INLINE unsigned get_curr_distance(block_info_t *bi, const ir_node *irn, i
        belady_env_t *env          = bi->bel;
        sched_timestep_t curr_step = sched_get_time_step(env->instr);
        next_use_t *use            = get_current_use(bi, irn);
-       int flags                  = arch_irn_get_flags(env->arch, irn);
+       int flags                  = arch_irn_get_flags(irn);
 
        assert(!(flags & arch_irn_flags_ignore));
 
@@ -738,7 +735,7 @@ static void belady(belady_env_t *env, int id) {
                if (is_op_forking(get_irn_op(env->instr))) {
                        for (i = get_irn_arity(env->instr) - 1; i >= 0; --i) {
                                ir_node *op = get_irn_n(env->instr, i);
-                               block_info->free_at_jump -= arch_irn_consider_in_reg_alloc(env->arch, env->cls, op);
+                               block_info->free_at_jump -= arch_irn_consider_in_reg_alloc(env->cls, op);
                        }
                }
 
@@ -1080,7 +1077,7 @@ static double can_bring_in(global_end_state_t *ges, ir_node *bl, ir_node *irn, d
                         * there might by unknwons as operands of phis in that case
                         * we set the costs to zero, since they won't get spilled.
                         */
-                       if (arch_irn_consider_in_reg_alloc(env->arch, env->cls, op))
+                       if (arch_irn_consider_in_reg_alloc(env->cls, op))
                                c = can_make_available_at_end(ges, pr, op, limit - glob_costs, level + 1);
                        else
                                c = 0.0;
@@ -1328,7 +1325,8 @@ static void optimize_variable(global_end_state_t *ges, bring_in_t *br)
                                DBG((dbg, DBG_GLOBAL, "\t-> use blocked. local reload: %+F, try spill at: %+F\n",
                                                        br->first_use, better_spill_loc));
                                be_add_reload(env->senv, irn, br->first_use, env->cls, 1);
-                               be_add_spill(env->senv, irn, sched_next(better_spill_loc));
+                               be_add_spill(env->senv, irn, better_spill_loc);
+                               ir_nodeset_insert(env->extra_spilled, irn);
                        }
 
                        /*
@@ -1399,8 +1397,10 @@ static bring_in_t **determine_global_order(belady_env_t *env)
 
 static void global_assign(belady_env_t *env)
 {
+       ir_nodeset_iterator_t iter;
        global_end_state_t ges;
        bring_in_t **br;
+       ir_node *irn;
        int i, j;
 
        /*
@@ -1444,11 +1444,15 @@ static void global_assign(belady_env_t *env)
                        if (!is_Phi(irn))
                                break;
 
-                       if (arch_irn_consider_in_reg_alloc(env->arch, env->cls, irn)
+                       if (arch_irn_consider_in_reg_alloc(env->cls, irn)
                                        && !bitset_contains_irn(ges.succ_phis, irn))
                                be_spill_phi(env->senv, irn);
                }
        }
+
+       /* check dominance for specially spilled nodes. */
+       foreach_ir_nodeset (env->extra_spilled, irn, iter)
+               make_spill_locations_dominate_irn(env->senv, irn);
 }
 
 static void collect_blocks(ir_node *bl, void *data)
@@ -1491,6 +1495,7 @@ void be_spill_belady(be_irg_t *birg, const arch_register_class_t *cls)
        env.senv       = be_new_spill_env(birg);
        env.ef         = be_get_birg_exec_freq(birg);
        env.spilled    = bitset_irg_obstack_alloc(&env.ob, irg);
+       env.extra_spilled = ir_nodeset_new(64);
        env.n_blocks   = 0;
 
        irg_block_walk_graph(irg, NULL, collect_blocks, &env);
@@ -1509,11 +1514,21 @@ void be_spill_belady(be_irg_t *birg, const arch_register_class_t *cls)
 
        global_assign(&env);
 
+       /* check dominance for specially spilled nodes. */
+       {
+               ir_nodeset_iterator_t iter;
+               ir_node *irn;
+
+               foreach_ir_nodeset (env.extra_spilled, irn, iter)
+                       make_spill_locations_dominate_irn(env.senv, irn);
+       }
+
        /* Insert spill/reload nodes into the graph and fix usages */
        be_insert_spills_reloads(env.senv);
 
        /* clean up */
        be_delete_spill_env(env.senv);
+       ir_nodeset_del(env.extra_spilled);
 
        obstack_free(&env.ob, NULL);
 }