#include "irdump_t.h"
#include "irnodeset.h"
+#include "dfs_t.h"
+#include "absgraph.h"
+#include "statev.h"
+
#include "beutil.h"
#include "belive_t.h"
#include "beirg_t.h"
#define LV_USE_BINARY_SEARCH
#undef LV_INTESIVE_CHECKS
+void be_live_chk_compare(be_lv_t *lv, lv_chk_t *lvc);
+
static INLINE int is_liveness_node(const ir_node *irn)
{
switch(get_irn_opcode(irn)) {
case iro_Block:
case iro_Bad:
case iro_End:
+ case iro_Anchor:
return 0;
default:;
}
if(n == 0)
return 0;
-#if 0
- if(idx < payload[0].u.node.idx)
- return 0;
-
- if(idx > payload[n - 1].u.node.idx)
- return n - 1;
-#endif
-
- /* start a binary search for the requested node. */
while(lo < hi) {
int md = lo + ((hi - lo) >> 1);
unsigned md_idx = payload[md].u.node.idx;
struct _be_lv_info_node_t *be_lv_get(const struct _be_lv_t *li, const ir_node *bl, const ir_node *irn)
{
- struct _be_lv_info_t *irn_live = phase_get_irn_data(&li->ph, bl);
+ struct _be_lv_info_t *irn_live;
+ struct _be_lv_info_node_t *res = NULL;
+ stat_ev_tim_push();
+ irn_live = phase_get_irn_data(&li->ph, bl);
if(irn_live) {
unsigned idx = get_irn_idx(irn);
int pos = _be_liveness_bsearch(irn_live, idx);
/* Get the record in question. 1 must be added, since the first record contains information about the array and must be skipped. */
- struct _be_lv_info_node_t *res = &irn_live[pos + 1].u.node;
+ struct _be_lv_info_node_t *rec = &irn_live[pos + 1].u.node;
/* Check, if the irn is in deed in the array. */
- if(res->idx == idx)
- return res;
+ if(rec->idx == idx)
+ res = rec;
}
+ stat_ev_tim_pop("be_lv_get");
- return NULL;
+ return res;
}
static struct _be_lv_info_node_t *be_lv_get_or_set(struct _be_lv_t *li, ir_node *bl, ir_node *irn)
ir_node *use = edge->src;
ir_node *use_block;
+ DBG((dbg, LEVEL_4, "%+F: use at %+F, pos %d in %+F\n", irn, use, edge->pos, get_block(use)));
+ assert(get_irn_n(use, edge->pos) == irn);
+
/*
* If the usage is no data node, skip this use, since it does not
* affect the liveness of the node.
static void *lv_phase_data_init(ir_phase *phase, ir_node *irn, void *old)
{
struct _be_lv_info_t *info = phase_alloc(phase, LV_STD_SIZE * sizeof(info[0]));
+ (void) irn;
+ (void) old;
+
memset(info, 0, LV_STD_SIZE * sizeof(info[0]));
info[0].u.head.n_size = LV_STD_SIZE - 1;
return info;
static int node_idx_cmp(const void *a, const void *b)
{
- int ia = get_irn_idx(a);
- int ib = get_irn_idx(b);
+ const ir_node *p = *(ir_node **) a;
+ const ir_node *q = *(ir_node **) b;
+ int ia = get_irn_idx(p);
+ int ib = get_irn_idx(q);
return ia - ib;
}
ir_node **nodes;
int i, n;
+ stat_ev_tim_push();
obstack_init(&obst);
irg_walk_graph(lv->irg, collect_nodes, NULL, &obst);
n = obstack_object_size(&obst) / sizeof(nodes[0]);
obstack_free(&obst, NULL);
register_hook(hook_node_info, &lv->hook_info);
+ stat_ev_tim_pop("be_lv_sets_cons");
}
void be_liveness_assure_sets(be_lv_t *lv)
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);
+ /* be_live_chk_compare(lv, lv->lvc); */
}
}
void be_liveness_assure_chk(be_lv_t *lv)
{
#ifndef USE_LIVE_CHK
- be_liveness_assure_sets(be_lv_t *lv);
+ be_liveness_assure_sets(lv);
+#else
+ (void) lv;
#endif
}
}
/* Compute the inter block liveness for a graph. */
-be_lv_t *be_liveness(ir_graph *irg)
+be_lv_t *be_liveness(const be_irg_t *birg)
{
be_lv_t *lv = xmalloc(sizeof(lv[0]));
memset(lv, 0, sizeof(lv[0]));
- lv->irg = irg;
- lv->lvc = lv_chk_new(irg);
+ lv->irg = be_get_birg_irg(birg);
+ lv->birg = birg;
+#ifdef USE_LIVE_CHK
+ lv->dfs = dfs_new(&absgraph_irg_cfg_succ, lv->irg);
+ lv->lvc = lv_chk_new(lv->irg, lv->dfs);
+#endif
lv->hook_info.context = lv;
lv->hook_info.hook._hook_node_info = lv_dump_block;
void be_liveness_check(be_lv_t *lv)
{
struct _lv_walker_t w;
- be_lv_t *fresh = be_liveness(lv->irg);
+ be_lv_t *fresh = be_liveness(lv->birg);
w.lv = lv;
w.data = fresh;
return !problem_found;
}
-pset *be_liveness_transfer(const arch_env_t *arch_env, const arch_register_class_t *cls, ir_node *irn, pset *live)
-{
- int i, n;
-
- /* You should better break out of your loop when hitting the first phi function. */
- assert(!is_Phi(irn) && "liveness_transfer produces invalid results for phi nodes");
-
- if(arch_irn_consider_in_reg_alloc(arch_env, cls, irn)) {
- ir_node *del = pset_remove_ptr(live, irn);
- (void) del;
- assert(irn == del);
- }
-
- for(i = 0, n = get_irn_arity(irn); i < n; ++i) {
- ir_node *op = get_irn_n(irn, i);
-
- if(arch_irn_consider_in_reg_alloc(arch_env, cls, op))
- pset_insert_ptr(live, op);
- }
-
- return live;
-}
-
-void be_liveness_transfer_ir_nodeset(const arch_env_t *arch_env,
- const arch_register_class_t *cls,
- ir_node *node, ir_nodeset_t *nodeset)
+void be_liveness_transfer(const arch_env_t *arch_env,
+ const arch_register_class_t *cls,
+ ir_node *node, ir_nodeset_t *nodeset)
{
int i, arity;
* function. */
assert(!is_Phi(node) && "liveness_transfer produces invalid results for phi nodes");
- if(arch_irn_consider_in_reg_alloc(arch_env, cls, node)) {
+ if (get_irn_mode(node) == mode_T) {
+ const ir_edge_t *edge;
+
+ foreach_out_edge(node, edge) {
+ ir_node *proj = get_edge_src_irn(edge);
+
+ if (arch_irn_consider_in_reg_alloc(arch_env, cls, proj)) {
+ ir_nodeset_remove(nodeset, proj);
+ }
+ }
+ }
+
+ if (arch_irn_consider_in_reg_alloc(arch_env, cls, node)) {
ir_nodeset_remove(nodeset, node);
}
arity = get_irn_arity(node);
- for(i = 0; i < arity; ++i) {
+ for (i = 0; i < arity; ++i) {
ir_node *op = get_irn_n(node, i);
- if(arch_irn_consider_in_reg_alloc(arch_env, cls, op))
+ if (arch_irn_consider_in_reg_alloc(arch_env, cls, op))
ir_nodeset_insert(nodeset, op);
}
}
-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))
- pset_insert_ptr(live, irn);
- }
-
- return live;
-}
-
-void be_liveness_end_of_block_ir_nodeset(const be_lv_t *lv,
- const arch_env_t *arch_env,
- const arch_register_class_t *cls,
- const ir_node *block,
- ir_nodeset_t *live)
+void 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 *block, ir_nodeset_t *live)
{
int i;
-pset *be_liveness_nodes_live_at(const be_lv_t *lv, const arch_env_t *arch_env, const arch_register_class_t *cls, const ir_node *pos, pset *live)
+void be_liveness_nodes_live_at(const be_lv_t *lv, const arch_env_t *arch_env,
+ const arch_register_class_t *cls,
+ const ir_node *pos, ir_nodeset_t *live)
{
const ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
ir_node *irn;
* exit immediately, so that this node is still live
*/
if(irn == pos)
- return live;
+ return;
be_liveness_transfer(arch_env, cls, irn, live);
}
-
- return live;
}
-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)
+void 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, ir_nodeset_t *live)
{
const ir_node *bl = is_Block(pos) ? pos : get_nodes_block(pos);
ir_node *irn;
sched_foreach_reverse(bl, irn) {
be_liveness_transfer(arch_env, cls, irn, live);
if(irn == pos)
- return live;
+ return;
}
-
- return live;
}
static void collect_node(ir_node *irn, void *data)
obstack_ptr_grow(&obst, NULL);
nodes = obstack_finish(&obst);
- for (i = 0; blocks[i]; ++i) {
- ir_node *bl = blocks[i];
+ stat_ev_ctx_push("be_lv_chk_compare");
+ for (j = 0; nodes[j]; ++j) {
+ ir_node *irn = nodes[j];
+ 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);
}
}
}
-
+ stat_ev_ctx_pop("be_lv_chk_compare");
obstack_free(&obst, NULL);
}