little optimization
[libfirm] / ir / ana / irscc.c
index 332633c..b9add05 100644 (file)
 #include <string.h>
 
 #include "irloop_t.h"
-#include "irnode_t.h"
+
+#include "irprog_t.h"
 #include "irgraph_t.h"
+#include "irnode_t.h"
+#include "irgwalk.h"
 #include "array.h"
 #include "pmap.h"
-#include "irgwalk.h"
-#include "irprog_t.h"
+
 #include "irdump.h"
 
-ir_graph *outermost_ir_graph;      /* The outermost graph the scc is computed
+/* A variant of the loop tree that avoids loops without head.
+   This reduces the depth of the loop tree. */
+#define NO_LOOPS_WITHOUT_HEAD 1
+
+
+INLINE void add_loop_son(ir_loop *loop, ir_loop *son);
+
+INLINE void add_loop_node(ir_loop *loop, ir_node *n);
+
+static ir_graph *outermost_ir_graph;      /* The outermost graph the scc is computed
                       for */
 static ir_loop *current_loop;      /* Current loop construction is working
                       on. */
@@ -46,9 +57,6 @@ ir_node *get_projx_link(ir_node *cb_projx);
 /* Node attributes                                                   **/
 /**********************************************************************/
 
-/* A map to get from irnodes to loop nodes. */
-static pmap *node_loop_map = NULL;
-
 /**********************************************************************/
 /* Node attributes needed for the construction.                      **/
 /**********************************************************************/
@@ -103,7 +111,7 @@ set_irn_uplink (ir_node *n, int uplink) {
   ((scc_info *)n->link)->uplink = uplink;
 }
 
-static INLINE int
+INLINE int
 get_irn_uplink (ir_node *n) {
   assert(get_irn_link(n));
   /*  from fast to slow */
@@ -119,7 +127,7 @@ set_irn_dfn (ir_node *n, int dfn) {
   ((scc_info *)n->link)->dfn = dfn;
 }
 
-static INLINE int
+INLINE int
 get_irn_dfn (ir_node *n) {
   assert(get_irn_link(n));
   /*  to slow */
@@ -127,28 +135,7 @@ get_irn_dfn (ir_node *n) {
   return ((scc_info *)n->link)->dfn;
 }
 
-#if 0
-/* Replaced node loop map by real field as hash access dominates runtime
- * of the algorithm. ! */
-/* Uses temporary information to set the loop */
-INLINE void
-set_irn_loop (ir_node *n, ir_loop* loop) {
-  assert(node_loop_map && "not initialized!");
-  pmap_insert(node_loop_map, (void *)n, (void *)loop);
-}
-
-/* Uses temporary information to get the loop */
-INLINE ir_loop *
-get_irn_loop (ir_node *n) {
-  ir_loop *res = NULL;
-  if (!node_loop_map) return NULL;
-
-  if (pmap_contains(node_loop_map, (void *)n))
-    res = (ir_loop *) pmap_get(node_loop_map, (void *)n);
 
-  return res;
-}
-#else
 INLINE void
 set_irn_loop (ir_node *n, ir_loop* loop) {
   n->loop = loop;
@@ -159,7 +146,6 @@ INLINE ir_loop *
 get_irn_loop (ir_node *n) {
   return n->loop;
 }
-#endif
 
 
 #if 0
@@ -243,20 +229,23 @@ pop_scc_to_loop (ir_node *n)
   ir_node *m;
   int i = 0;
 
-  /*for (;;) {*/
-  do
-    {
+  do {
     m = pop();
+
+    //printf(" dfn: %d, upl %d upl-new %d ", get_irn_dfn(m), get_irn_uplink(m), loop_node_cnt+1); DDMN(m);
+
     loop_node_cnt++;
     set_irn_dfn(m, loop_node_cnt);
     add_loop_node(current_loop, m);
     set_irn_loop(m, current_loop);
     i++;
     /*    if (m==n) break;*/
-    } while(m != n);
+  } while(m != n);
 
-  if(i > 1)
+  /* i might be bigger than 1 for dead (and that's why bad) loops */
+  /* if(i > 1)
     printf("Mehr als eine Iteration!!!!!!!!!!!!!!!!!!!!!!!!!!!!11111\n");
+   */
 }
 
 /* GL ??? my last son is my grandson???  Removes loops with no
@@ -435,7 +424,7 @@ add_loop_node(ir_loop *loop, ir_node *n) {
   loop_element ln;
   ln.node = n;
   assert(loop && loop->kind == k_ir_loop);
-  assert(get_kind(n) == k_ir_node);
+  assert(get_kind(n) == k_ir_node || get_kind(n) == k_ir_graph);  /* used in callgraph.c */
   ARR_APP1 (loop_element, loop->children, ln);
   loop->n_nodes++;
 }
@@ -520,25 +509,25 @@ init_node (ir_node *n, void *env) {
   /* Also init nodes not visible in intraproc_view. */
     /* @@@ init_node is called for too many nodes -- this wastes memory!.
        The mem is not lost as its on the obstack. */
-  if (intern_get_irn_op(n) == op_Filter) {
+  if (get_irn_op(n) == op_Filter) {
     for (i = 0; i < get_Filter_n_cg_preds(n); i++)
       init_node(get_Filter_cg_pred(n, i), NULL);
   }
-  if (intern_get_irn_op(n) == op_Block) {
+  if (get_irn_op(n) == op_Block) {
     for (i = 0; i < get_Block_cg_n_cfgpreds(n); i++) {
       init_node(get_Block_cg_cfgpred(n, i), NULL);
     }
   }
   /* The following pattern matches only after a call from above pattern. */
-  if ((intern_get_irn_op(n) == op_Proj) /*&& (get_Proj_proj(n) == 0)*/) {
+  if ((get_irn_op(n) == op_Proj) /*&& (get_Proj_proj(n) == 0)*/) {
     /* @@@ init_node is called for every proj -- this wastes memory!.
        The mem is not lost as its on the obstack. */
     ir_node *cb = get_Proj_pred(n);
-    if ((intern_get_irn_op(cb) == op_CallBegin) ||
-    (intern_get_irn_op(cb) == op_EndReg) ||
-    (intern_get_irn_op(cb) == op_EndExcept)) {
+    if ((get_irn_op(cb) == op_CallBegin) ||
+    (get_irn_op(cb) == op_EndReg) ||
+    (get_irn_op(cb) == op_EndExcept)) {
       init_node(cb, NULL);
-      init_node(get_nodes_Block(cb), NULL);
+      init_node(get_nodes_block(cb), NULL);
     }
   }
 #endif
@@ -548,7 +537,6 @@ static INLINE void
 init_scc_common (void) {
   current_dfn = 1;
   loop_node_cnt = 0;
-  if (!node_loop_map) node_loop_map = pmap_create();
   init_stack();
 }
 
@@ -575,10 +563,10 @@ init_ip_scc (void) {
 static bool is_outermost_Start(ir_node *n) {
   /* Test whether this is the outermost Start node.  If so
      recursion must end. */
-  if ((intern_get_irn_op(n) == op_Block)     &&
+  if ((get_irn_op(n) == op_Block)     &&
       (get_Block_n_cfgpreds(n) == 1)  &&
-      (intern_get_irn_op(skip_Proj(get_Block_cfgpred(n, 0))) == op_Start) &&
-      (get_nodes_Block(skip_Proj(get_Block_cfgpred(n, 0))) == n)) {
+      (get_irn_op(skip_Proj(get_Block_cfgpred(n, 0))) == op_Start) &&
+      (get_nodes_block(skip_Proj(get_Block_cfgpred(n, 0))) == n)) {
     return true;
   }
 #if 0
@@ -586,7 +574,7 @@ static bool is_outermost_Start(ir_node *n) {
       not possible in interprocedural view as outermost_graph is
       not necessarily the only with a dead-end start block.
       Besides current_ir_graph is not set properly. */
-  if ((intern_get_irn_op(n) == op_Block) &&
+  if ((get_irn_op(n) == op_Block) &&
       (n == get_irg_start_block(current_ir_graph))) {
     if ((!interprocedural_view)  ||
     (current_ir_graph == outermost_ir_graph))
@@ -609,11 +597,11 @@ get_start_index(ir_node *n) {
      not reachable.
      I.e., with this code, the order on the loop tree is correct. But a (single)
      test showed the loop tree is deeper.   */
-  if (intern_get_irn_op(n) == op_Phi   ||
-      intern_get_irn_op(n) == op_Block ||
-      (intern_get_irn_op(n) == op_Filter && interprocedural_view) ||
-      (get_irg_pinned(get_irn_irg(n)) == floats &&
-       get_op_pinned(get_irn_op(n)) == floats))
+  if (get_irn_op(n) == op_Phi   ||
+      get_irn_op(n) == op_Block ||
+      (get_irn_op(n) == op_Filter && interprocedural_view) ||
+      (get_irg_pinned(get_irn_irg(n)) == op_pin_state_floats &&
+       get_op_pinned(get_irn_op(n)) == op_pin_state_floats))
     // Here we could test for backedge at -1 which is illegal
     return 0;
   else
@@ -626,7 +614,7 @@ get_start_index(ir_node *n) {
      But it guarantees that Blocks are analysed before nodes contained in the
      block.  If so, we can set the value to undef if the block is not \
      executed. */
-   if (is_cfop(n) || is_fragile_op(n) || intern_get_irn_op(n) == op_Start)
+   if (is_cfop(n) || is_fragile_op(n) || get_irn_op(n) == op_Start)
      return -1;
    else
      return 0;
@@ -635,72 +623,6 @@ get_start_index(ir_node *n) {
 }
 
 
-#if 0
-/* Returns current_ir_graph and set it to the irg of predecessor index
-   of node n. */
-static INLINE ir_graph *
-switch_irg (ir_node *n, int index) {
-  ir_graph *old_current = current_ir_graph;
-
-  if (interprocedural_view) {
-    /* Only Filter and Block nodes can have predecessors in other graphs. */
-    if (intern_get_irn_op(n) == op_Filter)
-      n = get_nodes_Block(n);
-    if (intern_get_irn_op(n) == op_Block) {
-      ir_node *cfop = skip_Proj(get_Block_cfgpred(n, index));
-      if (is_ip_cfop(cfop)) {
-    current_ir_graph = get_irn_irg(cfop);
-    set_irg_visited(current_ir_graph, get_max_irg_visited());
-      }
-    }
-  }
-
-  return old_current;
-}
-
-/* Walks up the stack passing n and then finding the node
-   where we walked into the irg n is contained in.
-   Here we switch the irg. */
-static ir_graph *
-find_irg_on_stack (ir_node *n) {
-  ir_node *m;
-  ir_graph *old_current = current_ir_graph;
-  int i;
-
-  if (interprocedural_view) {
-    for (i = tos; i >= 0; i--) {
-      if (stack[i] == n) break;
-    }
-    if (i < 0) i = tos;
-
-    assert (i >= 0);
-    for (; i >= 0; i--) {
-      m = stack[i];
-      /*printf(" Visiting %d ", i); DDMN(m);*/
-      if (is_ip_cfop(m)) {
-    current_ir_graph = get_irn_irg(m);
-    break;
-      }
-      if (intern_get_irn_op(m) == op_Filter) {
-    /* Find the corresponding ip_cfop */
-    ir_node *pred = stack[i+1];
-    int j;
-    for (j = 0; j < get_Filter_n_cg_preds(m); j++)
-      if (get_Filter_cg_pred(m, j) == pred) break;
-    if (j >= get_Filter_n_cg_preds(m))
-      /* It is a filter we didn't pass as the predecessors are marked. */
-      continue;
-    assert(get_Filter_cg_pred(m, j) == pred);
-    switch_irg(m, j);
-    break;
-      }
-    }
-  }
-
-  return old_current;
-}
-#endif
-
 #if 0
 static void test(ir_node *pred, ir_node *root, ir_node *this) {
   int i;
@@ -722,7 +644,7 @@ static void test(ir_node *pred, ir_node *root, ir_node *this) {
 
 /* Test for legal loop header: Block, Phi, ... */
 INLINE static bool is_possible_loop_head(ir_node *n) {
-  ir_op *op = intern_get_irn_op(n);
+  ir_op *op = get_irn_op(n);
   return ((op == op_Block) ||
          (op == op_Phi) ||
          ((op == op_Filter) && interprocedural_view));
@@ -743,19 +665,18 @@ is_head (ir_node *n, ir_node *root)
     return false;
 
   if (!is_outermost_Start(n)) {
-    arity = intern_get_irn_arity(n);
+    arity = get_irn_arity(n);
     for (i = get_start_index(n); i < arity; i++) {
-      ir_node *pred = intern_get_irn_n(n, i);
+      ir_node *pred = get_irn_n(n, i);
       assert(pred);
       if (is_backedge(n, i)) continue;
       if (!irn_is_in_stack(pred)) {
        some_outof_loop = 1;
       } else {
-       if(get_irn_uplink(pred) < get_irn_uplink(root))
-         {
-           DDMN(pred); DDMN(root);
-         }
-       assert(get_irn_uplink(pred) >= get_irn_uplink(root));
+       if(get_irn_uplink(pred) < get_irn_uplink(root)) {
+         DDMN(n); DDMN(pred); DDMN(root);
+         assert(get_irn_uplink(pred) >= get_irn_uplink(root));
+       }
        some_in_loop = 1;
       }
     }
@@ -763,6 +684,40 @@ is_head (ir_node *n, ir_node *root)
   return some_outof_loop && some_in_loop;
 }
 
+/* Returns true if n is possible loop head of an endless loop.
+   I.e., it is a Block, Phi or Filter node and has only predecessors
+   within the loop.
+   @arg root: only needed for assertion. */
+static bool
+is_endless_head (ir_node *n, ir_node *root)
+{
+  int i, arity;
+  int some_outof_loop = 0, some_in_loop = 0;
+
+  /* Test for legal loop header: Block, Phi, ... */
+  if (!is_possible_loop_head(n))
+    return false;
+
+  if (!is_outermost_Start(n)) {
+    arity = get_irn_arity(n);
+    for (i = get_start_index(n); i < arity; i++) {
+      ir_node *pred = get_irn_n(n, i);
+      assert(pred);
+      if (is_backedge(n, i)) { continue; }
+      if (!irn_is_in_stack(pred)) {
+       some_outof_loop = 1; //printf(" some out of loop ");
+      } else {
+       if(get_irn_uplink(pred) < get_irn_uplink(root)) {
+         DDMN(pred); DDMN(root);
+         assert(get_irn_uplink(pred) >= get_irn_uplink(root));
+       }
+       some_in_loop = 1;
+      }
+    }
+  }
+  return !some_outof_loop && some_in_loop;
+}
+
 /* Returns index of the predecessor with the smallest dfn number
    greater-equal than limit. */
 static int
@@ -771,9 +726,9 @@ smallest_dfn_pred (ir_node *n, int limit)
   int i, index = -2, min = -1;
 
   if (!is_outermost_Start(n)) {
-    int arity = intern_get_irn_arity(n);
+    int arity = get_irn_arity(n);
     for (i = get_start_index(n); i < arity; i++) {
-      ir_node *pred = intern_get_irn_n(n, i);
+      ir_node *pred = get_irn_n(n, i);
       assert(pred);
       if (is_backedge(n, i) || !irn_is_in_stack(pred)) continue;
       if (get_irn_dfn(pred) >= limit && (min == -1 || get_irn_dfn(pred) < min)) {
@@ -792,9 +747,9 @@ largest_dfn_pred (ir_node *n)
   int i, index = -2, max = -1;
 
   if (!is_outermost_Start(n)) {
-    int arity = intern_get_irn_arity(n);
+    int arity = get_irn_arity(n);
     for (i = get_start_index(n); i < arity; i++) {
-      ir_node *pred = intern_get_irn_n(n, i);
+      ir_node *pred = get_irn_n(n, i);
       if (is_backedge (n, i) || !irn_is_in_stack(pred)) continue;
       if (get_irn_dfn(pred) > max) {
        index = i;
@@ -805,11 +760,14 @@ largest_dfn_pred (ir_node *n)
   return index;
 }
 
-/* Searches the stack for possible loop heads.  Tests these for backedges.
-   If it finds a head with an unmarked backedge it marks this edge and
-   returns the tail of the loop.
-   If it finds no backedge returns NULL.
-   ("disable_backedge" in fiasco) */
+/** Searches the stack for possible loop heads.  Tests these for backedges.
+    If it finds a head with an unmarked backedge it marks this edge and
+    returns the tail of the loop.
+    If it finds no backedge returns NULL.
+    ("disable_backedge" in fiasco)
+*
+*  @param n  A node where uplink == dfn.
+**/
 
 static ir_node *
 find_tail (ir_node *n) {
@@ -819,7 +777,6 @@ find_tail (ir_node *n) {
   /*
     if (!icfg && rm_cyclic_phis && remove_cyclic_phis (n)) return NULL;
   */
-
   m = stack[tos-1];  /* tos = top of stack */
   if (is_head (m, n)) {
     res_index = smallest_dfn_pred(m, 0);
@@ -827,21 +784,60 @@ find_tail (ir_node *n) {
     (n ==  m))
       return NULL;
   } else {
-    if (m == n) return NULL;
-    for (i = tos-2; ; --i) {
+    if (m == n) return NULL;    // Is this to catch Phi - self loops?
+    for (i = tos-2; i >= 0; --i) {
       m = stack[i];
+
       if (is_head (m, n)) {
        res_index = smallest_dfn_pred (m, get_irn_dfn(m) + 1);
        if (res_index == -2)  /* no smallest dfn pred found. */
          res_index = largest_dfn_pred (m);
+
+       if ((m == n) && (res_index == -2)) {  /* dont walk past loop head. */
+         i = -1;
+       }
+       break;
+      }
+
+      /* We should not walk past our selves on the stack:  The upcoming nodes
+        are not in this loop. We assume a loop not reachable from Start. */
+      if (m == n) {
+       i = -1;
        break;
       }
+
+    }
+
+    if (i < 0) {
+      /* A dead loop not reachable from Start. */
+      for (i = tos-2; i >= 0; --i) {
+       m = stack[i];
+       if (is_endless_head (m, n)) {
+         res_index = smallest_dfn_pred (m, get_irn_dfn(m) + 1);
+         if (res_index == -2)  /* no smallest dfn pred found. */
+           res_index = largest_dfn_pred (m);
+         break;
+       }
+       if (m == n) { break; }  /* It's not an unreachable loop, either. */
+      }
+      //assert(0 && "no head found on stack");
     }
+
+  }
+  if (res_index <= -2) {
+    /* It's a completely bad loop: without Phi/Block nodes that can
+       be a head. I.e., the code is "dying".  We break the loop by
+       setting Bad nodes. */
+    int arity = get_irn_arity(n);
+    for (i = -1; i < arity; ++i) {
+      set_irn_n(n, i, get_irg_bad(get_irn_irg(n)));
+    }
+    return NULL;
   }
   assert (res_index > -2);
 
   set_backedge (m, res_index);
-  return is_outermost_Start(n) ? NULL : intern_get_irn_n(m, res_index);
+  return is_outermost_Start(n) ? NULL : get_irn_n(m, res_index);
 }
 
 
@@ -873,9 +869,11 @@ int search_endproj_in_stack(ir_node *start_block)
          printf("FOUND PROJ!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
          ir_node *end_projx = stack[i];
 
-         for(j = 0; j < get_irn_arity(start_block); j++)
+         int arity = get_irn_arity(start_block);
+         for(j = 0; j < arity; j++)
            {
-             ir_node *begin_projx = get_Block_cfgpred(get_irg_start_block(get_irn_irg(end_projx)), get_Proj_proj(end_projx));
+             ir_node *begin_projx = get_Block_cfgpred(get_irg_start_block(get_irn_irg(end_projx)),
+                                                      get_Proj_proj(end_projx));
              DDMN(begin_projx);
              if(get_irn_n(start_block, j) == begin_projx)
                {
@@ -892,11 +890,13 @@ int search_endproj_in_stack(ir_node *start_block)
 static pmap *projx_link = NULL;
 
 void link_to_reg_end (ir_node *n, void *env) {
-  if(get_irn_op(n) == op_Proj && get_irn_mode(n) == mode_X && get_irn_op(get_irn_n(n, 0)) == op_EndReg)
-    {
+  if(get_irn_op(n) == op_Proj &&
+     get_irn_mode(n) == mode_X &&
+     get_irn_op(get_irn_n(n, 0)) == op_EndReg) {
       /* Reg End Projx -> Find the CallBegin Projx and hash it */
       ir_node *end_projx = n;
-      ir_node *begin_projx = get_Block_cfgpred(get_irg_start_block(get_irn_irg(end_projx)), get_Proj_proj(end_projx));
+      ir_node *begin_projx = get_Block_cfgpred(get_irg_start_block(get_irn_irg(end_projx)),
+                                              get_Proj_proj(end_projx));
       printf("Linked the following ProjxNodes:\n");
       DDMN(begin_projx);
       DDMN(end_projx);
@@ -918,6 +918,10 @@ ir_node *get_projx_link(ir_node *cb_projx)
 
 #endif
 
+INLINE static int
+is_outermost_loop(ir_loop *l) {
+  return l == get_loop_outer_loop(l);
+}
 
 
 /*-----------------------------------------------------------*
@@ -942,62 +946,122 @@ static void scc (ir_node *n) {
      so is_backedge does not access array[-1] but correctly returns false! */
 
   if (!is_outermost_Start(n)) {
-    int arity = intern_get_irn_arity(n);
+    int arity = get_irn_arity(n);
 
-#if EXPERIMENTAL_LOOP_TREE
+    for (i = get_start_index(n); i < arity; i++) {
+      ir_node *m;
+      if (is_backedge(n, i)) continue;
+      m = get_irn_n(n, i); /* get_irn_ip_pred(n, i); */
+      /* if ((!m) || (get_irn_op(m) == op_Unknown)) continue; */
+      scc (m);
+      if (irn_is_in_stack(m)) {
+       /* Uplink of m is smaller if n->m is a backedge.
+          Propagate the uplink to mark the loop. */
+       if (get_irn_uplink(m) < get_irn_uplink(n))
+         set_irn_uplink(n, get_irn_uplink(m));
+      }
+    }
+  }
 
-    /* This is meant to be used with the experimenatl code above.
-       If the above code is not used any more, this can be deleted, too.... */
+  if (get_irn_dfn(n) == get_irn_uplink(n)) {
+    /* This condition holds for
+       1) the node with the incoming backedge.
+          That is: We found a loop!
+       2) Straight line code, because no uplink has been propagated, so the
+          uplink still is the same as the dfn.
 
-    if(interprocedural_view &&
-       is_Block(n) &&
-       get_irn_op(get_irn_n(n, 0)) == op_Proj &&
-       get_irn_op(get_irn_n(get_irn_n(n, 0), 0)) == op_CallBegin)
-      {
-       /* We are at the start node of a function:
-          Walk to the callers in the correct order! */
-       DDMN(n);
-       DDMN(get_irn_n(get_irn_n(n, 0), 0));
-       for(i = 0; i < arity; i++)
-         {
-           int pred_nr;
-           ir_node *m;
-
-           pred_nr = search_endproj_in_stack(n);
-           assert(pred_nr >= 0);
-           if(is_backedge(n, pred_nr))
-             continue;
-           m = get_irn_n(n, pred_nr);
-           scc(m);
-
-           if (irn_is_in_stack(m)) {
-             /* Uplink of m is smaller if n->m is a backedge.
-                Propagate the uplink to mark the loop. */
-             if (get_irn_uplink(m) < get_irn_uplink(n))
-               set_irn_uplink(n, get_irn_uplink(m));
-           }
-         }
-      }
-    else
+       But n might not be a proper loop head for the analysis. Proper loop
+       heads are Block and Phi nodes. find_tail searches the stack for
+       Block's and Phi's and takes those nodes as loop heads for the current
+       loop instead and marks the incoming edge as backedge. */
 
+    ir_node *tail = find_tail(n);
+    if (tail) {
+      /* We have a loop, that is no straight line code,
+        because we found a loop head!
+        Next actions: Open a new loop on the loop tree and
+                      try to find inner loops */
+
+#if NO_LOOPS_WITHOUT_HEAD
+      /* This is an adaption of the algorithm from fiasco / optscc to
+       * avoid loops without Block or Phi as first node.  This should
+       * severely reduce the number of evaluations of nodes to detect
+       * a fixpoint in the heap analysis.
+       * Further it avoids loops without firm nodes that cause errors
+       * in the heap analyses.
+       * But attention:  don't do it for the outermost loop:  This loop
+       * is not iterated.  A first block can be a loop head in case of
+       * an endless recursion. */
+
+      ir_loop *l;
+      int close;
+      if ((get_loop_n_elements(current_loop) > 0) || (is_outermost_loop(current_loop))) {
+       l = new_loop();
+       close = 1;
+      } else {
+       l = current_loop;
+       close = 0;
+      }
+#else
+      ir_loop *l = new_loop();
 #endif
 
+      /* Remove the loop from the stack ... */
+      pop_scc_unmark_visit (n);
+
+      /* The current backedge has been marked, that is temporarily eliminated,
+        by find tail. Start the scc algorithm
+        anew on the subgraph thats left (the current loop without the backedge)
+        in order to find more inner loops. */
+      scc (tail);
+
+      assert (irn_visited(n));
+#if NO_LOOPS_WITHOUT_HEAD
+      if (close)
+#endif
+       close_loop(l);
+    }
+    else
       {
-       for (i = get_start_index(n); i < arity; i++) {
-         ir_node *m;
-         if (is_backedge(n, i)) continue;
-         /*      printf("i: %d\n", i); */
-         m = intern_get_irn_n(n, i); /* get_irn_ip_pred(n, i); */
-         /* if ((!m) || (intern_get_irn_op(m) == op_Unknown)) continue; */
-         scc (m);
-         if (irn_is_in_stack(m)) {
-           /* Uplink of m is smaller if n->m is a backedge.
-              Propagate the uplink to mark the loop. */
-           if (get_irn_uplink(m) < get_irn_uplink(n))
-             set_irn_uplink(n, get_irn_uplink(m));
-         }
-       }
+       /* No loop head was found, that is we have straightline code.
+          Pop all nodes from the stack to the current loop. */
+      pop_scc_to_loop(n);
+    }
+  }
+}
+
+static void my_scc (ir_node *n) {
+  int i;
+  if (irn_visited(n)) return;
+  mark_irn_visited(n);
+
+  /* Initialize the node */
+  set_irn_dfn(n, current_dfn);      /* Depth first number for this node */
+  set_irn_uplink(n, current_dfn);   /* ... is default uplink. */
+  set_irn_loop(n, NULL);
+  current_dfn ++;
+  push(n);
+
+  /* AS: get_start_index might return -1 for Control Flow Nodes, and thus a negative
+     array index would be passed to is_backedge(). But CFG Nodes dont't have a backedge array,
+     so is_backedge does not access array[-1] but correctly returns false! */
+
+  if (!is_outermost_Start(n)) {
+    int arity = get_irn_arity(n);
+
+    for (i = get_start_index(n); i < arity; i++) {
+      ir_node *m;
+      if (is_backedge(n, i)) continue;
+      m = get_irn_n(n, i); /* get_irn_ip_pred(n, i); */
+      /* if ((!m) || (get_irn_op(m) == op_Unknown)) continue; */
+      my_scc (m);
+      if (irn_is_in_stack(m)) {
+       /* Uplink of m is smaller if n->m is a backedge.
+          Propagate the uplink to mark the loop. */
+       if (get_irn_uplink(m) < get_irn_uplink(n))
+         set_irn_uplink(n, get_irn_uplink(m));
       }
+    }
   }
 
   if (get_irn_dfn(n) == get_irn_uplink(n)) {
@@ -1019,10 +1083,7 @@ static void scc (ir_node *n) {
         Next actions: Open a new loop on the loop tree and
                       try to find inner loops */
 
-
-#define NO_LOOPS_WITHOUT_HEAD 1
 #if NO_LOOPS_WITHOUT_HEAD
-
       /* This is an adaption of the algorithm from fiasco / optscc to
        * avoid loops without Block or Phi as first node.  This should
        * severely reduce the number of evaluations of nodes to detect
@@ -1032,33 +1093,25 @@ static void scc (ir_node *n) {
 
       ir_loop *l;
       int close;
-      if (get_loop_n_elements(current_loop) > 0) {
+      if ((get_loop_n_elements(current_loop) > 0) || (is_outermost_loop(current_loop))) {
        l = new_loop();
        close = 1;
       } else {
        l = current_loop;
        close = 0;
       }
-
 #else
-
       ir_loop *l = new_loop();
-
 #endif
 
       /* Remove the loop from the stack ... */
       pop_scc_unmark_visit (n);
 
-      /*  GL @@@ remove experimental stuff rem = find_irg_on_stack(tail); */
-
       /* The current backedge has been marked, that is temporarily eliminated,
         by find tail. Start the scc algorithm
         anew on the subgraph thats left (the current loop without the backedge)
         in order to find more inner loops. */
-
-      scc (tail);
-
-      /*  GL @@@ remove experimental stuff current_ir_graph = rem; */
+      my_scc (tail);
 
       assert (irn_visited(n));
 #if NO_LOOPS_WITHOUT_HEAD
@@ -1068,8 +1121,8 @@ static void scc (ir_node *n) {
     }
     else
       {
-       /* AS: No loop head was found, that is we have straightline code.
-              Pop all nodes from the stack to the current loop. */
+       /* No loop head was found, that is we have straightline code.
+          Pop all nodes from the stack to the current loop. */
       pop_scc_to_loop(n);
     }
   }
@@ -1084,7 +1137,7 @@ void construct_backedges(ir_graph *irg) {
   assert(!interprocedural_view &&
      "not implemented, use construct_ip_backedges");
 
-  current_ir_graph = irg;
+  current_ir_graph   = irg;
   outermost_ir_graph = irg;
 
   init_scc(current_ir_graph);
@@ -1093,17 +1146,10 @@ void construct_backedges(ir_graph *irg) {
   new_loop();  /* sets current_loop */
   head_rem = current_loop; /* Just for assertion */
 
-  if (interprocedural_view) {
-    set_irg_visited(current_ir_graph, inc_max_irg_visited());
-    init_ip_walk ();
-  } else {
-    inc_irg_visited(current_ir_graph);
-  }
+  inc_irg_visited(current_ir_graph);
 
   scc(get_irg_end(current_ir_graph));
 
-  if (interprocedural_view) finish_ip_walk();
-
   assert(head_rem == current_loop);
   set_irg_loop(current_ir_graph, current_loop);
   set_irg_loopinfo_state(current_ir_graph, loopinfo_consistent);
@@ -1145,7 +1191,7 @@ void construct_ip_backedges (void) {
     /* Find real entry points */
     sb = get_irg_start_block(current_ir_graph);
     if ((get_Block_n_cfgpreds(sb) > 1) ||
-    (get_nodes_Block(get_Block_cfgpred(sb, 0)) != sb)) continue;
+    (get_nodes_block(get_Block_cfgpred(sb, 0)) != sb)) continue;
     /* Compute scc for this graph */
     outermost_ir_graph = current_ir_graph;
     set_irg_visited(outermost_ir_graph, get_max_irg_visited());
@@ -1230,6 +1276,73 @@ void construct_ip_backedges (void) {
   interprocedural_view = rem_ipv;
 }
 #endif
+void my_construct_ip_backedges (void) {
+  ir_graph *rem = current_ir_graph;
+  int rem_ipv = interprocedural_view;
+  int i;
+
+  assert(get_irp_ip_view_state() == ip_view_valid);
+
+  outermost_ir_graph = get_irp_main_irg();
+
+  init_ip_scc();
+
+  current_loop = NULL;
+  new_loop();  /* sets current_loop */
+  interprocedural_view = 1;
+
+  inc_max_irg_visited();
+  for (i = 0; i < get_irp_n_irgs(); i++)
+    set_irg_visited(get_irp_irg(i), get_max_irg_visited());
+
+  /** We have to start the walk at the same nodes as cg_walk. **/
+  /* Walk starting at unreachable procedures. Only these
+   * have End blocks visible in interprocedural view. */
+  for (i = 0; i < get_irp_n_irgs(); i++) {
+    ir_node *sb;
+    current_ir_graph = get_irp_irg(i);
+
+    sb = get_irg_start_block(current_ir_graph);
+
+    if ((get_Block_n_cfgpreds(sb) > 1) ||
+    (get_nodes_block(get_Block_cfgpred(sb, 0)) != sb)) continue;
+
+    my_scc(get_irg_end(current_ir_graph));
+  }
+
+  /* Check whether we walked all procedures: there could be procedures
+     with cyclic calls but no call from the outside. */
+  for (i = 0; i < get_irp_n_irgs(); i++) {
+    ir_node *sb;
+    current_ir_graph = get_irp_irg(i);
+
+    /* Test start block: if inner procedure end and end block are not
+     * visible and therefore not marked. */
+    sb = get_irg_start_block(current_ir_graph);
+    if (get_irn_visited(sb) < get_irg_visited(current_ir_graph)) scc(sb);
+  }
+
+  /* Walk all endless loops in inner procedures.
+   * We recognize an inner procedure if the End node is not visited. */
+  for (i = 0; i < get_irp_n_irgs(); i++) {
+    ir_node *e;
+    current_ir_graph = get_irp_irg(i);
+
+    e = get_irg_end(current_ir_graph);
+    if (get_irn_visited(e) < get_irg_visited(current_ir_graph)) {
+      int j;
+      /* Don't visit the End node. */
+      for (j = 0; j < get_End_n_keepalives(e); j++) scc(get_End_keepalive(e, j));
+    }
+  }
+
+  set_irg_loop(outermost_ir_graph, current_loop);
+  set_irg_loopinfo_state(current_ir_graph, loopinfo_ip_consistent);
+  assert(get_irg_loop(outermost_ir_graph)->kind == k_ir_loop);
+
+  current_ir_graph = rem;
+  interprocedural_view = rem_ipv;
+}
 
 static void reset_backedges(ir_node *n) {
   if (is_possible_loop_head(n)) {
@@ -1242,6 +1355,8 @@ static void reset_backedges(ir_node *n) {
   }
 }
 
+
+/*
 static void loop_reset_backedges(ir_loop *l) {
   int i;
   reset_backedges(get_loop_node(l, 0));
@@ -1251,12 +1366,23 @@ static void loop_reset_backedges(ir_loop *l) {
     loop_reset_backedges(get_loop_son(l, i));
   }
 }
+*/
+
+static void loop_reset_node(ir_node *n, void *env) {
+  set_irn_loop(n, NULL);
+  reset_backedges(n);
+}
+
 
 /** Removes all loop information.
     Resets all backedges */
 void free_loop_information(ir_graph *irg) {
-  if (get_irg_loop(irg))
-    loop_reset_backedges(get_irg_loop(irg));
+  /* We can not use this recursion, as the loop might contain
+     illegal nodes by now.  Why else would we throw away the
+     representation?
+  if (get_irg_loop(irg)) loop_reset_backedges(get_irg_loop(irg));
+  */
+  irg_walk_graph(irg, loop_reset_node, NULL, NULL);
   set_irg_loop(irg, NULL);
   set_irg_loopinfo_state(current_ir_graph, loopinfo_none);
   /* We cannot free the loop nodes, they are on the obstack. */
@@ -1270,8 +1396,6 @@ void free_all_loop_information (void) {
   for (i = 0; i < get_irp_n_irgs(); i++) {
     free_loop_information(get_irp_irg(i));
   }
-  pmap_destroy(node_loop_map);
-  node_loop_map = NULL;
   interprocedural_view = rem;
 }