reindenting source
[libfirm] / ir / be / bespill.c
index 94c22c9..e003a2d 100644 (file)
@@ -28,7 +28,6 @@
 #include "benode_t.h"
 #include "bechordal_t.h"
 
-#define REMAT
 /* This enables re-computation of values. Current state: Unfinished and buggy. */
 #undef BUGGY_REMAT
 
@@ -233,7 +232,7 @@ static INLINE ir_node *skip_projs(ir_node *node) {
 /**
  * Searchs the schedule backwards until we reach the first use or def of a
  * value or a phi.
- * Returns the node before this node (so that you can do sched_add_before)
+ * Returns the node after this node (so that you can do sched_add_before)
  */
 static ir_node *find_last_use_def(spill_env_t *env, ir_node *block, ir_node *value) {
        ir_node *node, *last;
@@ -251,7 +250,7 @@ static ir_node *find_last_use_def(spill_env_t *env, ir_node *block, ir_node *val
                for(i = 0, arity = get_irn_arity(node); i < arity; ++i) {
                        ir_node *arg = get_irn_n(node, i);
                        if(arg == value) {
-                               return skip_projs(node);
+                               return skip_projs(last);
                        }
                }
                last = node;
@@ -358,8 +357,6 @@ static ir_node *be_spill_node(spill_env_t *senv, ir_node *to_spill) {
        return res;
 }
 
-#ifdef REMAT
-
 #ifdef BUGGY_REMAT
 
 /**
@@ -370,11 +367,11 @@ static ir_node *be_spill_node(spill_env_t *senv, ir_node *to_spill) {
  * @param spilled   the node that was spilled
  * @param reloader  a irn that requires a reload
  */
-static int check_remat_conditions(spill_env_t *senv, ir_node *spill, ir_node *spilled, ir_node *reloader) {
+static int check_remat_conditions(spill_env_t *senv, ir_node *spilled, ir_node *reloader) {
        int pos, max;
 
        /* check for 'normal' spill and general remat condition */
-       if (!be_is_Spill(spill) || !arch_irn_is(senv->chordal_env->birg->main_env->arch_env, spilled, rematerializable))
+       if (!arch_irn_is(senv->chordal_env->birg->main_env->arch_env, spilled, rematerializable))
                return 0;
 
        /* check availability of original arguments */
@@ -432,18 +429,15 @@ is_alive: ;
  * @param spilled   the node that was spilled
  * @param reloader  a irn that requires a reload
  */
-static int check_remat_conditions(spill_env_t *senv, ir_node *spill, ir_node *spilled, ir_node *reloader) {
+static int check_remat_conditions(spill_env_t *senv, ir_node *spilled, ir_node *reloader) {
        const arch_env_t *aenv = senv->chordal_env->birg->main_env->arch_env;
 
        return get_irn_arity(spilled) == 0 &&
-                  be_is_Spill(spill) &&
                   arch_irn_is(aenv, spilled, rematerializable);
 }
 
 #endif /* BUGGY_REMAT */
 
-#endif /* REMAT */
-
 /**
  * Re-materialize a node.
  *
@@ -476,13 +470,11 @@ static ir_node *do_remat(spill_env_t *senv, ir_node *spilled, ir_node *reloader)
        return res;
 }
 
-void be_spill_phi(spill_env_t *env, ir_node *node) {
+static void place_copies_for_phi(spill_env_t *env, ir_node* node) {
        int i, arity;
 
        assert(is_Phi(node));
 
-       pset_insert_ptr(env->mem_phis, node);
-
        /* We have to place copy nodes in the predecessor blocks to temporarily
         * produce new values that get separate spill slots
         */
@@ -508,11 +500,36 @@ void be_spill_phi(spill_env_t *env, ir_node *node) {
        }
 }
 
+void be_place_copies(spill_env_t *env) {
+       ir_node *node;
+
+       foreach_pset(env->mem_phis, node) {
+               place_copies_for_phi(env, node);
+       }
+}
+
+void be_spill_phi(spill_env_t *env, ir_node *node) {
+       spill_ctx_t *spill_ctx;
+
+       assert(is_Phi(node));
+
+       pset_insert_ptr(env->mem_phis, node);
+
+       // remove spill context for this phi (if there was one)
+       spill_ctx = be_get_spill_ctx(env->spill_ctxs, node, node);
+       if(spill_ctx != NULL) {
+               spill_ctx->spill = NULL;
+       }
+}
+
 void be_insert_spills_reloads(spill_env_t *env) {
        const arch_env_t *arch_env = env->chordal_env->birg->main_env->arch_env;
-       ir_node *node;
+       //ir_node *node;
        spill_info_t *si;
 
+#if 0
+       // Matze: This should be pointless as beladies fix_block_borders
+       // should result in the same
        DBG((env->dbg, LEVEL_1, "Reloads for mem-phis:\n"));
        foreach_pset(env->mem_phis, node) {
                const ir_edge_t *e;
@@ -531,6 +548,7 @@ void be_insert_spills_reloads(spill_env_t *env) {
                        }
                }
        }
+#endif
 
        /* process each spilled node */
        DBG((env->dbg, LEVEL_1, "Insert spills and reloads:\n"));
@@ -543,16 +561,15 @@ void be_insert_spills_reloads(spill_env_t *env) {
                for(rld = si->reloaders; rld; rld = rld->next) {
                        ir_node *new_val;
 
-                       /* the spill for this reloader */
-                       ir_node *spill   = be_spill_node(env, si->spilled_node);
-
-#ifdef REMAT
-                       if (check_remat_conditions(env, spill, si->spilled_node, rld->reloader)) {
+                       if (check_remat_conditions(env, si->spilled_node, rld->reloader)) {
                                new_val = do_remat(env, si->spilled_node, rld->reloader);
-                       } else
-#endif
+                       } else {
+                               /* the spill for this reloader */
+                               ir_node *spill = be_spill_node(env, si->spilled_node);
+
                                /* do a reload */
                                new_val = be_reload(arch_env, env->cls, rld->reloader, mode, spill);
+                       }
 
                        DBG((env->dbg, LEVEL_1, " %+F of %+F before %+F\n", new_val, si->spilled_node, rld->reloader));
                        pset_insert_ptr(values, new_val);
@@ -561,7 +578,7 @@ void be_insert_spills_reloads(spill_env_t *env) {
                /* introduce copies, rewire the uses */
                assert(pset_count(values) > 0 && "???");
                pset_insert_ptr(values, si->spilled_node);
-               be_ssa_constr_set_ignore(env->chordal_env->dom_front, values, env->mem_phis);
+               be_ssa_constr_set_ignore(env->chordal_env->dom_front, env->chordal_env->lv, values, env->mem_phis);
 
                del_pset(values);
        }
@@ -588,6 +605,8 @@ void be_add_reload(spill_env_t *env, ir_node *to_spill, ir_node *before) {
        rel->reloader = before;
        rel->next     = res->reloaders;
        res->reloaders = rel;
+
+       be_liveness_add_missing(env->chordal_env->lv);
 }
 
 void be_add_reload_on_edge(spill_env_t *env, ir_node *to_spill, ir_node *block, int pos) {
@@ -643,21 +662,26 @@ typedef struct _ss_env_t {
  * Walker: compute the spill slots
  */
 static void compute_spill_slots_walker(ir_node *spill, void *env) {
-       ss_env_t *ssenv = env;
-       ir_node *ctx;
-       pmap_entry *entry;
+       ss_env_t     *ssenv    = env;
+       arch_env_t   *arch_env = ssenv->cenv->birg->main_env->arch_env;
+       ir_node      *ctx;
+       pmap_entry   *entry;
        spill_slot_t *ss;
+       const arch_register_class_t *cls;
+
+       if (! be_is_Spill(spill))
+               return;
+
+       cls = arch_get_irn_reg_class(arch_env, spill, be_pos_Spill_val);
 
-       if (!be_is_Spill(spill))
+       if (cls != ssenv->cenv->cls)
                return;
 
        /* check, if this spill is for a context already known */
-       ctx = be_get_Spill_context(spill);
+       ctx   = be_get_Spill_context(spill);
        entry = pmap_find(ssenv->slots, ctx);
 
-       if (!entry) {
-               struct _arch_env_t *arch_env     = ssenv->cenv->birg->main_env->arch_env;
-               const arch_register_class_t *cls = arch_get_irn_reg_class(arch_env, spill, be_pos_Spill_val);
+       if (! entry) {
                ir_mode *largest_mode            = arch_register_class_mode(cls);
 
                /* this is a new spill context */
@@ -682,7 +706,7 @@ static void compute_spill_slots_walker(ir_node *spill, void *env) {
                        for (irn = pset_first(ss->members); irn; irn = pset_next(ss->members)) {
                                /* use values_interfere here, because it uses the dominance check,
                                         which does work for values in memory */
-                               assert(!values_interfere(spill, irn) && "Spills for the same spill slot must not interfere!");
+                               assert(!values_interfere(ssenv->cenv->lv, spill, irn) && "Spills for the same spill slot must not interfere!");
                        }
                }
 #endif /* NDEBUG */
@@ -728,7 +752,8 @@ static void optimize_slots(ss_env_t *ssenv, int size, spill_slot_t *ass[]) {
                - assign a new offset to this slot
            - xor find another slot to coalesce with */
        used_slots = 0;
-       for (i=0; i<size; ++i) { /* for each spill slot */
+       for (i=0; i<size; ++i) {
+               /* for each spill slot */
                ir_node *n1;
                int tgt_slot = -1;
 
@@ -742,7 +767,7 @@ static void optimize_slots(ss_env_t *ssenv, int size, spill_slot_t *ass[]) {
                        ir_node *n2;
                        for(n1 = pset_first(ass[i]->members); n1; n1 = pset_next(ass[i]->members))
                                for(n2 = pset_first(ass[o]->members); n2; n2 = pset_next(ass[o]->members))
-                                       if(values_interfere(n1, n2)) {
+                                       if(values_interfere(ssenv->cenv->lv, n1, n2)) {
                                                pset_break(ass[i]->members);
                                                pset_break(ass[o]->members);
                                                DBG((ssenv->dbg, LEVEL_1, "    Interf %+F -- %+F\n", n1, n2));
@@ -873,7 +898,7 @@ void be_compute_spill_offsets(be_chordal_env_t *cenv) {
        ssenv.cenv  = cenv;
        ssenv.slots = pmap_create();
        ssenv.types = pmap_create();
-       FIRM_DBG_REGISTER(ssenv.dbg, "ir.be.spillslots");
+       FIRM_DBG_REGISTER(ssenv.dbg, "firm.be.spillslots");
 
        /* Get initial spill slots */
        irg_walk_graph(cenv->irg, NULL, compute_spill_slots_walker, &ssenv);