typos fixed
[libfirm] / ir / ana / irextbb.c
index b262089..2d5ee83 100644 (file)
@@ -62,26 +62,22 @@ static void addto_extblk(ir_extblk *extblk, ir_node *block)
 
 /**
  * Pre block-walker. Calculates the extended block info.
- * Currently, we use the (free) block input of all basis blocks
- * to point to the leader block.
  */
 static void pre_walk_calc_extbb(ir_node *block, void *ctx)
 {
   int n = get_Block_n_cfgpreds(block);
   env_t *env = ctx;
 
-  if (n > 1 || block == get_irg_start_block(current_ir_graph)) {
+  if (n <= 0 || n > 1 || block == get_irg_start_block(current_ir_graph)) {
     /*
-     * block is a JOIN-node ie he control flow from
+     * block is a JOIN-node ie the control flow from
      * many other blocks joins here. block is a leader.
+     * Note that we handle unreachable blocks (n <= 0) here too.
      */
     allocate_extblk(block, env);
   }
-  else {
-    ir_node *add_to = get_Block_cfgpred(block, 0);
-
-    if (! is_Bad(add_to))
-      add_to = get_nodes_block(add_to);
+  else {    /* we have only one control flow predecessor */
+    ir_node *add_to = get_Block_cfgpred_block(block, 0);
 
     /* blocks with only one BAD predecessors are leaders too */
     if (is_Bad(add_to)) {
@@ -89,7 +85,7 @@ static void pre_walk_calc_extbb(ir_node *block, void *ctx)
     }
     else {
       /*
-       * Only on control flow predecessor. This block belongs
+       * Only one control flow predecessor. This block belongs
        * to the same extended basic block as its predecessor.
        */
       set_Block_extbb(block, NULL);
@@ -97,25 +93,52 @@ static void pre_walk_calc_extbb(ir_node *block, void *ctx)
   }
 }
 
+static int _sentinel;
+
 /**
  * Post block-walker. Calculates the extended block info.
  * During construction, we use the (free) block input of all basic blocks
  * to point to there previous block.
  */
-static void post_walk_calc_extbb(ir_node *block, void *env)
+static void post_walk_calc_extbb(ir_node *block, void *ctx)
 {
   ir_extblk *extbb = get_Block_extbb(block);
+  env_t *env = ctx;
+  ir_extblk *sentinel = (ir_extblk *)&_sentinel;
 
   if (! extbb) {
-    ir_node *prev = block;
+    ir_node *curr, *prev;
 
-    /* search the leader */
-    do {
-      prev = get_nodes_block(get_Block_cfgpred(prev, 0));
+    /*
+     * Search the leader. It can happen, that we fall into an endless
+     * loop, because we enter an unreachable loop that is not yet detected.
+     * We break the loop using a sentinel.
+     */
+    for (curr = block; !extbb; curr = prev) {
+      prev = get_Block_cfgpred_block(curr, 0);
       extbb = get_Block_extbb(prev);
-    } while (! extbb);
+      set_Block_extbb(curr, sentinel);
+    }
+
+    if (extbb == sentinel) {
+      /* We detect a dead loop. We fix this by allocating an
+       * special Extended block
+       */
+      ir_printf("Dead loop detected starting with %+F::%+F\n", get_irg_entity(current_ir_graph), block);
 
-    addto_extblk(extbb, block);
+      allocate_extblk(block, env);
+      extbb = get_Block_extbb(block);
+      set_Block_extbb(block, sentinel);
+    }
+
+    /* replace all sentinels by the extbb info */
+    prev = block;
+    while (1) {
+      if (get_Block_extbb(prev) != sentinel)
+        break;
+      set_Block_extbb(prev, extbb);
+      prev = get_Block_cfgpred_block(prev, 0);
+    }
   }
 }
 
@@ -156,7 +179,8 @@ void compute_extbb(ir_graph *irg) {
     for (block = extbb->link, i = 0; i < len; ++i) {
       ir_node *nblock = get_irn_link(block);
 
-      extbb->blks[i] = block;
+      /* ensure that the leader is the first one */
+      extbb->blks[len - 1 - i] = block;
       set_irn_link(block, NULL);
       block = nblock;
     }
@@ -180,7 +204,7 @@ void free_extbb(ir_graph *irg) {
 
 /* Return the extended block of a node. */
 ir_extblk *get_nodes_extbb(ir_node *node) {
-  ir_node *block = is_Block(node) ? node : get_nodes_block(node);
+  ir_node *block = is_Block(node) ? node : get_irn_n(node, -1);
   return get_Block_extbb(block);
 }
 
@@ -219,12 +243,22 @@ void (set_extbb_link)(ir_extblk *blk, void *link) {
   _set_extbb_link(blk, link);
 }
 
-/* Return the number of basis blocks of an extended block */
+/* Return the number of basic blocks of an extended block */
 int (get_extbb_n_blocks)(const ir_extblk *blk) {
   return _get_extbb_n_blocks(blk);
 }
 
-/* Return the i'th basis block of an extended block */
+/* Return the i'th basic block of an extended block */
 ir_node *(get_extbb_block)(ir_extblk *blk, int pos) {
   return _get_extbb_block(blk, pos);
 }
+
+/* Return the leader basis block of an extended block. */
+ir_node *(get_extbb_leader)(ir_extblk *blk) {
+  return _get_extbb_leader(blk);
+}
+
+/* Return the node number of an extended block. */
+long get_extbb_node_nr(ir_extblk *blk) {
+  return get_irn_node_nr(get_extbb_leader(blk));
+}