+ const ir_edge_t *edge;
+ ir_node *def_block;
+ pset *visited;
+
+ /* Don't compute liveness information for non-data nodes. */
+ if(!is_data_node(irn))
+ return;
+
+ visited = pset_new_ptr(512);
+ def_block = get_nodes_block(irn);
+
+ /* Go over all uses of the value */
+ foreach_out_edge(irn, edge) {
+ ir_node *use = edge->src;
+ ir_node *use_block;
+
+ /*
+ * If the usage is no data node, skip this use, since it does not
+ * affect the liveness of the node.
+ */
+ if(!is_data_node(use))
+ continue;
+
+ /* Get the block where the usage is in. */
+ use_block = get_nodes_block(use);
+
+ /*
+ * If the use is a phi function, determine the corresponding block
+ * through which the value reaches the phi function and mark the
+ * value as live out of that block.
+ */
+ if(is_Phi(use)) {
+ ir_node *pred_block = get_Block_cfgpred_block(use_block, edge->pos);
+ live_end_at_block(irn, pred_block, visited, 0);
+ }
+
+ /*
+ * Else, the value is live in at this block. Mark it and call live
+ * out on the predecessors.
+ */
+ else if(def_block != use_block) {
+ int i, n;
+
+ mark_live_in(use_block, irn);
+
+ for(i = 0, n = get_irn_arity(use_block); i < n; ++i) {
+ ir_node *pred_block = get_nodes_block(get_irn_n(use_block, i));
+ live_end_at_block(irn, pred_block, visited, 1);
+ }
+ }
+ }
+
+ del_pset(visited);
+}