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_foreach (live_end_dom, elm) {
ir_node *irn = get_idx_irn(env->irg, elm);
- if (lv_chk_bl_in(lv, block, irn)) {
+ if (be_is_live_in(birg->lv, block, irn)) {
const arch_register_t *reg = arch_get_irn_register(arch_env, irn);
int col;
{
be_chordal_alloc_env_t env;
char buf[256];
+ be_lv_t *lv;
be_irg_t *birg = chordal_env->birg;
const arch_register_class_t *cls = chordal_env->cls;
return;
be_assure_dom_front(birg);
- be_assure_liveness(birg);
+ lv = be_assure_liveness(birg);
+ be_liveness_assure_sets(lv);
+ be_liveness_assure_chk(lv);
+
assure_doms(irg);
env.chordal_env = chordal_env;
static void draw(draw_chordal_env_t *env, const rect_t *start_box)
{
plotter_t *p = env->plotter;
+ be_lv_t *lv;
rect_t bbox;
bbox.x = bbox.y = 0;
bbox.w = start_box->w + 2 * env->opts->x_margin;
bbox.h = start_box->h + 2 * env->opts->y_margin;
- be_assure_liveness(env->chordal_env->birg);
+ lv = be_assure_liveness(env->chordal_env->birg);
+ be_liveness_assure_sets(lv);
+ be_liveness_assure_chk(lv);
p->vtab->begin(p, &bbox);
irg_block_walk_graph(env->chordal_env->irg, draw_block, NULL, env);
dump(BE_CH_DUMP_LOWER, irg, NULL, "-belower-after-ra", dump_ir_block_graph_sched);
obstack_free(&obst, NULL);
- be_invalidate_liveness(birg);
+ be_liveness_invalidate(be_get_birg_liveness(birg));
BE_TIMER_POP(ra_timer.t_epilog);
BE_TIMER_POP(ra_timer.t_other);
if (algo < 0 || algo >= CO_ALGO_LAST)
return;
+ be_liveness_assure_chk(be_get_birg_liveness(cenv->birg));
+
co = new_copy_opt(cenv, cost_func);
co_build_ou_structure(co);
co_build_graph_structure(co);
#include "irphase_t.h"
#include "iredges_t.h"
-#include "irlivechk.h"
-
#include "beirg_t.h"
#include "besched_t.h"
*/
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 be_lv_t *lv = be_get_birg_liveness(birg);
const ir_edge_t *edge;
/* the node must strictly dominate the location, else it cannot be live there. */
* 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))
+ if (be_is_live_end(lv, get_nodes_block(where), irn))
return 1;
/*
*/
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 be_lv_t *lv = be_get_birg_liveness(birg);
const ir_edge_t *edge;
if (!_value_dominates(irn, where))
return 0;
- if (lv_chk_bl_end(lv, get_nodes_block(where), irn))
+ if (be_is_live_end(lv, get_nodes_block(where), irn))
return 1;
foreach_out_edge (irn, edge) {
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)
+be_lv_t *be_assure_liveness(be_irg_t *birg)
{
if (birg->lv != NULL)
return;
- birg->lv = be_liveness(birg->irg);
-}
-
-void be_invalidate_liveness(be_irg_t *birg)
-{
- if (birg->lv == NULL)
- return;
-
- be_liveness_free(birg->lv);
- birg->lv = NULL;
+ return birg->lv = be_liveness(birg->irg);
}
void be_assure_dom_front(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);
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_assure_liveness(be_irg_t *birg);
be_lv_t *be_get_birg_liveness(const be_irg_t *birg);
void be_assure_dom_front(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 */
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)
bitset_free(w.data);
}
+void be_liveness_assure_sets(be_lv_t *lv)
+{
+ if (!lv->nodes) {
+ lv->nodes = bitset_malloc(2 * get_irg_last_idx(lv->irg));
+ phase_init(&lv->ph, "liveness", lv->irg, PHASE_DEFAULT_GROWTH, lv_phase_data_init, NULL);
+ compute_liveness(lv);
+ }
+}
+
+void be_liveness_assure_chk(be_lv_t *lv)
+{
+#ifndef USE_LIVE_CHK
+ be_liveness_assure_sets(be_lv_t *lv);
+#endif
+}
+
+void be_liveness_invalidate(be_lv_t *lv)
+{
+ if (lv && lv->nodes) {
+ phase_free(&lv->ph);
+ bitset_free(lv->nodes);
+ lv->nodes = NULL;
+ }
+}
+
/* Compute the inter block liveness for a graph. */
be_lv_t *be_liveness(ir_graph *irg)
{
memset(lv, 0, sizeof(lv[0]));
lv->irg = irg;
- lv->nodes = bitset_malloc(2 * get_irg_last_idx(irg));
+ lv->lvc = lv_chk_new(irg);
lv->hook_info.context = lv;
lv->hook_info.hook._hook_node_info = lv_dump_block;
register_hook(hook_node_info, &lv->hook_info);
- phase_init(&lv->ph, "liveness", irg, PHASE_DEFAULT_GROWTH, lv_phase_data_init, NULL);
- compute_liveness(lv);
return lv;
}
void be_liveness_free(be_lv_t *lv)
{
+ be_liveness_invalidate(lv);
unregister_hook(hook_node_info, &lv->hook_info);
- phase_free(&lv->ph);
- bitset_free(lv->nodes);
free(lv);
}
void be_liveness_remove(be_lv_t *lv, ir_node *irn)
{
- unsigned idx = get_irn_idx(irn);
- struct _lv_walker_t w;
+ if (lv->nodes) {
+ unsigned idx = get_irn_idx(irn);
+ struct _lv_walker_t w;
- /*
- * Removes a single irn from the liveness information.
- * Since an irn can only be live at blocks dominated by the block of its
- * definition, we only have to process that dominance subtree.
- */
- w.lv = lv;
- w.data = irn;
- dom_tree_walk(get_nodes_block(irn), lv_remove_irn_walker, NULL, &w);
- if(idx < bitset_size(lv->nodes))
- bitset_clear(lv->nodes, idx);
+ /*
+ * Removes a single irn from the liveness information.
+ * Since an irn can only be live at blocks dominated by the block of its
+ * definition, we only have to process that dominance subtree.
+ */
+ w.lv = lv;
+ w.data = irn;
+ dom_tree_walk(get_nodes_block(irn), lv_remove_irn_walker, NULL, &w);
+ if(idx < bitset_size(lv->nodes))
+ bitset_clear(lv->nodes, idx);
+ }
}
void be_liveness_introduce(be_lv_t *lv, ir_node *irn)
{
- struct _lv_walker_t w;
- w.lv = lv;
- w.data = bitset_malloc(get_irg_last_idx(lv->irg));
- liveness_for_node(irn, &w);
- bitset_free(w.data);
+ if (lv->nodes) {
+ struct _lv_walker_t w;
+ w.lv = lv;
+ w.data = bitset_malloc(get_irg_last_idx(lv->irg));
+ liveness_for_node(irn, &w);
+ bitset_free(w.data);
+ }
}
void be_liveness_update(be_lv_t *lv, ir_node *irn)
be_liveness_introduce(lv, irn);
}
-static void lv_add_missing_walker(ir_node *irn, void *data)
-{
- struct _lv_walker_t *w = data;
- if(!is_Block(irn) && !bitset_contains_irn(w->lv->nodes, irn)) {
- liveness_for_node(irn, w);
- }
-}
-
-void be_liveness_add_missing(be_lv_t *lv)
-{
- struct _lv_walker_t w;
- w.lv = lv;
- w.data = bitset_malloc(get_irg_last_idx(lv->irg));
- irg_walk_graph(lv->irg, lv_add_missing_walker, NULL, &w);
- bitset_free(w.data);
-}
-
static void lv_check_walker(ir_node *bl, void *data)
{
struct _lv_walker_t *w = data;
pset *be_liveness_end_of_block(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *bl, pset *live)
{
int i;
+ assert(lv->nodes && "live sets must be computed");
be_lv_foreach(lv, bl, be_lv_state_end, i) {
ir_node *irn = be_lv_get_irn(lv, bl, i);
if(arch_irn_consider_in_reg_alloc(arch_env, cls, irn))
{
int i;
+ assert(lv->nodes && "live sets must be computed");
be_lv_foreach(lv, block, be_lv_state_end, i) {
ir_node *node = be_lv_get_irn(lv, block, i);
if(!arch_irn_consider_in_reg_alloc(arch_env, cls, node))
const ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
ir_node *irn;
+ assert(lv->nodes && "live sets must be computed");
be_liveness_end_of_block(lv, arch_env, cls, bl, live);
sched_foreach_reverse(bl, irn) {
be_liveness_transfer(arch_env, cls, irn, live);
obstack_ptr_grow(obst, irn);
}
-void be_live_chk_compare(be_irg_t *birg)
+void be_live_chk_compare(be_lv_t *lv, lv_chk_t *lvc)
{
- ir_graph *irg = be_get_birg_irg(birg);
+ ir_graph *irg = lv->irg;
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);
*/
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);
+/**
+ * Make sure the live sets are computed.
+ * @param lv The liveness infirmation.
+ */
+void be_liveness_assure_sets(be_lv_t *lv);
+
+/**
+ * Make sure all information needed for liveness checks is available.
+ * @param lv The liveness information.
+ */
+void be_liveness_assure_chk(be_lv_t *lv);
+
+/**
+ * Invalidate the liveness information.
+ * You must call this if you modify the program and do not
+ * update the liveness with the be_liveness_{update,remove,introduce}
+ * functions.
+ * @param lv The liveness info.
+ */
+void be_liveness_invalidate(be_lv_t *lv);
#endif /* FIRM_BE_BELIVE_H */
#include "belive.h"
+#define USE_LIVE_CHK
+
+#ifdef USE_LIVE_CHK
+#include "irlivechk.h"
+#endif
+
struct _be_lv_t {
ir_phase ph;
ir_graph *irg;
bitset_t *nodes;
hook_entry_t hook_info;
+#ifdef USE_LIVE_CHK
+ lv_chk_t *lvc;
+#endif
};
struct _be_lv_info_node_t {
static INLINE int _be_is_live_xxx(const struct _be_lv_t *li, const ir_node *block, const ir_node *irn, unsigned flags)
{
- struct _be_lv_info_node_t *info = be_lv_get(li, block, irn);
- return info ? (info->flags & flags) != 0 : 0;
+ if (li->nodes) {
+ struct _be_lv_info_node_t *info = be_lv_get(li, block, irn);
+ return info ? (info->flags & flags) != 0 : 0;
+ }
+
+#ifdef USE_LIVE_CHK
+ else
+ return (lv_chk_bl_xxx(li->lvc, block, irn) & flags) != 0;
+#else
+ assert(li->nodes && "node sets must be computed");
+#endif /* USE_LIVE_CHK */
}
#define be_lv_foreach(lv, bl, flags, i) \
del_pset(cenv.op_set);
obstack_free(&cenv.obst, NULL);
- be_invalidate_liveness(birg);
+ be_liveness_invalidate(be_get_birg_liveness(birg));
}
f = fopen(fname, "w");
assert(f);
- be_assure_liveness(birg);
+ be_liveness_assure_sets(be_assure_liveness(birg));
FIRM_DBG_REGISTER(ra.dbg, "firm.be.regpressureana");
/* Clean up */
free_ssa_destr_simple(raenv.vars);
- be_invalidate_liveness(birg);
+ be_liveness_invalidate(be_get_birg_liveness(birg));
}
/******************************************************************************
be_remove_dead_nodes_from_schedule(env->irg);
/* Matze: In theory be_ssa_construction should take care of the liveness...
* try to disable this again in the future */
- be_invalidate_liveness(env->birg);
+ be_liveness_invalidate(env->birg->lv);
}
void be_init_spill(void)
struct obstack ob;
const arch_env_t *arch;
const arch_register_class_t *cls;
- const be_lv_t *lv;
+ be_lv_t *lv;
be_loopana_t *loop_ana;
int n_regs; /** number of regs in this reg-class */
if(n_regs == 0)
return;
- be_invalidate_liveness(birg);
- be_assure_liveness(birg);
+ be_liveness_assure_sets(be_assure_liveness(birg));
+
/* construct control flow loop tree */
if(! (get_irg_loopinfo_state(irg) & loopinfo_cf_consistent)) {
construct_cf_backedges(irg);
if(n_regs == 0)
return;
- be_invalidate_liveness(birg);
- be_assure_liveness(birg);
+ be_liveness_assure_sets(be_assure_liveness(birg));
env.spill_env = be_new_spill_env(birg);
env.n_regs = n_regs;
const arch_env_t *arch;
const arch_register_class_t *cls;
ir_graph *irg;
- const be_lv_t *lv;
+ be_lv_t *lv;
struct obstack obst;
/** maximum safe register pressure */
int registers_available;
ir_graph *irg = be_get_birg_irg(birg);
morgan_env_t env;
- be_assure_liveness(birg);
+ be_liveness_assure_sets(be_assure_liveness(birg));
env.arch = birg->main_env->arch_env;
env.irg = irg;
/**
* @file
- * @brief Naiv spilling algorithm
+ * @brief Naive spilling algorithm
* @author Matthias Braun
* @date 20.09.2005
- * @version $Id: bespillbelady.c 13913 2007-05-18 12:48:56Z matze $
+ * @version $Id$
* @summary
- * This implements a naiv spilling algorithm. It is design to produce similar
+ * This implements a naive spilling algorithm. It is design to produce similar
* effects to the spill decisions produced by traditional graph coloring
* register allocators that spill while they are coloring the graph.
*
int n_regs;
const arch_env_t *arch_env;
const arch_register_class_t *cls;
- const be_lv_t *lv;
+ be_lv_t *lv;
bitset_t *spilled_nodes;
};
if(n_regs == 0)
return;
- be_invalidate_liveness(birg);
- be_assure_liveness(birg);
+ be_liveness_assure_sets(be_assure_liveness(birg));
env.spill_env = be_new_spill_env(birg);
env.n_regs = n_regs;
const arch_env_t *arch_env = birg->main_env->arch_env;
be_fec_env_t *env = xmalloc(sizeof(env[0]));
- be_assure_liveness(birg);
+ be_liveness_assure_chk(be_assure_liveness(birg));
obstack_init(&env->obst);
env->arch_env = arch_env;
perm = be_new_Perm(chordal_env->cls, irg, pred_bl, n_projs, in);
be_stat_ev("phi_perm", n_projs);
- free(in);
insert_after = sched_skip(sched_last(pred_bl), 0, sched_skip_cf_predicator, chordal_env->birg->main_env->arch_env);
sched_add_after(insert_after, perm);
pp = set_find(arg_set, &templ, sizeof(templ), nodeset_hash(templ.arg));
/* If not found, it was an interfering argument */
- if (pp)
+ if (pp) {
set_irn_n(phi, i, pp->proj);
+ be_liveness_introduce(lv, pp->proj);
+ }
+ }
+
+ /* update the liveness of the Perm's operands. It might be changed. */
+ {
+ int i;
+ for (i = 0; i < n_projs; ++i)
+ be_liveness_update(lv, in[i]);
}
+ free(in);
/* register in perm map */
pmap_insert(perm_map, pred_bl, perm);
*/
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 */
set_reg(dupl, phi_reg);
sched_add_after(sched_skip(sched_last(arg_block), 0, sched_skip_cf_predicator, chordal_env->birg->main_env->arch_env), dupl);
pin_irn(dupl, phi_block);
+ be_liveness_introduce(lv, dupl);
+ be_liveness_update(lv, arg);
DBG((dbg, LEVEL_1, " they do interfere: insert %+F(%s)\n", dupl, get_reg(dupl)->name));
continue; /* with next argument */
}
for(ins = sched_next(perm); is_Proj(ins); ins = sched_next(ins));
sched_add_before(ins, dupl);
pin_irn(dupl, phi_block);
+ be_liveness_introduce(lv, dupl);
+ be_liveness_update(lv, arg);
DBG((dbg, LEVEL_1, " arg is pinned: insert %+F(%s)\n", dupl, get_reg(dupl)->name));
} else {
/*
}
void be_ssa_destruction(be_chordal_env_t *chordal_env) {
+ insert_all_perms_env_t insert_perms_env;
pmap *perm_map = pmap_create();
ir_graph *irg = chordal_env->irg;
- insert_all_perms_env_t insert_perms_env;
+ be_lv_t *lv = be_assure_liveness(chordal_env->birg);
FIRM_DBG_REGISTER(dbg, "ir.be.ssadestr");
- be_assure_liveness(chordal_env->birg);
+ be_liveness_assure_sets(lv);
/* create a map for fast lookup of perms: block --> perm */
irg_walk_graph(irg, clear_link, collect_phis_walker, chordal_env);
insert_perms_env.perm_map = perm_map;
irg_block_walk_graph(irg, insert_all_perms_walker, NULL, &insert_perms_env);
+ // Matze: really needed here?
+ // Sebastian: Yes. the walker function uses interference.
+ be_liveness_invalidate(lv);
+
if (chordal_env->opts->dump_flags & BE_CH_DUMP_SSADESTR)
be_dump(irg, "-ssa_destr_perms_placed", dump_ir_block_graph_sched);
- // Matze: really needed here?
- be_invalidate_liveness(chordal_env->birg);
- be_assure_liveness(chordal_env->birg);
+ be_liveness_assure_chk(lv);
DBG((dbg, LEVEL_1, "Setting regs and placing dupls...\n"));
irg_block_walk_graph(irg, set_regs_or_place_dupls_walker, NULL, chordal_env);
+ /* TODO: unfortunaltely updating doesn't work yet. */
+ be_liveness_invalidate(lv);
+
if (chordal_env->opts->dump_flags & BE_CH_DUMP_SSADESTR)
be_dump(irg, "-ssa_destr_regs_set", dump_ir_block_graph_sched);
minibelady_env_t env;
ir_graph *irg = be_get_birg_irg(birg);
spill_info_t *info;
- be_lv_t *lv = be_get_birg_liveness(birg);
+ be_lv_t *lv = be_assure_liveness(birg);
- be_assure_liveness(birg);
+ be_liveness_assure_sets(lv);
be_assure_dom_front(birg);
/* construct control flow loop tree */
if(! (get_irg_loopinfo_state(irg) & loopinfo_cf_consistent)) {
free_trouts();
free_loop_information(irg);
set_irg_doms_inconsistent(irg);
- be_invalidate_liveness(birg);
+
+ be_liveness_invalidate(be_get_birg_liveness(birg));
be_invalidate_dom_front(birg);
/* create a new obstack */
env.registers_available = env.cls->n_regs - be_put_ignore_regs(birg, env.cls, NULL);
env.problem_found = 0;
+ be_liveness_assure_sets(env.lv);
irg_block_walk_graph(irg, verify_liveness_walker, NULL, &env);
be_liveness_free(env.lv);
env.lv = be_liveness(irg);
env.problem_found = 0;
+ be_liveness_assure_sets(env.lv);
irg_block_walk_graph(irg, verify_block_register_allocation, NULL, &env);
be_liveness_free(env.lv);
sim.worklist = new_waitq();
waitq_put(sim.worklist, start_block);
- be_invalidate_liveness(birg);
be_assure_liveness(birg);
sim.lv = be_get_birg_liveness(birg);
+// sim.lv = be_liveness(be_get_birg_irg(birg));
+ be_liveness_assure_sets(sim.lv);
/* Calculate the liveness for all nodes. We must precalculate this info,
* because the simulator adds new nodes (possible before Phi nodes) which