+static void collect_liveness_nodes(ir_node *irn, void *data)
+{
+ ir_node **nodes = (ir_node**)data;
+ if (is_liveness_node(irn))
+ nodes[get_irn_idx(irn)] = irn;
+}
+
+void be_liveness_compute_sets(be_lv_t *lv)
+{
+ ir_node **nodes;
+ int i;
+ int n;
+ unsigned last_idx;
+
+ if (lv->sets_valid)
+ return;
+
+ be_timer_push(T_LIVE);
+ last_idx = get_irg_last_idx(lv->irg);
+ if (last_idx >= bitset_size(lv->nodes)) {
+ bitset_free(lv->nodes);
+ lv->nodes = bitset_malloc(last_idx * 2);
+ } else {
+ bitset_clear_all(lv->nodes);
+ }
+ ir_nodehashmap_init(&lv->map);
+ obstack_init(&lv->obst);
+
+ n = get_irg_last_idx(lv->irg);
+ nodes = NEW_ARR_F(ir_node *, n);
+ memset(nodes, 0, sizeof(nodes[0]) * n);
+
+ /* inserting the variables sorted by their ID is probably
+ * more efficient since the binary sorted set insertion
+ * will not need to move around the data. */
+ irg_walk_graph(lv->irg, NULL, collect_liveness_nodes, nodes);
+
+ re.lv = lv;
+ re.visited = bitset_malloc(n);
+
+ for (i = 0; i < n; ++i) {
+ if (nodes[i] != NULL)
+ liveness_for_node(nodes[i]);
+ }
+
+ DEL_ARR_F(nodes);
+ free(re.visited);
+ register_hook(hook_node_info, &lv->hook_info);
+
+ be_timer_pop(T_LIVE);
+
+ lv->sets_valid = true;
+}
+
+void be_liveness_compute_chk(be_lv_t *lv)
+{
+ if (lv->lvc != NULL)
+ return;
+ lv->lvc = lv_chk_new(lv->irg);
+}
+
+void be_liveness_invalidate_sets(be_lv_t *lv)
+{
+ if (!lv->sets_valid)
+ return;
+ unregister_hook(hook_node_info, &lv->hook_info);
+ obstack_free(&lv->obst, NULL);
+ ir_nodehashmap_destroy(&lv->map);
+ lv->sets_valid = false;
+}
+
+void be_liveness_invalidate_chk(be_lv_t *lv)
+{
+ be_liveness_invalidate_sets(lv);
+
+ if (lv->lvc == NULL)
+ return;
+ lv_chk_free(lv->lvc);
+ lv->lvc = NULL;
+}
+
+be_lv_t *be_liveness_new(ir_graph *irg)
+{
+ be_lv_t *lv = XMALLOCZ(be_lv_t);
+
+ lv->irg = irg;
+ lv->hook_info.context = lv;
+ lv->hook_info.hook._hook_node_info = be_dump_liveness_block;
+ lv->nodes = bitset_malloc(2 * get_irg_last_idx(lv->irg));
+
+ return lv;
+}
+
+void be_liveness_free(be_lv_t *lv)
+{
+ be_liveness_invalidate_sets(lv);
+ be_liveness_invalidate_chk(lv);
+
+ bitset_free(lv->nodes);
+ xfree(lv);
+}
+
+void be_liveness_remove(be_lv_t *lv, const ir_node *irn)
+{
+ if (lv->sets_valid) {
+ unsigned idx = get_irn_idx(irn);
+ lv_remove_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.irn = 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)
+{
+ /* Don't compute liveness information for non-data nodes. */
+ if (lv->sets_valid && is_liveness_node(irn)) {
+ re.lv = lv;
+ re.visited = bitset_malloc(get_irg_last_idx(lv->irg));
+ liveness_for_node(irn);
+ bitset_free(re.visited);
+ }
+}
+
+void be_liveness_update(be_lv_t *lv, ir_node *irn)