* Added a new file: beintlive_t.h which subsumes all interferene/liveness checks
authorSebastian Hack <hack@ipd.info.uni-karlsruhe.de>
Thu, 10 May 2007 15:43:44 +0000 (15:43 +0000)
committerSebastian Hack <hack@ipd.info.uni-karlsruhe.de>
Thu, 10 May 2007 15:43:44 +0000 (15:43 +0000)
  - it uses the new liveness checking algos in ana/irlivechk.h
  - value_dominates, etc. was erased from bera.h because it does not belong there

* bechordal.c features an experimental coloring (by defualt disabled by macro)
  which can color the routine in a single pass without building the "borders".
  A long term goal is to disable borders completely but they are used in other
  places, too.

* The 1st parameter of values_interfere is now a birg and not a be_lv_t. There
  is now a special routine lv_values_interfere() for those who want to use the
  computed liveness explicitly. changing the parameter makes it more easy to
  switch to other liveness implementations.

All other files were modified to respect the changes

[r13762]

21 files changed:
ir/be/bechordal.c
ir/be/becopyheur.c
ir/be/becopyopt.c
ir/be/becopystat.c
ir/be/beifg_clique.c
ir/be/beifg_std.c
ir/be/beintlive_t.h [new file with mode: 0644]
ir/be/beirg.c
ir/be/beirg.h
ir/be/beirg_t.h
ir/be/belive.c
ir/be/belive.h
ir/be/bemain.c
ir/be/bera.c
ir/be/bera.h
ir/be/bespill.c
ir/be/bespillremat.c
ir/be/bespillslots.c
ir/be/bessaconstr.c
ir/be/bessadestr.c
ir/be/beverify.c

index 7f2c2ee..2000c28 100644 (file)
@@ -46,6 +46,7 @@
 #include "irdump.h"
 #include "irdom.h"
 #include "irtools.h"
+#include "irbitset.h"
 #include "debug.h"
 #include "xmalloc.h"
 #include "iredges.h"
@@ -61,6 +62,7 @@
 #include "beinsn_t.h"
 #include "bestatevent.h"
 #include "beirg_t.h"
+#include "beintlive_t.h"
 #include "bera.h"
 #include "bechordal_t.h"
 #include "bechordal_draw.h"
@@ -72,6 +74,9 @@ DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 
 #define DUMP_INTERVALS
 
+/* new style assign routine without borders. */
+#undef NEW_STYLE_ASSIGN
+
 typedef struct _be_chordal_alloc_env_t {
        be_chordal_env_t *chordal_env;
 
@@ -178,8 +183,7 @@ static INLINE border_t *border_add(be_chordal_env_t *env, struct list_head *head
  */
 static INLINE int has_reg_class(const be_chordal_env_t *env, const ir_node *irn)
 {
-       return arch_irn_has_reg_class(env->birg->main_env->arch_env, irn, -1, env->cls);
-       // return arch_irn_consider_in_reg_alloc(env->birg->main_env->arch_env, env->cls, irn);
+       return arch_irn_consider_in_reg_alloc(env->birg->main_env->arch_env, env->cls, irn);
 }
 
 #define has_limited_constr(req, irn) \
@@ -232,7 +236,8 @@ static be_insn_t *chordal_scan_insn(be_chordal_env_t *env, ir_node *irn)
 
 static ir_node *prepare_constr_insn(be_chordal_env_t *env, ir_node *irn)
 {
-       const arch_env_t *aenv = env->birg->main_env->arch_env;
+       const be_irg_t *birg   = env->birg;
+       const arch_env_t *aenv = birg->main_env->arch_env;
        bitset_t *tmp          = bitset_alloca(env->cls->n_regs);
        bitset_t *def_constr   = bitset_alloca(env->cls->n_regs);
        ir_node *bl            = get_nodes_block(irn);
@@ -325,7 +330,7 @@ static ir_node *prepare_constr_insn(be_chordal_env_t *env, ir_node *irn)
                        3) is constrained to a register occuring in out constraints.
                */
                if(!op->has_constraints ||
-                               !values_interfere(lv, insn->irn, op->carrier) ||
+                               !values_interfere(birg, insn->irn, op->carrier) ||
                                bitset_popcnt(tmp) == 0)
                        continue;
 
@@ -372,7 +377,6 @@ static void pair_up_operands(const be_chordal_alloc_env_t *alloc_env, be_insn_t
        int n_defs   = be_insn_n_defs(insn);
        bitset_t *bs = bitset_alloca(env->cls->n_regs);
        int *pairing = alloca(MAX(n_defs, n_uses) * sizeof(pairing[0]));
-       be_lv_t *lv  = env->birg->lv;
 
        int i, j;
 
@@ -392,7 +396,7 @@ static void pair_up_operands(const be_chordal_alloc_env_t *alloc_env, be_insn_t
 
                        if (op->partner != NULL)
                                continue;
-                       if (values_interfere(lv, op->irn, op->carrier))
+                       if (values_interfere(env->birg, op->irn, op->carrier))
                                continue;
 
                        bitset_clear_all(bs);
@@ -503,7 +507,7 @@ static ir_node *handle_constraints(be_chordal_alloc_env_t *alloc_env, ir_node *i
        be_insn_t *insn        = chordal_scan_insn(env, irn);
        ir_node *res           = insn->next_insn;
        int be_silent          = *silent;
-       be_lv_t *lv            = env->birg->lv;
+       be_irg_t *birg         = env->birg;
 
        if(insn->pre_colored) {
                int i;
@@ -594,7 +598,7 @@ static ir_node *handle_constraints(be_chordal_alloc_env_t *alloc_env, ir_node *i
 
                        assert(is_Proj(proj));
 
-                       if(!values_interfere(lv, proj, irn) || pmap_contains(partners, proj))
+                       if(!values_interfere(birg, proj, irn) || pmap_contains(partners, proj))
                                continue;
 
                        assert(n_alloc < n_regs);
@@ -932,6 +936,129 @@ static void assign(ir_node *block, void *env_ptr)
        del_pset(live_in);
 }
 
+/**
+ * A new assign...
+ */
+static void assign_new(ir_node *block, be_chordal_alloc_env_t *alloc_env, bitset_t *live_end_dom)
+{
+       be_chordal_env_t *env      = alloc_env->chordal_env;
+       bitset_t *colors           = alloc_env->colors;
+       bitset_t *in_colors        = alloc_env->in_colors;
+       bitset_t *live             = bitset_irg_malloc(env->irg);
+       const arch_env_t *arch_env = env->birg->main_env->arch_env;
+       be_irg_t *birg             = env->birg;
+       lv_chk_t *lv               = be_get_birg_liveness_chk(birg);
+
+       bitset_pos_t elm;
+       ir_node *irn;
+
+       bitset_clear_all(colors);
+       bitset_clear_all(in_colors);
+
+       /*
+        * All variables which are live in to this block are live out
+        * of the immediate dominator thanks to SSA properties. As we
+        * have already visited the immediate dominator, we know these
+        * variables. The only tjing left is to check wheather they are live
+        * in here (they also could be phi arguments to some ohi not
+        * in this block, hence we have to check).
+        */
+       bitset_foreach (live_end_dom, elm) {
+               ir_node *irn = get_idx_irn(env->irg, elm);
+               if (lv_chk_bl_in(lv, block, irn)) {
+                       const arch_register_t *reg = arch_get_irn_register(arch_env, irn);
+                       int col;
+
+                       assert(be_is_live_in(env->birg->lv, block, irn));
+                       assert(reg && "Node must have been assigned a register");
+                       col = arch_register_get_index(reg);
+
+                       DBG((dbg, LEVEL_4, "%+F has reg %s\n", irn, reg->name));
+
+                       /* Mark the color of the live in value as used. */
+                       bitset_set(colors, col);
+                       bitset_set(in_colors, col);
+
+                       /* Mark the value live in. */
+                       bitset_set(live, elm);
+               }
+
+               else {
+                       assert(!be_is_live_in(env->birg->lv, block, irn));
+               }
+       }
+
+       /*
+        * Mind that the sequence of defs from back to front defines a perfect
+        * elimination order. So, coloring the definitions from first to last
+        * will work.
+        */
+       sched_foreach (block, irn) {
+               int nr       = get_irn_idx(irn);
+               int ignore   = arch_irn_is(arch_env, irn, ignore);
+
+               /* Clear the color upon a last use. */
+               if(!is_Phi(irn)) {
+                       int i;
+                       for (i = get_irn_arity(irn) - 1; i >= 0; --i) {
+                               ir_node *op = get_irn_n(irn, i);
+
+                               /*
+                                * If the reg class matches and the operand is not live after
+                                * the node, irn is a last use of op and the register can
+                                * be freed.
+                                */
+                               if (has_reg_class(env, op)) {
+                                       if (!be_lv_chk_after_irn(birg, op, irn)) {
+                                               const arch_register_t *reg = arch_get_irn_register(arch_env, op);
+                                               int col;
+
+                                               assert(reg && "Register must have been assigned");
+                                               col = arch_register_get_index(reg);
+                                               bitset_clear(colors, col);
+                                               bitset_clear(live, nr);
+                                       }
+                               }
+                       }
+               }
+
+               if (has_reg_class(env, irn)) {
+                       const arch_register_t *reg;
+                       int col = NO_COLOR;
+
+                       /*
+                        * Assign a color, if it is a local def. Global defs already have a
+                        * color.
+                        */
+                       if(ignore || pset_find_ptr(alloc_env->pre_colored, irn)) {
+                               reg = arch_get_irn_register(arch_env, irn);
+                               col = reg->index;
+                               assert(!bitset_is_set(colors, col) && "pre-colored register must be free");
+                       } else {
+                               col = get_next_free_reg(alloc_env, colors);
+                               reg = arch_register_for_index(env->cls, col);
+                               assert(arch_get_irn_register(arch_env, irn) == NULL && "This node must not have been assigned a register yet");
+                               assert(!arch_register_type_is(reg, ignore) && "Must not assign ignore register");
+                       }
+
+                       bitset_set(colors, col);
+                       arch_set_irn_register(arch_env, irn, reg);
+
+                       DBG((dbg, LEVEL_1, "\tassigning register %s(%d) to %+F\n", arch_register_get_name(reg), col, irn));
+
+                       assert(!bitset_is_set(live, nr) && "Value's definition must not have been encountered");
+                       bitset_set(live, nr);
+               }
+
+       }
+
+       dominates_for_each (block, irn) {
+               assign_new(irn, alloc_env, live);
+       }
+
+       bitset_free(live);
+}
+
 void be_ra_chordal_color(be_chordal_env_t *chordal_env)
 {
        be_chordal_alloc_env_t env;
@@ -972,7 +1099,11 @@ void be_ra_chordal_color(be_chordal_env_t *chordal_env)
        dom_tree_walk_irg(irg, pressure, NULL, &env);
 
        /* Assign the colors */
+#ifdef NEW_STYLE_ASSIGN
+       assign_new(get_irg_start_block(irg), &env, env.live);
+#else
        dom_tree_walk_irg(irg, assign, NULL, &env);
+#endif
 
        if(chordal_env->opts->dump_flags & BE_CH_DUMP_TREE_INTV) {
                plotter_t *plotter;
@@ -988,7 +1119,7 @@ void be_ra_chordal_color(be_chordal_env_t *chordal_env)
 
 void be_init_chordal(void)
 {
-       FIRM_DBG_REGISTER(dbg, "firm.be.chordal.constr");
+       FIRM_DBG_REGISTER(dbg, "firm.be.chordal");
 }
 
 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_chordal);
index 1afb062..af9fd5e 100644 (file)
@@ -44,7 +44,7 @@
 #include "becopyopt_t.h"
 #include "becopystat.h"
 #include "benodesets.h"
-#include "bera.h"
+#include "beintlive_t.h"
 #include "beirg_t.h"
 
 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
@@ -96,7 +96,7 @@ static INLINE int nodes_interfere(const be_chordal_env_t *env, const ir_node *a,
        if (env->ifg)
                return be_ifg_connected(env->ifg, a, b);
        else
-               return values_interfere(env->birg->lv, a, b);
+               return values_interfere(env->birg, a, b);
 }
 
 static int set_cmp_conflict_t(const void *x, const void *y, size_t size) {
index 76031dc..b27d36b 100644 (file)
@@ -54,6 +54,7 @@
 #include "benode_t.h"
 #include "beutil.h"
 #include "beifg_t.h"
+#include "beintlive_t.h"
 #include "becopyopt_t.h"
 #include "becopystat.h"
 #include "belive_t.h"
@@ -64,7 +65,6 @@
 #include "bestatevent.h"
 #include "beirg_t.h"
 #include "error.h"
-#include "bera.h"
 
 #include <libcore/lc_timing.h>
 #include <libcore/lc_opts.h>
@@ -176,7 +176,7 @@ static int nodes_interfere(const be_chordal_env_t *env, const ir_node *a, const
        if (env->ifg)
                return be_ifg_connected(env->ifg, a, b);
        else
-               return values_interfere(env->birg->lv, a, b);
+               return values_interfere(env->birg, a, b);
 }
 
 
index f63541e..4790b57 100644 (file)
@@ -45,7 +45,7 @@
 #include "becopystat.h"
 #include "beirg_t.h"
 #include "bemodule.h"
-#include "bera.h"
+#include "beintlive_t.h"
 
 #define DEBUG_LVL SET_LEVEL_1
 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
@@ -239,10 +239,9 @@ static void stat_phi_node(be_chordal_env_t *chordal_env, ir_node *phi) {
  * Collect register-constrained node data
  */
 static void stat_copy_node(be_chordal_env_t *chordal_env, ir_node *root) {
-       be_lv_t *lv = be_get_birg_liveness(chordal_env->birg);
        curr_vals[I_CPY_CNT]++;
        curr_vals[I_COPIES_MAX]++;
-       if (values_interfere(lv, root, get_Perm_src(root))) {
+       if (values_interfere(chordal_env->birg, root, get_Perm_src(root))) {
                curr_vals[I_COPIES_IF]++;
                assert(0 && "A Perm pair (in/out) should never interfere!");
        }
@@ -253,7 +252,6 @@ static void stat_copy_node(be_chordal_env_t *chordal_env, ir_node *root) {
  */
 static void stat_phi_class(be_chordal_env_t *chordal_env, ir_node **pc) {
        int i, o, size, if_free, phis;
-       be_lv_t *lv = be_get_birg_liveness(chordal_env->birg);
 
        /* phi class count */
        curr_vals[I_CLS_CNT]++;
@@ -279,7 +277,7 @@ static void stat_phi_class(be_chordal_env_t *chordal_env, ir_node **pc) {
        curr_vals[I_CLS_IF_MAX] += size * (size - 1) / 2;
        for (if_free = 1, i = 0; i < size - 1; ++i)
                for (o = i + 1; o < size; ++o)
-                       if (values_interfere(lv, pc[i], pc[o])) {
+                       if (values_interfere(chordal_env->birg, pc[i], pc[o])) {
                                if_free = 0;
                                curr_vals[I_CLS_IF_CNT]++;
                        }
index 694db7a..5a3eaf7 100644 (file)
@@ -40,7 +40,7 @@
 
 #include "bearch_t.h"
 #include "be_t.h"
-#include "bera.h"
+#include "beintlive_t.h"
 #include "beifg_t.h"
 #include "bechordal_t.h"
 #include "benodesets.h"
index b139f19..6c5e535 100644 (file)
@@ -45,7 +45,7 @@
 #include "beifg_t.h"
 #include "bechordal_t.h"
 #include "beirg_t.h"
-#include "bera.h"
+#include "beintlive_t.h"
 
 typedef struct _ifg_std_t ifg_std_t;
 
@@ -62,8 +62,7 @@ static void ifg_std_free(void *self)
 static int ifg_std_connected(const void *self, const ir_node *a, const ir_node *b)
 {
        const ifg_std_t *ifg = self;
-       be_lv_t         *lv  = ifg->env->birg->lv;
-       return values_interfere(lv, a, b);
+       return values_interfere(ifg->env->birg, a, b);
 }
 
 typedef struct _nodes_iter_t {
diff --git a/ir/be/beintlive_t.h b/ir/be/beintlive_t.h
new file mode 100644 (file)
index 0000000..659f5de
--- /dev/null
@@ -0,0 +1,251 @@
+/**
+ * @file   beintlive_t.h
+ * @date   10.05.2007
+ * @author Sebastian Hack
+ *
+ * Principal routines for liveness and interference checks.
+ *
+ * Copyright (C) 2007 Universitaet Karlsruhe
+ * Released under the GPL
+ */
+
+#ifndef _BELIVECHK_T_H
+#define _BELIVECHK_T_H
+
+#include "irgraph_t.h"
+#include "irphase_t.h"
+#include "iredges_t.h"
+
+#include "irlivechk.h"
+
+#include "beirg_t.h"
+#include "besched_t.h"
+
+/**
+ * Check dominance of two nodes in the same block.
+ * @param a The first node.
+ * @param b The second node.
+ * @return 1 if a comes before b in the same block or if a == b, 0 else.
+ */
+static INLINE int _value_dominates_intrablock(const ir_node *a, const ir_node *b)
+{
+       /* TODO: ? :  can be removed?! */
+       sched_timestep_t as = is_Phi(a) ? 0 : sched_get_time_step(a);
+       sched_timestep_t bs = is_Phi(b) ? 0 : sched_get_time_step(b);
+       return as <= bs;
+}
+
+/**
+ * Check, if one value dominates the other.
+ * The dominance is not strict here.
+ * @param a The first node.
+ * @param b The second node.
+ * @return 1 if a dominates b or if a == b, 0 else.
+ */
+static INLINE int _value_dominates(const ir_node *a, const ir_node *b)
+{
+       const ir_node *block_a = get_block(a);
+       const ir_node *block_b = get_block(b);
+
+       /*
+        * a and b are not in the same block,
+        * so dominance is determined by the dominance of the blocks.
+        */
+       if(block_a != block_b) {
+               return block_dominates(block_a, block_b);
+       }
+
+       /*
+        * Dominance is determined by the time steps of the schedule.
+        */
+       return _value_dominates_intrablock(a, b);
+}
+
+/**
+ * Check, if two values interfere.
+ * @param lv Liveness information (in the future we should use a be_irg_t here).
+ * @param a The first value.
+ * @param b The second value.
+ * @return 1, if a and b interfere, 0 if not.
+ */
+static INLINE int _lv_values_interfere(const be_lv_t *lv, const ir_node *a, const ir_node *b)
+{
+       int a2b = _value_dominates(a, b);
+       int b2a = _value_dominates(b, a);
+
+       /* If there is no dominance relation, they do not interfere. */
+       if((a2b | b2a) > 0) {
+               const ir_edge_t *edge;
+               ir_node *bb;
+
+               /*
+                * Adjust a and b so, that a dominates b if
+                * a dominates b or vice versa.
+                */
+               if(b2a) {
+                       const ir_node *t = a;
+                       a = b;
+                       b = t;
+               }
+
+               bb = get_nodes_block(b);
+
+               /*
+                * If a is live end in b's block it is
+                * live at b's definition (a dominates b)
+                */
+               if(be_is_live_end(lv, bb, a))
+                       return 1;
+
+               /*
+                * Look at all usages of a.
+                * If there's one usage of a in the block of b, then
+                * we check, if this use is dominated by b, if that's true
+                * a and b interfere. Note that b must strictly dominate the user,
+                * since if b is the last user of in the block, b and a do not
+                * interfere.
+                * Uses of a not in b's block can be disobeyed, because the
+                * check for a being live at the end of b's block is already
+                * performed.
+                */
+               foreach_out_edge(a, edge) {
+                       const ir_node *user = get_edge_src_irn(edge);
+                       if(get_nodes_block(user) == bb && !is_Phi(user) && b != user && _value_dominates(b, user))
+                               return 1;
+               }
+       }
+
+       return 0;
+}
+
+
+
+/**
+ * Check if a node dominates a use.
+ * Note that the use of a phi is in its corresponding predecessor.
+ * @param irn  The node.
+ * @param edge The use.
+ * @return     1, if @p irn dominates the use @p edge.
+ */
+static INLINE int _dominates_use(const ir_node *irn, const ir_edge_t *edge)
+{
+       ir_node *use = get_edge_src_irn(edge);
+
+       if (is_Phi(use)) {
+               int pos         = get_edge_src_pos(edge);
+               ir_node *phi_bl = get_nodes_block(use);
+               ir_node *use_bl = get_Block_cfgpred_block(phi_bl, pos);
+               ir_node *irn_bl = get_nodes_block(irn);
+               return block_dominates(irn_bl, use_bl);
+       }
+
+       return _value_dominates(irn, use);
+}
+
+/**
+ * Check if a node strictly dominates a use.
+ * Note that the use of a phi is in its corresponding predecessor.
+ * @param irn  The node.
+ * @param edge The use.
+ * @return     1, if @p irn strictly dominates the use @p edge.
+ */
+static INLINE int _strictly_dominates_use(const ir_node *irn, const ir_edge_t *edge)
+{
+       return get_edge_src_irn(edge) != irn && _dominates_use(irn, edge);
+}
+
+/**
+ * Check, if a node is live in front of another.
+ * @param birg  The backend irg.
+ * @param irn   The node.
+ * @param where The location to check for.
+ * @return      1, if @p irn is live in front of @p where.
+ */
+static INLINE int _be_lv_chk_before_irn(const be_irg_t *birg, const ir_node *irn, const ir_node *where)
+{
+       const lv_chk_t *lv = be_get_birg_liveness_chk(birg);
+       const ir_edge_t *edge;
+
+       /* the node must strictly dominate the location, else it cannot be live there. */
+       if (!_value_dominates(irn, where) || irn == where)
+               return 0;
+
+       /*
+        * now that it is clear that it strictly dominates the location it is surely live
+        * if it is also live end at the block.
+        */
+       if (lv_chk_bl_end(lv, get_nodes_block(where), irn))
+               return 1;
+
+       /*
+        * If the node is not live out, we have to check if there
+        * is a use which is dominated by the location.
+        */
+       foreach_out_edge (irn, edge) {
+               if (_dominates_use(where, edge))
+                       return 1;
+       }
+
+       return 0;
+}
+
+/**
+ * Check, if a node is live after another node.
+ * @param birg  The backend irg.
+ * @param irn   The node.
+ * @param where The location to check for.
+ * @return      1, if @p irn is live after @p where.
+ */
+static INLINE int _be_lv_chk_after_irn(const be_irg_t *birg, const ir_node *irn, const ir_node *where)
+{
+       const lv_chk_t *lv = be_get_birg_liveness_chk(birg);
+       const ir_edge_t *edge;
+
+       if (!_value_dominates(irn, where))
+               return 0;
+
+       if (lv_chk_bl_end(lv, get_nodes_block(where), irn))
+               return 1;
+
+       foreach_out_edge (irn, edge) {
+               if (_strictly_dominates_use(where, edge))
+                       return 1;
+       }
+
+       return 0;
+}
+
+/**
+ * Check, if two nodes interfere.
+ * This will become the favored rotine to call but it is not used yet.
+ * @param birg   The backend irg.
+ * @param a      The first node.
+ * @param b      The second node.
+ * @return       1, if a and b interfere, 0 if not.
+ */
+static INLINE int _be_lv_chk_values_interfere(const be_irg_t *birg, const ir_node *a, const ir_node *b)
+{
+       int adb = _value_dominates(a, b);
+       int bda = _value_dominates(b, a);
+
+       if (bda) {
+               const ir_node *t = a;
+               a = b;
+               b = t;
+               adb = 1;
+       }
+
+       return adb && _be_lv_chk_after_irn(birg, a, b);
+}
+
+#define value_dominates_intrablock(a, b)         _value_dominates_intrablock(a, b)
+#define value_dominates(a, b)                    _value_dominates(a, b)
+#define lv_values_interfere(lv, a, b)            _lv_values_interfere(lv, a, b)
+#define values_interfere(birg, a, b)             _lv_values_interfere(be_get_birg_liveness(birg), a, b)
+#define dominates_use(a, e)                      _dominates_use(a, e)
+#define strictly_dominates_use(a, e)             _strictly_dominates_use(a, e)
+#define be_lv_chk_before_irn(birg, a, b)         _be_lv_chk_before_irn(birg, a, b)
+#define be_lv_chk_after_irn(birg, a, b)          _be_lv_chk_after_irn(birg, a, b)
+#define be_lv_chk_values_interfere(birg, a, b)   _be_lv_chk_values_interfere(birg, a, b)
+
+#endif /* _BELIVECHK_T_H */
index c9cd719..9579177 100644 (file)
 #include "execfreq.h"
 #include "beirg_t.h"
 
+void be_assure_liveness_chk(be_irg_t *birg)
+{
+       if (birg->lv_chk != NULL)
+               return;
+
+       birg->lv_chk = lv_chk_new(birg->irg);
+}
+
 void be_assure_liveness(be_irg_t *birg)
 {
        if (birg->lv != NULL)
@@ -95,6 +103,11 @@ be_lv_t *(be_get_birg_liveness)(const be_irg_t *birg)
        return _be_get_birg_liveness(birg);
 }
 
+lv_chk_t *(be_get_birg_liveness_chk)(const be_irg_t *birg)
+{
+       return _be_get_birg_liveness_chk(birg);
+}
+
 be_dom_front_info_t *(be_get_birg_dom_front)(const be_irg_t *birg)
 {
        return _be_get_birg_dom_front(birg);
index b9813f0..647480a 100644 (file)
@@ -35,6 +35,7 @@ typedef struct be_irg_t be_irg_t;
 ir_graph *be_get_birg_irg(const be_irg_t *birg);
 
 void be_assure_liveness(be_irg_t *birg);
+void be_assure_liveness_chk(be_irg_t *birg);
 void be_invalidate_liveness(be_irg_t *birg);
 be_lv_t *be_get_birg_liveness(const be_irg_t *birg);
 
@@ -52,4 +53,11 @@ ir_exec_freq *be_get_birg_exec_freq(const be_irg_t *birg);
  */
 void be_free_birg(be_irg_t *birg);
 
+/**
+ * Compare the computed liveness information with the liveness check info.
+ * @param lv    The computed liveness.
+ * @param lvc   The liveness check information.
+ */
+void be_live_chk_compare(be_irg_t *birg);
+
 #endif /* FIRM_BE_BEIRG_H */
index 2f6cbbf..babc5ae 100644 (file)
@@ -29,6 +29,7 @@
 
 #include "beirg.h"
 #include "be_t.h"
+#include "irlivechk.h"
 
 /**
  * An ir_graph with additional analysis data about this irg. Also includes some
@@ -42,6 +43,7 @@ struct be_irg_t {
        ir_exec_freq           *exec_freq;
        be_dom_front_info_t    *dom_front;
        be_lv_t                *lv;
+       lv_chk_t               *lv_chk;
 };
 
 static INLINE be_lv_t *
@@ -49,6 +51,11 @@ _be_get_birg_liveness(const be_irg_t *birg) {
        return birg->lv;
 }
 
+static INLINE lv_chk_t *
+_be_get_birg_liveness_chk(const be_irg_t *birg) {
+       return birg->lv_chk;
+}
+
 static INLINE ir_exec_freq *
 _be_get_birg_exec_freq(const be_irg_t *birg) {
        return birg->exec_freq;
@@ -71,6 +78,7 @@ _be_get_birg_arch_env(const be_irg_t *birg) {
 
 #define be_get_birg_exec_freq(birg)        _be_get_birg_exec_freq(birg)
 #define be_get_birg_liveness(birg)         _be_get_birg_liveness(birg)
+#define be_get_birg_liveness_chk(birg)     _be_get_birg_liveness_chk(birg)
 #define be_get_birg_dom_front(birg)        _be_get_birg_dom_front(birg)
 #define be_get_birg_irg(birg)              _be_get_birg_irg(birg)
 
index f422869..273a64c 100644 (file)
@@ -37,6 +37,7 @@
 
 #include "beutil.h"
 #include "belive_t.h"
+#include "beirg_t.h"
 #include "besched_t.h"
 #include "bemodule.h"
 
@@ -764,6 +765,68 @@ pset *be_liveness_nodes_live_at_input(const be_lv_t *lv, const arch_env_t *arch_
        return live;
 }
 
+static void collect_node(ir_node *irn, void *data)
+{
+       struct obstack *obst = data;
+       obstack_ptr_grow(obst, irn);
+}
+
+void be_live_chk_compare(be_irg_t *birg)
+{
+       ir_graph *irg    = be_get_birg_irg(birg);
+
+       struct obstack obst;
+       ir_node **nodes;
+       ir_node **blocks;
+       be_lv_t *lv;
+       lv_chk_t *lvc;
+       int i, j;
+
+       be_assure_liveness(birg);
+       be_assure_liveness_chk(birg);
+       lv  = be_get_birg_liveness(birg);
+       lvc = be_get_birg_liveness_chk(birg);
+
+       obstack_init(&obst);
+
+       irg_block_walk_graph(irg, collect_node, NULL, &obst);
+       obstack_ptr_grow(&obst, NULL);
+       blocks = obstack_finish(&obst);
+
+       irg_walk_graph(irg, collect_node, NULL, &obst);
+       obstack_ptr_grow(&obst, NULL);
+       nodes = obstack_finish(&obst);
+
+       for (i = 0; blocks[i]; ++i) {
+               ir_node *bl = blocks[i];
+
+               for (j = 0; nodes[j]; ++j) {
+                       ir_node *irn = nodes[j];
+                       if (!is_Block(irn)) {
+                               int lvr_in  = be_is_live_in (lv, bl, irn);
+                               int lvr_out = be_is_live_out(lv, bl, irn);
+                               int lvr_end = be_is_live_end(lv, bl, irn);
+
+                               int lvc_in  = lv_chk_bl_in (lvc, bl, irn);
+                               int lvc_out = lv_chk_bl_out(lvc, bl, irn);
+                               int lvc_end = lv_chk_bl_end(lvc, bl, irn);
+
+                               if (lvr_in - lvc_in != 0)
+                                       ir_fprintf(stderr, "live in  info for %+F at %+F differs: nml: %d, chk: %d\n", irn, bl, lvr_in, lvc_in);
+
+                               if (lvr_end - lvc_end != 0)
+                                       ir_fprintf(stderr, "live end info for %+F at %+F differs: nml: %d, chk: %d\n", irn, bl, lvr_end, lvc_end);
+
+                               if (lvr_out - lvc_out != 0)
+                                       ir_fprintf(stderr, "live out info for %+F at %+F differs: nml: %d, chk: %d\n", irn, bl, lvr_out, lvc_out);
+                       }
+               }
+       }
+
+
+       obstack_free(&obst, NULL);
+}
+
 void be_init_live(void)
 {
        FIRM_DBG_REGISTER(dbg, "firm.be.liveness");
index 39f0a7f..f3e1e2d 100644 (file)
@@ -32,6 +32,7 @@
 #include "firm_types.h"
 #include "pset.h"
 
+#include "irlivechk.h"
 #include "bearch.h"
 
 typedef enum {
@@ -186,4 +187,5 @@ pset *be_liveness_nodes_live_at(const be_lv_t *lv, const arch_env_t *arch_env, c
  */
 pset *be_liveness_nodes_live_at_input(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *pos, pset *live);
 
+
 #endif /* FIRM_BE_BELIVE_H */
index 6c0343c..874fc92 100644 (file)
@@ -532,11 +532,12 @@ static void be_main_loop(FILE *file_handle, const char *cup_name)
                /**
                 * Create execution frequencies from profile data or estimate some
                 */
-               if (be_profile_has_data()) {
+               if (be_profile_has_data())
                        birg->exec_freq = be_create_execfreqs_from_profile(irg);
-               } else {
+               else
                        birg->exec_freq = compute_execfreq(irg, 10);
-               }
+
+               be_live_chk_compare(birg);
 
                /* let backend prepare scheduling */
                BE_TIMER_PUSH(t_codegen);
index b776366..b673bef 100644 (file)
 
 be_ra_timer_t *global_ra_timer = NULL;
 
-#define get_time_step(irn) (is_Phi(irn) ? 0 : sched_get_time_step(irn))
-
-static INLINE int _value_dominates_intrablock(const ir_node *a, const ir_node *b)
-{
-       sched_timestep_t as = get_time_step(a);
-       sched_timestep_t bs = get_time_step(b);
-       return as <= bs;
-}
-
-int value_dominates_intrablock(const ir_node *a, const ir_node *b)
-{
-       return _value_dominates_intrablock(a, b);
-}
-
-int value_dominates(const ir_node *a, const ir_node *b)
-{
-       const ir_node *block_a = get_block(a);
-       const ir_node *block_b = get_block(b);
-
-       /*
-        * a and b are not in the same block,
-        * so dominance is determined by the dominance of the blocks.
-        */
-       if(block_a != block_b) {
-               return block_dominates(block_a, block_b);
-       }
-
-       /*
-        * Dominance is determined by the time steps of the schedule.
-        */
-       return _value_dominates_intrablock(a, b);
-}
-
-/**
- * Check, if two values interfere.
- * @param a The first value.
- * @param b The second value.
- * @return 1, if a and b interfere, 0 if not.
- */
-int values_interfere(const be_lv_t *lv, const ir_node *a, const ir_node *b)
-{
-       int a2b = value_dominates(a, b);
-       int b2a = value_dominates(b, a);
-
-       /* If there is no dominance relation, they do not interfere. */
-       if((a2b | b2a) > 0) {
-               const ir_edge_t *edge;
-               ir_node *bb;
-
-               /*
-                * Adjust a and b so, that a dominates b if
-                * a dominates b or vice versa.
-                */
-               if(b2a) {
-                       const ir_node *t = a;
-                       a = b;
-                       b = t;
-               }
-
-               bb = get_nodes_block(b);
-
-               /*
-                * If a is live end in b's block it is
-                * live at b's definition (a dominates b)
-                */
-               if(be_is_live_end(lv, bb, a))
-                       return 1;
-
-               /*
-                * Look at all usages of a.
-                * If there's one usage of a in the block of b, then
-                * we check, if this use is dominated by b, if that's true
-                * a and b interfere. Note that b must strictly dominate the user,
-                * since if b is the last user of in the block, b and a do not
-                * interfere.
-                * Uses of a not in b's block can be disobeyed, because the
-                * check for a being live at the end of b's block is already
-                * performed.
-                */
-               foreach_out_edge(a, edge) {
-                       const ir_node *user = get_edge_src_irn(edge);
-                       if(get_nodes_block(user) == bb && !is_Phi(user) && b != user && value_dominates(b, user))
-                               return 1;
-               }
-       }
-
-       return 0;
-}
-
 /** The list of register allocators */
 static be_module_list_entry_t *register_allocators = NULL;
 static be_ra_t *selected_allocator = NULL;
index f78e3e6..fcab788 100644 (file)
@@ -61,29 +61,6 @@ void be_register_allocator(const char *name, be_ra_t *allocator);
  */
 void be_allocate_registers(be_irg_t *birg);
 
-/**
- * Check, if two values interfere.
- * @param lv Liveness information.
- * @param a The first value.
- * @param b The second value.
- * @return 1, if @p a and @p b interfere, 0 if not.
- */
-int values_interfere(const be_lv_t *lv, const ir_node *a, const ir_node *b);
-
-/**
- * Check, if a value dominates the other one.
- * Note, that this function also considers the schedule and does thus
- * more than block_dominates().
- *
- * @param a The first.
- * @param b The second value.
- * @return 1 if a dominates b, 0 else.
- */
-int value_dominates(const ir_node *a, const ir_node *b);
-
-/**
- * Like value_dominates(), but the nodes have to be in the same block
- */
-int value_dominates_intrablock(const ir_node *a, const ir_node *b);
+int (values_interfere)(const be_irg_t *birg, const ir_node *a, const ir_node *b);
 
 #endif /* FIRM_BE_BERA_H */
index 00d4545..2495cc7 100644 (file)
@@ -58,7 +58,7 @@
 #include "bestatevent.h"
 #include "bessaconstr.h"
 #include "beirg_t.h"
-#include "bera.h"
+#include "beintlive_t.h"
 
 /* only rematerialise when costs are less than REMAT_COST_LIMIT */
 /* TODO determine a good value here... */
index cc51f96..5aa573b 100644 (file)
@@ -63,6 +63,7 @@
 #include "besched_t.h"
 #include "bessaconstr.h"
 #include "bearch_t.h"
+#include "beintlive_t.h"
 #include "beabi.h"
 #include "benode_t.h"
 #include "beutil.h"
@@ -71,7 +72,6 @@
 #include "bepressurestat.h"
 #include "beprofile.h"
 #include "bespilloptions.h"
-#include "bera.h"
 #include "bechordal_t.h"
 #include "bemodule.h"
 
index 815119f..e06fa91 100644 (file)
@@ -49,7 +49,7 @@
 #include "bestatevent.h"
 #include "bespilloptions.h"
 #include "bemodule.h"
-#include "bera.h"
+#include "beintlive_t.h"
 #include "beirg_t.h"
 #include "bearch_t.h"
 
@@ -275,7 +275,6 @@ static void do_greedy_coalescing(be_fec_env_t *env)
        int affinity_edge_count;
        bitset_t **interferences;
        int* spillslot_unionfind;
-       const be_lv_t *lv = be_get_birg_liveness(env->birg);
 
        spillcount = set_count(env->spills);
        if(spillcount == 0)
@@ -315,7 +314,7 @@ static void do_greedy_coalescing(be_fec_env_t *env)
                        if (is_NoMem(spill2))
                                continue;
 
-                       if (values_interfere(lv, spill1, spill2)) {
+                       if (values_interfere(env->birg, spill1, spill2)) {
                                DBG((dbg, DBG_INTERFERENCES, "Slot %d and %d interfere\n", i, i2));
                                bitset_set(interferences[i], i2);
                                bitset_set(interferences[i2], i);
index a1f2c90..a5c1a35 100644 (file)
@@ -53,7 +53,7 @@
 #include "bessaconstr.h"
 #include "bemodule.h"
 #include "besched_t.h"
-#include "bera.h"
+#include "beintlive_t.h"
 #include "beirg_t.h"
 
 #include "debug.h"
index 1f8a1d1..41c11d3 100644 (file)
@@ -49,7 +49,7 @@
 #include "benodesets.h"
 #include "bestatevent.h"
 #include "beirg_t.h"
-#include "bera.h"
+#include "beintlive_t.h"
 
 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
 
@@ -221,7 +221,6 @@ static void insert_all_perms_walker(ir_node *bl, void *data) {
  */
 static void    set_regs_or_place_dupls_walker(ir_node *bl, void *data) {
        be_chordal_env_t *chordal_env = data;
-       be_lv_t *lv = chordal_env->birg->lv;
        ir_node *phi;
 
        /* Consider all phis of this block */
@@ -247,7 +246,7 @@ static void set_regs_or_place_dupls_walker(ir_node *bl, void *data) {
 
                        DBG((dbg, LEVEL_1, "  for %+F(%s) -- %+F(%s)\n", phi, phi_reg->name, arg, arg_reg->name));
 
-                       if (values_interfere(lv, phi, arg)) {
+                       if (values_interfere(chordal_env->birg, phi, arg)) {
                                /*
                                        Insert a duplicate in arguments block,
                                        make it the new phi arg,
index d082bc2..7cf226b 100644 (file)
@@ -46,7 +46,7 @@
 #include "besched_t.h"
 #include "benode_t.h"
 #include "beirg_t.h"
-#include "bera.h"
+#include "beintlive_t.h"
 
 static int my_values_interfere(const ir_node *a, const ir_node *b);