Commit 3c2f7c0c authored by Sebastian Hack's avatar Sebastian Hack
Browse files

* Changed the liveness API:

  - The liveness in the birg stays always the same
  - Invalidation is done with be_liveness_invalidate()
  - Each algo has to specify if it needs only liveness checks
      be_liveness_assure_chk()
    or the complete liveness sets for use with be_lv_foreach, etc.
      be_liveness_assure_sets()

* Adapted all the files to these changes
* made bessadestr.c liveness updating

[r14506]
parent 1d197a56
......@@ -950,7 +950,6 @@ static void assign_new(ir_node *block, be_chordal_alloc_env_t *alloc_env, bitset
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;
......@@ -968,7 +967,7 @@ static void assign_new(ir_node *block, be_chordal_alloc_env_t *alloc_env, bitset
*/
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;
......@@ -1066,6 +1065,7 @@ void be_ra_chordal_color(be_chordal_env_t *chordal_env)
{
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;
......@@ -1078,7 +1078,10 @@ void be_ra_chordal_color(be_chordal_env_t *chordal_env)
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;
......
......@@ -445,13 +445,16 @@ static void draw_block(ir_node *bl, void *data)
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);
......
......@@ -634,7 +634,7 @@ static void be_ra_chordal_main(be_irg_t *birg)
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);
......
......@@ -1424,6 +1424,8 @@ void co_driver(be_chordal_env_t *cenv)
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);
......
......@@ -16,8 +16,6 @@
#include "irphase_t.h"
#include "iredges_t.h"
#include "irlivechk.h"
#include "beirg_t.h"
#include "besched_t.h"
......@@ -163,7 +161,7 @@ static INLINE int _strictly_dominates_use(const ir_node *irn, const ir_edge_t *e
*/
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. */
......@@ -174,7 +172,7 @@ static INLINE int _be_lv_chk_before_irn(const be_irg_t *birg, const ir_node *irn
* 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;
/*
......@@ -198,13 +196,13 @@ static INLINE int _be_lv_chk_before_irn(const be_irg_t *birg, const ir_node *irn
*/
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) {
......@@ -215,37 +213,12 @@ static INLINE int _be_lv_chk_after_irn(const be_irg_t *birg, const ir_node *irn,
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 */
......@@ -31,29 +31,12 @@
#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)
......@@ -103,11 +86,6 @@ 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);
......
......@@ -34,9 +34,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_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);
......@@ -53,11 +51,4 @@ 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 */
......@@ -43,7 +43,6 @@ 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 *
......@@ -51,11 +50,6 @@ _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;
......@@ -78,7 +72,6 @@ _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)
......
......@@ -486,6 +486,31 @@ static void compute_liveness(be_lv_t *lv)
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)
{
......@@ -493,12 +518,10 @@ 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;
}
......@@ -522,36 +545,39 @@ void be_liveness_recompute(be_lv_t *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)
......@@ -560,23 +586,6 @@ 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;
......@@ -753,6 +762,7 @@ void be_liveness_transfer_ir_nodeset(const arch_env_t *arch_env,
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))
......@@ -770,6 +780,7 @@ void be_liveness_end_of_block_ir_nodeset(const be_lv_t *lv,
{
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))
......@@ -806,6 +817,7 @@ pset *be_liveness_nodes_live_at_input(const be_lv_t *lv, const arch_env_t *arch_
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);
......@@ -822,22 +834,15 @@ static void collect_node(ir_node *irn, void *data)
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);
......
......@@ -192,5 +192,25 @@ 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);
/**
* 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 */
......@@ -36,11 +36,20 @@
#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 {
......@@ -88,8 +97,17 @@ struct _be_lv_info_node_t *be_lv_get(const struct _be_lv_t *li, const ir_node *b
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) \
......
......@@ -872,7 +872,7 @@ void assure_constraints(be_irg_t *birg) {
del_pset(cenv.op_set);
obstack_free(&cenv.obst, NULL);
be_invalidate_liveness(birg);
be_liveness_invalidate(be_get_birg_liveness(birg));
}
......
......@@ -133,7 +133,7 @@ void be_analyze_regpressure(be_irg_t *birg, const arch_register_class_t *cls, co
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");
......
......@@ -783,7 +783,7 @@ static void be_ra_extern_main(be_irg_t *birg) {
/* Clean up */
free_ssa_destr_simple(raenv.vars);
be_invalidate_liveness(birg);
be_liveness_invalidate(be_get_birg_liveness(birg));
}
/******************************************************************************
......
......@@ -892,7 +892,7 @@ void be_insert_spills_reloads(spill_env_t *env)
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)
......
......@@ -83,7 +83,7 @@ typedef struct _belady_env_t {
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 */
......@@ -709,8 +709,8 @@ void be_spill_belady_spill_env(be_irg_t *birg, const arch_register_class_t *cls,
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);
......
......@@ -374,8 +374,7 @@ void be_spill_daemel(be_irg_t *birg, const arch_register_class_t *cls)
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;
......
......@@ -59,7 +59,7 @@ typedef struct morgan_env {
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;
......@@ -564,7 +564,7 @@ void be_spill_morgan(be_irg_t *birg, const arch_register_class_t *cls) {
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;
......
......@@ -19,12 +19,12 @@
/**
* @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.
*
......@@ -63,7 +63,7 @@ struct daemel_env_t {
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;
};
......@@ -316,8 +316,7 @@ void be_spill_daemel(be_irg_t *birg, const arch_register_class_t *cls)
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;
......
......@@ -662,7 +662,7 @@ be_fec_env_t *be_new_frame_entity_coalescer(be_irg_t *birg)
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;
......