#include "irdump.h"
#include "irdom.h"
#include "irtools.h"
+#include "irbitset.h"
#include "debug.h"
#include "xmalloc.h"
#include "iredges.h"
#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"
#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;
*/
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) \
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);
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;
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;
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);
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;
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);
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;
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;
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);
#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;)
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) {
#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"
#include "bestatevent.h"
#include "beirg_t.h"
#include "error.h"
-#include "bera.h"
#include <libcore/lc_timing.h>
#include <libcore/lc_opts.h>
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);
}
#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;)
* 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!");
}
*/
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]++;
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]++;
}
#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"
#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;
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 {
--- /dev/null
+/**
+ * @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 */
#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)
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);
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);
*/
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 */
#include "beirg.h"
#include "be_t.h"
+#include "irlivechk.h"
/**
* An ir_graph with additional analysis data about this irg. Also includes some
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 *
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;
#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)
#include "beutil.h"
#include "belive_t.h"
+#include "beirg_t.h"
#include "besched_t.h"
#include "bemodule.h"
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");
#include "firm_types.h"
#include "pset.h"
+#include "irlivechk.h"
#include "bearch.h"
typedef enum {
*/
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 */
/**
* 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);
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;
*/
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 */
#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... */
#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"
#include "bepressurestat.h"
#include "beprofile.h"
#include "bespilloptions.h"
-#include "bera.h"
#include "bechordal_t.h"
#include "bemodule.h"
#include "bestatevent.h"
#include "bespilloptions.h"
#include "bemodule.h"
-#include "bera.h"
+#include "beintlive_t.h"
#include "beirg_t.h"
#include "bearch_t.h"
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)
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);
#include "bessaconstr.h"
#include "bemodule.h"
#include "besched_t.h"
-#include "bera.h"
+#include "beintlive_t.h"
#include "beirg_t.h"
#include "debug.h"
#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;)
*/
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 */
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,
#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);