Panic in case of an invalid solution.
[libfirm] / ir / be / bespillbelady2.c
index a0aa866..4c8a641 100644 (file)
 #include "dfs_t.h"
 
 #include "beutil.h"
-#include "bearch_t.h"
-#include "besched_t.h"
+#include "bearch.h"
+#include "besched.h"
 #include "beirgmod.h"
 #include "belive_t.h"
-#include "benode_t.h"
+#include "benode.h"
 #include "bechordal_t.h"
-#include "bespilloptions.h"
+#include "bespill.h"
 #include "beloopana.h"
-#include "beirg_t.h"
+#include "beirg.h"
 #include "bemodule.h"
-#include "bespill.h"
+#include "bespillutil.h"
 
 #include "lc_opts.h"
 #include "lc_opts_enum.h"
@@ -148,7 +148,7 @@ static inline void workset_print(const workset_t *w)
 {
        int i;
 
-       for(i = 0; i < w->len; ++i) {
+       for (i = 0; i < w->len; ++i) {
                ir_fprintf(stderr, "%+F %d\n", w->vals[i].irn, w->vals[i].time);
        }
 }
@@ -156,22 +156,18 @@ static inline void workset_print(const workset_t *w)
 /**
  * Alloc a new workset on obstack @p ob with maximum size @p max
  */
-static inline workset_t *new_workset(belady_env_t *env, struct obstack *ob) {
-       workset_t *res;
-       size_t size = sizeof(*res) + (env->n_regs)*sizeof(res->vals[0]);
-       res = obstack_alloc(ob, size);
-       memset(res, 0, size);
-       return res;
+static inline workset_t *new_workset(belady_env_t *env, struct obstack *ob)
+{
+       return OALLOCFZ(ob, workset_t, vals, env->n_regs);
 }
 
 /**
  * Alloc a new instance on obstack and make it equal to @param ws
  */
-static inline workset_t *workset_clone(belady_env_t *env, struct obstack *ob, workset_t *ws) {
-       workset_t *res;
-       size_t size = sizeof(*res) + (env->n_regs)*sizeof(res->vals[0]);
-       res = obstack_alloc(ob, size);
-       memcpy(res, ws, size);
+static inline workset_t *workset_clone(belady_env_t *env, struct obstack *ob, workset_t *ws)
+{
+       workset_t *res = OALLOCF(ob, workset_t, vals, env->n_regs);
+       memcpy(res, ws, sizeof(*res) + (env->n_regs)*sizeof(res->vals[0]));
        return res;
 }
 
@@ -179,7 +175,8 @@ static inline workset_t *workset_clone(belady_env_t *env, struct obstack *ob, wo
  * Do NOT alloc anything. Make @param tgt equal to @param src.
  * returns @param tgt for convenience
  */
-static inline workset_t *workset_copy(belady_env_t *env, workset_t *tgt, workset_t *src) {
+static inline workset_t *workset_copy(belady_env_t *env, workset_t *tgt, workset_t *src)
+{
        size_t size = sizeof(*src) + (env->n_regs)*sizeof(src->vals[0]);
        memcpy(tgt, src, size);
        return tgt;
@@ -190,7 +187,8 @@ static inline workset_t *workset_copy(belady_env_t *env, workset_t *tgt, workset
  * @param count locations given at memory @param locs.
  * Set the length of @param ws to count.
  */
-static inline void workset_bulk_fill(workset_t *workset, int count, const loc_t *locs) {
+static inline void workset_bulk_fill(workset_t *workset, int count, const loc_t *locs)
+{
        workset->len = count;
        memcpy(&(workset->vals[0]), locs, count * sizeof(locs[0]));
 }
@@ -199,7 +197,8 @@ static inline void workset_bulk_fill(workset_t *workset, int count, const loc_t
  * Inserts the value @p val into the workset, iff it is not
  * already contained. The workset must not be full.
  */
-static inline void workset_insert(belady_env_t *env, workset_t *ws, ir_node *val) {
+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->cls, val)) {
@@ -208,7 +207,7 @@ static inline void workset_insert(belady_env_t *env, workset_t *ws, ir_node *val
        }
 
        /* check if val is already contained */
-       for(i=0; i<ws->len; ++i)
+       for (i=0; i<ws->len; ++i)
                if (ws->vals[i].irn == val)
                        return;
 
@@ -220,16 +219,18 @@ static inline void workset_insert(belady_env_t *env, workset_t *ws, ir_node *val
 /**
  * Removes all entries from this workset
  */
-static inline void workset_clear(workset_t *ws) {
+static inline void workset_clear(workset_t *ws)
+{
        ws->len = 0;
 }
 
 /**
  * Removes the value @p val from the workset if present.
  */
-static inline void workset_remove(workset_t *ws, ir_node *val) {
+static inline void workset_remove(workset_t *ws, ir_node *val)
+{
        int i;
-       for(i=0; i<ws->len; ++i) {
+       for (i=0; i<ws->len; ++i) {
                if (ws->vals[i].irn == val) {
                        ws->vals[i] = ws->vals[--ws->len];
                        return;
@@ -237,9 +238,10 @@ static inline void workset_remove(workset_t *ws, ir_node *val) {
        }
 }
 
-static inline int workset_get_index(const workset_t *ws, const ir_node *val) {
+static inline int workset_get_index(const workset_t *ws, const ir_node *val)
+{
        int i;
-       for(i=0; i<ws->len; ++i) {
+       for (i=0; i<ws->len; ++i) {
                if (ws->vals[i].irn == val)
                        return i;
        }
@@ -253,7 +255,7 @@ static inline int workset_get_index(const workset_t *ws, const ir_node *val) {
  * @p v  A variable to put the current value in
  * @p i  An integer for internal use
  */
-#define workset_foreach(ws, v, i)      for(i=0; \
+#define workset_foreach(ws, v, i)      for (i=0; \
                                                                                v=(i < ws->len) ? ws->vals[i].irn : NULL, i < ws->len; \
                                                                                ++i)
 
@@ -296,13 +298,12 @@ typedef struct _block_info_t {
 static inline void *new_block_info(belady_env_t *bel, int id)
 {
        ir_node      *bl  = bel->blocks[id];
-       block_info_t *res = obstack_alloc(&bel->ob, sizeof(*res));
-       memset(res, 0, sizeof(res[0]));
+       block_info_t *res = OALLOCZ(&bel->ob, block_info_t);
        res->first_non_in = NULL;
-       res->last_ins = NULL;
-       res->bel = bel;
-       res->bl  = bl;
-       res->id  = id;
+       res->last_ins     = NULL;
+       res->bel          = bel;
+       res->bl           = bl;
+       res->id           = id;
        res->exec_freq    = get_block_execfreq(bel->ef, bl);
        res->reload_cost  = bel->arch->reload_cost * res->exec_freq;
        res->free_at_jump = bel->n_regs;
@@ -333,21 +334,13 @@ typedef struct _next_use_t {
                                                                 or NULL. */
 } next_use_t;
 
-static void *next_use_init(ir_phase *phase, const ir_node *irn, void *old)
-{
-       (void) phase;
-       (void) irn;
-       (void) old;
-       return NULL;
-}
-
 static void build_next_uses(block_info_t *bi)
 {
        ir_node *irn;
 
        sched_renumber(bi->bl);
 
-       phase_init(&bi->next_uses, "next uses", bi->bel->irg, PHASE_DEFAULT_GROWTH, next_use_init, NULL);
+       phase_init(&bi->next_uses, bi->bel->irg, phase_irn_init_default);
        sched_foreach_reverse(bi->bl, irn) {
                int i;
 
@@ -442,8 +435,7 @@ struct _bring_in_t {
 
 static inline bring_in_t *new_bring_in(block_info_t *bi, ir_node *irn, const next_use_t *use)
 {
-       bring_in_t *br    = obstack_alloc(&bi->bel->ob, sizeof(br[0]));
-
+       bring_in_t *br      = OALLOC(&bi->bel->ob, bring_in_t);
        br->irn             = irn;
        br->bi              = bi;
        br->first_use       = use->irn;
@@ -503,10 +495,10 @@ static inline unsigned get_curr_distance(block_info_t *bi, const ir_node *irn, i
        next_use_t *use            = get_current_use(bi, irn);
        int flags                  = arch_irn_get_flags(irn);
 
-       assert(!(flags & arch_irn_flags_ignore));
+       assert(!arch_irn_is_ignore(irn));
 
        /* We have to keep non-spillable nodes in the working set */
-       if(flags & arch_irn_flags_dont_spill)
+       if (flags & arch_irn_flags_dont_spill)
                return 0;
 
        if (!is_usage && use && use->step == curr_step)
@@ -560,7 +552,8 @@ static inline int is_transport_in(const ir_node *bl, const ir_node *irn)
  * @p is_usage indicates that the values in new_vals are used (not defined)
  * In this case reloads must be performed
  */
-static void displace(block_info_t *bi, workset_t *new_vals, int is_usage) {
+static void displace(block_info_t *bi, workset_t *new_vals, int is_usage)
+{
        belady_env_t *env       = bi->bel;
        workset_t    *ws        = env->ws;
        ir_node     **to_insert = ALLOCAN(ir_node*, env->n_regs);
@@ -656,7 +649,8 @@ static void displace(block_info_t *bi, workset_t *new_vals, int is_usage) {
  * whether it is used from a register or is reloaded
  * before the use.
  */
-static void belady(belady_env_t *env, int id) {
+static void belady(belady_env_t *env, int id)
+{
        block_info_t *block_info = new_block_info(env, id);
        const ir_node *block     = block_info->bl;
 
@@ -694,7 +688,7 @@ static void belady(belady_env_t *env, int id) {
 
                /* allocate all values _used_ by this instruction */
                workset_clear(new_vals);
-               for(i = 0, arity = get_irn_arity(irn); i < arity; ++i) {
+               for (i = 0, arity = get_irn_arity(irn); i < arity; ++i) {
                        workset_insert(env, new_vals, get_irn_n(irn, i));
                }
                DBG((dbg, DBG_DECIDE, "\t* uses\n"));
@@ -706,7 +700,7 @@ static void belady(belady_env_t *env, int id) {
                 * augmenting the pressure. Note, that a variable is dead
                 * if it has no further use in this block and is *not* live end
                 */
-               for(i = 0, arity = get_irn_arity(irn); i < arity; ++i) {
+               for (i = 0, arity = get_irn_arity(irn); i < arity; ++i) {
                        ir_node *op = get_irn_n(irn, i);
                        next_use_t *use = get_current_use(block_info, op);
 
@@ -742,7 +736,7 @@ static void belady(belady_env_t *env, int id) {
                env->instr_nr++;
        }
 
-       phase_free(&block_info->next_uses);
+       phase_deinit(&block_info->next_uses);
 
        /* Remember end-workset for this block */
        block_info->ws_end = workset_clone(env, &env->ob, env->ws);
@@ -831,7 +825,7 @@ static inline const workset_t *get_end_state(global_end_state_t *ges, block_info
 static block_state_t *new_block_state(global_end_state_t *ges, block_info_t *bi)
 {
        block_state_t *bs = get_block_state(ges, bi);
-       block_state_t *nw = obstack_alloc(&ges->obst, sizeof(nw[0]));
+       block_state_t *nw = OALLOC(&ges->obst, block_state_t);
 
        nw->next_intern = bs;
        nw->next        = ges->bs_top;
@@ -854,7 +848,7 @@ static block_state_t *new_block_state(global_end_state_t *ges, block_info_t *bi)
 
 static irn_action_t *new_irn_action(global_end_state_t *ges, ir_node *irn, const ir_node *bl)
 {
-       irn_action_t *ia = obstack_alloc(&ges->obst, sizeof(ia[0]));
+       irn_action_t *ia = OALLOC(&ges->obst, irn_action_t);
 
        ia->irn  = irn;
        ia->bl   = bl;
@@ -1414,8 +1408,8 @@ static void global_assign(belady_env_t *env)
        ges.version      = ver_make_newer(ver_oldest);
        ges.succ_phis    = bitset_irg_obstack_alloc(&ges.obst, env->irg);
        ges.committed    = bitset_obstack_alloc(&ges.obst, env->n_blocks);
-       ges.bs_tops      = obstack_alloc(&ges.obst, sizeof(ges.bs_tops[0])      * env->n_blocks);
-       ges.bs_tops_vers = obstack_alloc(&ges.obst, sizeof(ges.bs_tops_vers[0]) * env->n_blocks);
+       ges.bs_tops      = OALLOCN(&ges.obst, block_state_t*, env->n_blocks);
+       ges.bs_tops_vers = OALLOCN(&ges.obst, unsigned,       env->n_blocks);
 
        /* invalidate all state stack pointer versions */
        for (i = 0; i < env->n_blocks; ++i) {
@@ -1466,18 +1460,17 @@ static void collect_blocks(ir_node *bl, void *data)
  * In the transformed graph, the register pressure never exceeds the number
  * of available registers.
  *
- * @param birg  The backend graph
+ * @param irg   The graph
  * @param cls   The register class to spill
  */
-void be_spill_belady(be_irg_t *birg, const arch_register_class_t *cls)
+static void be_spill_belady(ir_graph *irg, const arch_register_class_t *cls)
 {
-       ir_graph *irg = be_get_birg_irg(birg);
        belady_env_t env;
        int i, n_regs;
 
        /* some special classes contain only ignore regs, nothing to do then */
-       n_regs = cls->n_regs - be_put_ignore_regs(birg, cls, NULL);
-       if(n_regs == 0)
+       n_regs = cls->n_regs - be_put_ignore_regs(irg, cls, NULL);
+       if (n_regs == 0)
                return;
 
        be_clear_links(irg);
@@ -1485,14 +1478,14 @@ void be_spill_belady(be_irg_t *birg, const arch_register_class_t *cls)
        /* init belady env */
        obstack_init(&env.ob);
        env.irg        = irg;
-       env.arch       = be_get_birg_arch_env(birg);
+       env.arch       = be_get_irg_arch_env(irg);
        env.cls        = cls;
-       env.lv         = be_get_birg_liveness(birg);
+       env.lv         = be_get_irg_liveness(irg);
        env.dfs        = env.lv->dfs;
        env.n_regs     = n_regs;
        env.ws         = new_workset(&env, &env.ob);
-       env.senv       = be_new_spill_env(birg);
-       env.ef         = be_get_birg_exec_freq(birg);
+       env.senv       = be_new_spill_env(irg);
+       env.ef         = be_get_irg_exec_freq(irg);
        env.spilled    = bitset_irg_obstack_alloc(&env.ob, irg);
        env.extra_spilled = ir_nodeset_new(64);
        env.n_blocks   = 0;
@@ -1532,6 +1525,7 @@ void be_spill_belady(be_irg_t *birg, const arch_register_class_t *cls)
        obstack_free(&env.ob, NULL);
 }
 
+BE_REGISTER_MODULE_CONSTRUCTOR(be_init_spillbelady2);
 void be_init_spillbelady2(void)
 {
        lc_opt_entry_t *be_grp    = lc_opt_get_grp(firm_opt_get_root(), "be");
@@ -1546,5 +1540,3 @@ void be_init_spillbelady2(void)
        be_register_spiller("belady2", &belady_spiller);
        FIRM_DBG_REGISTER(dbg, "firm.be.spill.belady2");
 }
-
-BE_REGISTER_MODULE_CONSTRUCTOR(be_init_spillbelady2);