Added new arch interface
[libfirm] / ir / be / belive.c
index 113584b..bf96266 100644 (file)
 #include "beutil.h"
 #include "belive_t.h"
 
+#define DEFAULT_LIVE_SET_SIZE                          8
+
 FIRM_IMPL2(is_live_in, int, const ir_node *, const ir_node *)
 FIRM_IMPL2(is_live_out, int, const ir_node *, const ir_node *)
+FIRM_IMPL2(is_live_end, int, const ir_node *, const ir_node *)
 
 /** The offset of the liveness information in a firm node. */
 size_t live_irn_data_offset = 0;
@@ -38,6 +41,12 @@ static INLINE void mark_live_out(ir_node *block, const ir_node *irn)
        pset_insert_ptr(info->out, irn);
 }
 
+static INLINE void mark_live_end(ir_node *block, const ir_node *irn)
+{
+       block_live_info_t *info = get_block_live_info(block);
+       pset_insert_ptr(info->end, irn);
+}
+
 /**
  * Mark a node (value) live out at a certain block. Do this also
  * transitively, i.e. if the block is not the block of the value's
@@ -45,26 +54,33 @@ static INLINE void mark_live_out(ir_node *block, const ir_node *irn)
  * @param def The node (value).
  * @param block The block to mark the value live out of.
  * @param visited A set were all visited blocks are recorded.
+ * @param is_true_out Is the node real out there or only live at the end
+ * of the block.
  */
-static void live_out_at_block(ir_node *def, ir_node *block, pset *visited)
+static void live_end_at_block(ir_node *def, ir_node *block,
+               pset *visited, int is_true_out)
 {
-       if(pset_find_ptr(visited, block))
-               return;
+       mark_live_end(block, def);
+       if(is_true_out)
+               mark_live_out(block, def);
+
+       if(!pset_find_ptr(visited, block)) {
+
+               pset_insert_ptr(visited, block);
 
-       pset_insert_ptr(visited, block);
-       mark_live_out(block, def);
+               /*
+                * If this block is not the definition block, we have to go up
+                * further.
+                */
+               if(get_nodes_block(def) != block) {
+                       int i, n;
 
-       /*
-        * If this block is not the definition block, we have to go up
-        * further.
-        */
-       if(get_nodes_block(def) != block) {
-               int i, n;
+                       mark_live_in(block, def);
 
-               mark_live_in(block, def);
+                       for(i = 0, n = get_irn_arity(block); i < n; ++i)
+                               live_end_at_block(def, get_nodes_block(get_irn_n(block, i)), visited, 1);
+               }
 
-               for(i = 0, n = get_irn_arity(block); i < n; ++i)
-                       live_out_at_block(def, get_nodes_block(get_irn_n(block, i)), visited);
        }
 }
 
@@ -81,7 +97,7 @@ static void liveness_for_node(ir_node *irn, void *env)
        ir_node *def_block;
        pset *visited;
 
-       /* Don't compute liveness information fornon-data nodes. */
+       /* Don't compute liveness information for non-data nodes. */
        if(!is_data_node(irn))
                return;
 
@@ -103,13 +119,6 @@ static void liveness_for_node(ir_node *irn, void *env)
                /* Get the block where the usage is in. */
                use_block = get_nodes_block(use);
 
-               /*
-                * If the block of the definition equals the use block, we can skip
-                * the following computations, since this use is local to a block.
-                */
-               if(def_block == use_block)
-                       continue;
-
                /*
                 * If the use is a phi function, determine the corresponding block
                 * through which the value reaches the phi function and mark the
@@ -124,7 +133,7 @@ static void liveness_for_node(ir_node *irn, void *env)
                        for(i = 0, n = get_irn_arity(use); i < n; ++i) {
                                if(get_irn_n(use, i) == irn) {
                                        ir_node *pred_block = get_nodes_block(get_irn_n(use_block, i));
-                                       live_out_at_block(irn, pred_block, visited);
+                                       live_end_at_block(irn, pred_block, visited, 0);
                                }
                        }
                }
@@ -133,14 +142,14 @@ static void liveness_for_node(ir_node *irn, void *env)
                 * Else, the value is live in at this block. Mark it and call live
                 * out on the predecessors.
                 */
-               else {
+               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_out_at_block(irn, pred_block, visited);
+                               live_end_at_block(irn, pred_block, visited, 1);
                        }
                }
        }
@@ -151,8 +160,9 @@ static void liveness_for_node(ir_node *irn, void *env)
 static void create_sets(ir_node *block, void *env)
 {
        block_live_info_t *info = get_block_live_info(block);
-       info->in = pset_new_ptr(128);
-       info->out = pset_new_ptr(128);
+       info->in = pset_new_ptr(DEFAULT_LIVE_SET_SIZE);
+       info->out = pset_new_ptr(DEFAULT_LIVE_SET_SIZE);
+       info->end = pset_new_ptr(DEFAULT_LIVE_SET_SIZE);
 }
 
 
@@ -165,6 +175,7 @@ static void liveness_dump(ir_node *block, void *env)
        ir_fprintf(f, "liveness at block %n\n", block);
        ir_fprintf(f, "\tlive  in: %*n\n", pset_iterator, info->in);
        ir_fprintf(f, "\tlive out: %*n\n", pset_iterator, info->out);
+       ir_fprintf(f, "\tlive end: %*n\n", pset_iterator, info->end);
 }
 
 void be_liveness_dump(FILE *f, ir_graph *irg)