- BugFix: check mode_T nodes for different_constraints
[libfirm] / ir / be / bespill.c
index 78ff148..04c8860 100644 (file)
  * @date               29.09.2005
  * @version     $Id$
  */
-#ifdef HAVE_CONFIG_H
 #include "config.h"
-#endif
 
 #include <stdlib.h>
+#include <stdbool.h>
 
 #include "pset.h"
 #include "irnode_t.h"
@@ -54,7 +53,6 @@
 #include "belive_t.h"
 #include "benode_t.h"
 #include "bechordal_t.h"
-#include "bejavacoal.h"
 #include "bespilloptions.h"
 #include "bestatevent.h"
 #include "bessaconstr.h"
@@ -80,7 +78,7 @@ struct reloader_t {
 typedef struct spill_t spill_t;
 struct spill_t {
        spill_t *next;
-       ir_node *before;   /**< spill has to be placed before this node (or earlier) */
+       ir_node *after;  /**< spill has to be placed after this node (or earlier) */
        ir_node *spill;
 };
 
@@ -107,8 +105,6 @@ struct spill_env_t {
                                               placed */
        ir_nodeset_t      mem_phis;       /**< set of all spilled phis. */
        ir_exec_freq     *exec_freq;
-       unsigned          new_nodes_idx;  /**< all old nodes idx is smaller than
-                                              this */
 
 #ifdef FIRM_STATISTICS
        unsigned          spill_count;
@@ -156,7 +152,7 @@ spill_env_t *be_new_spill_env(be_irg_t *birg)
 {
        const arch_env_t *arch_env = birg->main_env->arch_env;
 
-       spill_env_t *env        = xmalloc(sizeof(env[0]));
+       spill_env_t *env = XMALLOC(spill_env_t);
        env->spills                     = new_set(cmp_spillinfo, 1024);
        env->irg            = be_get_birg_irg(birg);
        env->birg           = birg;
@@ -194,32 +190,31 @@ void be_delete_spill_env(spill_env_t *env)
  *
  */
 
-void be_add_spill(spill_env_t *env, ir_node *to_spill, ir_node *before)
+void be_add_spill(spill_env_t *env, ir_node *to_spill, ir_node *after)
 {
-#if 1
        spill_info_t *spill_info = get_spillinfo(env, to_spill);
        spill_t      *spill;
        spill_t      *s;
        spill_t      *last;
 
-       assert(! arch_irn_is(env->arch_env, to_spill, dont_spill));
-       DB((dbg, LEVEL_1, "Add spill of %+F before %+F\n", to_spill, before));
+       assert(!arch_irn_is(to_spill, dont_spill));
+       DB((dbg, LEVEL_1, "Add spill of %+F after %+F\n", to_spill, after));
 
        /* Just for safety make sure that we do not insert the spill in front of a phi */
-       for (; is_Phi(before); before = sched_next(before));
+       assert(!is_Phi(sched_next(after)));
 
        /* spills that are dominated by others are not needed */
        last = NULL;
        s    = spill_info->spills;
        for( ; s != NULL; s = s->next) {
                /* no need to add this spill if it is dominated by another */
-               if(value_dominates(s->before, before)) {
-                       DB((dbg, LEVEL_1, "...dominated by %+F, not added\n", s->before));
+               if(value_dominates(s->after, after)) {
+                       DB((dbg, LEVEL_1, "...dominated by %+F, not added\n", s->after));
                        return;
                }
                /* remove spills that we dominate */
-               if(value_dominates(before, s->before)) {
-                       DB((dbg, LEVEL_1, "...remove old spill at %+F\n", s->before));
+               if(value_dominates(after, s->after)) {
+                       DB((dbg, LEVEL_1, "...remove old spill at %+F\n", s->after));
                        if(last != NULL) {
                                last->next         = s->next;
                        } else {
@@ -231,12 +226,11 @@ void be_add_spill(spill_env_t *env, ir_node *to_spill, ir_node *before)
        }
 
        spill         = obstack_alloc(&env->obst, sizeof(spill[0]));
-       spill->before = before;
+       spill->after  = after;
        spill->next   = spill_info->spills;
        spill->spill  = NULL;
 
        spill_info->spills = spill;
-#endif
 }
 
 void be_add_remat(spill_env_t *env, ir_node *to_spill, ir_node *before,
@@ -269,7 +263,7 @@ void be_add_reload2(spill_env_t *env, ir_node *to_spill, ir_node *before,
        spill_info_t *info;
        reloader_t *rel;
 
-       assert(! arch_irn_is(env->arch_env, to_spill, dont_spill));
+       assert(!arch_irn_is(to_spill, dont_spill));
 
        info = get_spillinfo(env, to_spill);
 
@@ -326,9 +320,11 @@ ir_node *be_get_end_of_block_insertion_point(const ir_node *block)
 
 static ir_node *skip_keeps_phis(ir_node *node)
 {
-       node = sched_next(node);
-       while(is_Phi(node) || be_is_Keep(node)) {
-               node = sched_next(node);
+       while(true) {
+               ir_node *next = sched_next(node);
+               if(!is_Phi(next) && !be_is_Keep(next))
+                       break;
+               node = next;
        }
        return node;
 }
@@ -385,7 +381,7 @@ void be_spill_phi(spill_env_t *env, ir_node *node)
        block = get_nodes_block(node);
        spill = get_spillinfo(env, node);
        for(i = 0, arity = get_irn_arity(node); i < arity; ++i) {
-               ir_node *arg        = get_irn_n(node, i);
+               ir_node *arg = get_irn_n(node, i);
                ir_node *insert;
                //get_spillinfo(env, arg);
 
@@ -394,6 +390,7 @@ void be_spill_phi(spill_env_t *env, ir_node *node)
                if(!sched_is_scheduled(arg)) {
                        ir_node *pred_block = get_Block_cfgpred_block(block, i);
                        insert = be_get_end_of_block_insertion_point(pred_block);
+                       insert = sched_prev(insert);
                } else {
                        insert = skip_keeps_phis(arg);
                }
@@ -442,19 +439,14 @@ static void spill_irn(spill_env_t *env, spill_info_t *spillinfo)
        DBG((dbg, LEVEL_1, "spilling %+F ... \n", to_spill));
        spill = spillinfo->spills;
        for( ; spill != NULL; spill = spill->next) {
-               ir_node *block  = get_block(spill->before);
-               ir_node *before = spill->before;
-
-               /* place all spills before the reloads (as we can't guarantee the
-                * same order as the be_add_spill and be_add_reload calls.
-                * Also make sure that we do not run into Phis when going up. */
-               while(get_irn_idx(sched_prev(before)) > env->new_nodes_idx && !is_Phi(sched_prev(before))) {
-                       before = sched_prev(before);
-               }
+               ir_node *after = spill->after;
+               ir_node *block = get_block(after);
 
-               spill->spill    = be_spill(env->arch_env, block, to_spill);
-               sched_add_before(before, spill->spill);
-               DB((dbg, LEVEL_1, "\t%+F before %+F\n", spill->spill, before));
+               after = skip_keeps_phis(after);
+
+               spill->spill = be_spill(block, to_spill);
+               sched_add_after(after, spill->spill);
+               DB((dbg, LEVEL_1, "\t%+F after %+F\n", spill->spill, after));
 #ifdef FIRM_STATISTICS
                env->spill_count++;
 #endif
@@ -499,7 +491,7 @@ static void spill_phi(spill_env_t *env, spill_info_t *spillinfo)
 
        /* override or replace spills list... */
        spill         = obstack_alloc(&env->obst, sizeof(spill[0]));
-       spill->before = skip_keeps_phis(phi);
+       spill->after  = skip_keeps_phis(phi);
        spill->spill  = new_r_Phi(irg, block, arity, ins, mode_M);
        spill->next   = NULL;
 
@@ -578,7 +570,7 @@ static int is_value_available(spill_env_t *env, const ir_node *arg,
        /*
         * Ignore registers are always available
         */
-       if(arch_irn_is(env->arch_env, arg, ignore)) {
+       if (arch_irn_is(arg, ignore)) {
                return 1;
        }
 
@@ -610,13 +602,11 @@ static int is_value_available(spill_env_t *env, const ir_node *arg,
 /**
  * Checks whether the node can principally be rematerialized
  */
-static int is_remat_node(spill_env_t *env, const ir_node *node)
+static int is_remat_node(const ir_node *node)
 {
-       const arch_env_t *arch_env = env->arch_env;
-
        assert(!be_is_Spill(node));
 
-       if(arch_irn_is(arch_env, node, rematerializable))
+       if (arch_irn_is(node, rematerializable))
                return 1;
 
        return 0;
@@ -639,18 +629,18 @@ static int check_remat_conditions_costs(spill_env_t *env,
        int argremats;
        int costs = 0;
 
-       if(!is_remat_node(env, spilled))
+       if (!is_remat_node(spilled))
                return REMAT_COST_INFINITE;
 
        if(be_is_Reload(spilled)) {
                costs += 2;
        } else {
-               costs += arch_get_op_estimated_cost(env->arch_env, spilled);
+               costs += arch_get_op_estimated_cost(spilled);
        }
        if(parentcosts + costs >= env->reload_cost + env->spill_cost) {
                return REMAT_COST_INFINITE;
        }
-       if(arch_irn_is(env->arch_env, spilled, modify_flags)) {
+       if (arch_irn_is(spilled, modify_flags)) {
                return REMAT_COST_INFINITE;
        }
 
@@ -719,6 +709,7 @@ static ir_node *do_remat(spill_env_t *env, ir_node *spilled, ir_node *reloader)
                          get_irn_op(spilled), get_irn_mode(spilled),
                          get_irn_arity(spilled), ins);
        copy_node_attr(spilled, res);
+       arch_env_mark_remat(env->arch_env, res);
        new_backedge_info(res);
 
        DBG((dbg, LEVEL_1, "Insert remat %+F of %+F before reloader %+F\n", res, spilled, reloader));
@@ -808,7 +799,7 @@ static void determine_spill_costs(spill_env_t *env, spill_info_t *spillinfo)
        if(spillinfo->spill_costs >= 0)
                return;
 
-       assert(! arch_irn_is(env->arch_env, to_spill, dont_spill));
+       assert(!arch_irn_is(to_spill, dont_spill));
        assert(!be_is_Reload(to_spill));
 
        /* some backends have virtual noreg/unknown nodes that are not scheduled
@@ -819,9 +810,9 @@ static void determine_spill_costs(spill_env_t *env, spill_info_t *spillinfo)
        if(!sched_is_scheduled(to_spill)) {
                /* override spillinfos or create a new one */
                spill_t *spill = obstack_alloc(&env->obst, sizeof(spill[0]));
-               spill->before  = NULL;
-               spill->next    = NULL;
-               spill->spill   = new_NoMem();
+               spill->after = NULL;
+               spill->next  = NULL;
+               spill->spill = new_NoMem();
 
                spillinfo->spills      = spill;
                spillinfo->spill_costs = 0;
@@ -844,17 +835,12 @@ static void determine_spill_costs(spill_env_t *env, spill_info_t *spillinfo)
                spill_t *s;
                double   spills_execfreq;
 
-               /* calculate sum of executaion frequencies of individual spills */
+               /* calculate sum of execution frequencies of individual spills */
                spills_execfreq = 0;
                s               = spillinfo->spills;
                for( ; s != NULL; s = s->next) {
-                       ir_node *spill_block = s->before;
-                       double   freq;
-
-                       if(!is_Block(spill_block)) {
-                               spill_block = get_nodes_block(spill_block);
-                       }
-                       freq = get_block_execfreq(env->exec_freq, spill_block);
+                       ir_node *spill_block = get_block(s->after);
+                       double   freq = get_block_execfreq(env->exec_freq, spill_block);
 
                        spills_execfreq += freq;
                }
@@ -872,10 +858,10 @@ static void determine_spill_costs(spill_env_t *env, spill_info_t *spillinfo)
        }
 
        /* override spillinfos or create a new one */
-       spill         = obstack_alloc(&env->obst, sizeof(spill[0]));
-       spill->before = skip_keeps_phis(to_spill);
-       spill->next   = NULL;
-       spill->spill  = NULL;
+       spill        = obstack_alloc(&env->obst, sizeof(spill[0]));
+       spill->after = skip_keeps_phis(to_spill);
+       spill->next  = NULL;
+       spill->spill = NULL;
 
        spillinfo->spills      = spill;
        spillinfo->spill_costs = spill_execfreq * env->spill_cost;
@@ -905,7 +891,7 @@ void make_spill_locations_dominate_irn(spill_env_t *env, ir_node *irn)
         * If the bitset is not empty after that, we have reloads that are
         * not dominated by any spill. */
        for (s = si->spills; s != NULL; s = s->next) {
-               ir_node *bl = get_nodes_block(s->before);
+               ir_node *bl = get_nodes_block(s->after);
                int start   = get_Block_dom_tree_pre_num(bl);
                int end     = get_Block_dom_max_subtree_pre_num(bl);
 
@@ -913,13 +899,11 @@ void make_spill_locations_dominate_irn(spill_env_t *env, ir_node *irn)
        }
 
        if (!bitset_is_empty(reloads))
-               be_add_spill(env, si->to_spill, sched_next(si->to_spill));
+               be_add_spill(env, si->to_spill, si->to_spill);
 }
 
 void be_insert_spills_reloads(spill_env_t *env)
 {
-       ir_graph              *irg       = env->irg;
-       const arch_env_t      *arch_env  = env->arch_env;
        const ir_exec_freq    *exec_freq = env->exec_freq;
        spill_info_t          *si;
        ir_nodeset_iterator_t  iter;
@@ -927,8 +911,6 @@ void be_insert_spills_reloads(spill_env_t *env)
 
        BE_TIMER_PUSH(t_ra_spill_apply);
 
-       env->new_nodes_idx = get_irg_last_idx(irg);
-
        /* create all phi-ms first, this is needed so, that phis, hanging on
           spilled phis work correctly */
        foreach_ir_nodeset(&env->mem_phis, node, iter) {
@@ -1024,7 +1006,7 @@ void be_insert_spills_reloads(spill_env_t *env)
                                /* create a reload, use the first spill for now SSA
                                 * reconstruction for memory comes below */
                                assert(si->spills != NULL);
-                               copy = be_reload(arch_env, si->reload_cls, rld->reloader, mode,
+                               copy = be_reload(si->reload_cls, rld->reloader, mode,
                                                 si->spills->spill);
 #ifdef FIRM_STATISTICS
                                env->reload_count++;