made copy_attrs an ir_op operation
[libfirm] / ir / ir / irgopt.c
index e9cc720..9292431 100644 (file)
 
 
 #ifdef HAVE_CONFIG_H
-# include <config.h>
+# include "config.h"
 #endif
 
-# include <assert.h>
-# include <stdbool.h>
-
-# include "irprog.h"
-# include "irgopt.h"
-# include "irnode_t.h"
-# include "irgraph_t.h"
-# include "iropt_t.h"
-# include "irgwalk.h"
-# include "ircons.h"
-# include "irgmod.h"
-# include "array.h"
-# include "pset.h"
-# include "eset.h"
-# include "pdeq.h"       /* Fuer code placement */
-# include "irouts.h"
-# include "irloop.h"
-# include "irbackedge_t.h"
-# include "irflag_t.h"
-# include "firmstat.h"
+#include <assert.h>
+
+#include "irnode_t.h"
+#include "irgraph_t.h"
+#include "irprog_t.h"
+
+#include "ircons.h"
+#include "iropt_t.h"
+#include "irgopt.h"
+#include "irgmod.h"
+#include "irgwalk.h"
+
+#include "array.h"
+#include "pset.h"
+#include "eset.h"
+#include "pdeq.h"       /* Fuer code placement */
+#include "xmalloc.h"
+
+#include "irouts.h"
+#include "irloop_t.h"
+#include "irbackedge_t.h"
+#include "cgana.h"
+
+#include "irflag_t.h"
+#include "firmstat.h"
 
 /* Defined in iropt.c */
 pset *new_identities (void);
@@ -50,9 +55,9 @@ static void init_link (ir_node *n, void *env) {
 }
 
 #if 0   /* Old version. Avoids Ids.
-       This is not necessary:  we do a postwalk, and get_irn_n
-       removes ids anyways.  So it's much cheaper to call the
-       optimization less often and use the exchange() algorithm. */
+           This is not necessary:  we do a postwalk, and get_irn_n
+           removes ids anyways.  So it's much cheaper to call the
+           optimization less often and use the exchange() algorithm. */
 static void
 optimize_in_place_wrapper (ir_node *n, void *env) {
   int i, irn_arity;
@@ -81,16 +86,11 @@ optimize_in_place_wrapper (ir_node *n, void *env) {
 #endif
 
 
-
-void
-local_optimize_graph (ir_graph *irg) {
-  ir_graph *rem = current_ir_graph;
-  current_ir_graph = irg;
-
+static INLINE void do_local_optimize(ir_node *n) {
   /* Handle graph state */
-  assert(get_irg_phase_state(irg) != phase_building);
+  assert(get_irg_phase_state(current_ir_graph) != phase_building);
   if (get_opt_global_cse())
-    set_irg_pinned(current_ir_graph, floats);
+    set_irg_pinned(current_ir_graph, op_pin_state_floats);
   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
     set_irg_outs_inconsistent(current_ir_graph);
   if (get_irg_dom_state(current_ir_graph) == dom_consistent)
@@ -99,15 +99,34 @@ local_optimize_graph (ir_graph *irg) {
 
 
   /* Clean the value_table in irg for the cse. */
-  del_identities(irg->value_table);
-  irg->value_table = new_identities();
+  del_identities(current_ir_graph->value_table);
+  current_ir_graph->value_table = new_identities();
 
   /* walk over the graph */
-  irg_walk(irg->end, init_link, optimize_in_place_wrapper, NULL);
+  irg_walk(n, init_link, optimize_in_place_wrapper, NULL);
+}
+
+void local_optimize_node(ir_node *n) {
+  ir_graph *rem = current_ir_graph;
+  current_ir_graph = get_irn_irg(n);
+
+  do_local_optimize(n);
+
+  current_ir_graph = rem;
+
+}
+
+void
+local_optimize_graph (ir_graph *irg) {
+  ir_graph *rem = current_ir_graph;
+  current_ir_graph = irg;
+
+  do_local_optimize(irg->end);
 
   current_ir_graph = rem;
 }
 
+
 /*------------------------------------------------------------------*/
 /* Routines for dead node elimination / copying garbage collection  */
 /* of the obstack.                                                  */
@@ -185,23 +204,31 @@ static INLINE void new_backedge_info(ir_node *n) {
  * For Phi and Block nodes the function allocates in-arrays with an arity
  * only for useful predecessors.  The arity is determined by counting
  * the non-bad predecessors of the block.
+ *
+ * @param n    The node to be copied
+ * @param env  if non-NULL, the node number attribute will be copied to the new node
  */
 static void
 copy_node (ir_node *n, void *env) {
   ir_node *nn, *block;
   int new_arity;
+  opcode op = get_irn_opcode(n);
+  int copy_node_nr = env != NULL;
 
   /* The end node looses it's flexible in array.  This doesn't matter,
      as dead node elimination builds End by hand, inlineing doesn't use
      the End node. */
   /* assert(n->op == op_End ||  ((_ARR_DESCR(n->in))->cookie != ARR_F_MAGIC)); */
 
-  if (get_irn_opcode(n) == iro_Block) {
+  if (op == iro_Bad) {
+    /* node copied already */
+    return;
+  } else if (op == iro_Block) {
     block = NULL;
     new_arity = compute_new_arity(n);
     n->attr.block.graph_arr = NULL;
   } else {
-    block = get_nodes_Block(n);
+    block = get_nodes_block(n);
     if (get_irn_opcode(n) == iro_Phi) {
       new_arity = compute_new_arity(block);
     } else {
@@ -218,13 +245,19 @@ copy_node (ir_node *n, void *env) {
   /* Copy the attributes.  These might point to additional data.  If this
      was allocated on the old obstack the pointers now are dangling.  This
      frees e.g. the memory of the graph_arr allocated in new_immBlock. */
-  copy_attrs(n, nn);
+  copy_node_attr(n, nn);
   new_backedge_info(nn);
   set_new_node(n, nn);
 
+#if DEBUG_libfirm
+  if (copy_node_nr) {
+    /* for easier debugging, we want to copy the node numbers too */
+    nn->node_nr = n->node_nr;
+  }
+#endif
+
   /*  printf("\n old node: "); DDMSG2(n);
       printf(" new node: "); DDMSG2(nn); */
-
 }
 
 /**
@@ -248,9 +281,9 @@ copy_preds (ir_node *n, void *env) {
     irn_arity = get_irn_arity(n);
     for (i = 0; i < irn_arity; i++)
       if (get_irn_opcode(get_irn_n(n, i)) != iro_Bad) {
-       set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
-       /*if (is_backedge(n, i)) set_backedge(nn, j);*/
-       j++;
+        set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
+        /*if (is_backedge(n, i)) set_backedge(nn, j);*/
+        j++;
       }
     /* repair the block visited flag from above misuse. Repair it in both
        graphs so that the old one can still be used. */
@@ -261,33 +294,33 @@ copy_preds (ir_node *n, void *env) {
        We don't call optimize_in_place as it requires
        that the fields in ir_graph are set properly. */
     if ((get_opt_control_flow_straightening()) &&
-       (get_Block_n_cfgpreds(nn) == 1) &&
-       (get_irn_op(get_Block_cfgpred(nn, 0)) == op_Jmp)) {
-      ir_node *old = get_nodes_Block(get_Block_cfgpred(nn, 0));
+        (get_Block_n_cfgpreds(nn) == 1) &&
+        (get_irn_op(get_Block_cfgpred(nn, 0)) == op_Jmp)) {
+      ir_node *old = get_nodes_block(get_Block_cfgpred(nn, 0));
       if (nn == old) {
-       /* Jmp jumps into the block it is in -- deal self cycle. */
-       assert(is_Bad(get_new_node(get_irg_bad(current_ir_graph))));
-       exchange(nn, get_new_node(get_irg_bad(current_ir_graph)));
+        /* Jmp jumps into the block it is in -- deal self cycle. */
+        assert(is_Bad(get_new_node(get_irg_bad(current_ir_graph))));
+        exchange(nn, get_new_node(get_irg_bad(current_ir_graph)));
       } else {
-       exchange(nn, old);
+        exchange(nn, old);
       }
     }
   } else if (get_irn_opcode(n) == iro_Phi) {
     /* Don't copy node if corresponding predecessor in block is Bad.
        The Block itself should not be Bad. */
-    block = get_nodes_Block(n);
+    block = get_nodes_block(n);
     set_irn_n (nn, -1, get_new_node(block));
     j = 0;
     irn_arity = get_irn_arity(n);
     for (i = 0; i < irn_arity; i++)
       if (get_irn_opcode(get_irn_n(block, i)) != iro_Bad) {
-    set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
-    /*if (is_backedge(n, i)) set_backedge(nn, j);*/
-    j++;
+        set_irn_n (nn, j, get_new_node(get_irn_n(n, i)));
+        /*if (is_backedge(n, i)) set_backedge(nn, j);*/
+        j++;
       }
     /* If the pre walker reached this Phi after the post walker visited the
        block block_visited is > 0. */
-    set_Block_block_visited(get_nodes_Block(n), 0);
+    set_Block_block_visited(get_nodes_block(n), 0);
     /* Compacting the Phi's ins might generate Phis with only one
        predecessor. */
     if (get_irn_arity(n) == 1)
@@ -305,10 +338,12 @@ copy_preds (ir_node *n, void *env) {
 
 /**
  * Copies the graph recursively, compacts the keepalive of the end node.
+ *
+ * @param copy_node_nr  If non-zero, the node number will be copied
  */
 static void
-copy_graph (void) {
-  ir_node *oe, *ne; /* old end, new end */
+copy_graph (int copy_node_nr) {
+  ir_node *oe, *ne, *ob, *nb, *om, *nm; /* old end, new end, old bad, new bad, old NoMem, new NoMem */
   ir_node *ka;      /* keep alive */
   int i, irn_arity;
 
@@ -322,13 +357,35 @@ copy_graph (void) {
            -1,
            NULL);
   /* Copy the attributes.  Well, there might be some in the future... */
-  copy_attrs(oe, ne);
+  copy_node_attr(oe, ne);
   set_new_node(oe, ne);
 
+  /* copy the Bad node */
+  ob = get_irg_bad(current_ir_graph);
+  nb =  new_ir_node(get_irn_dbg_info(ob),
+           current_ir_graph,
+           NULL,
+           op_Bad,
+           mode_T,
+           0,
+           NULL);
+  set_new_node(ob, nb);
+
+  /* copy the NoMem node */
+  om = get_irg_no_mem(current_ir_graph);
+  nm =  new_ir_node(get_irn_dbg_info(om),
+           current_ir_graph,
+           NULL,
+           op_NoMem,
+           mode_M,
+           0,
+           NULL);
+  set_new_node(om, nm);
+
   /* copy the live nodes */
-  irg_walk(get_nodes_Block(oe), copy_node, copy_preds, NULL);
+  irg_walk(get_nodes_block(oe), copy_node, copy_preds, (void *)copy_node_nr);
   /* copy_preds for the end node ... */
-  set_nodes_Block(ne, get_new_node(get_nodes_Block(oe)));
+  set_nodes_block(ne, get_new_node(get_nodes_block(oe)));
 
   /*- ... and now the keep alives. -*/
   /* First pick the not marked block nodes and walk them.  We must pick these
@@ -337,10 +394,10 @@ copy_graph (void) {
   for (i = 0; i < irn_arity; i++) {
     ka = get_irn_intra_n(oe, i);
     if ((get_irn_op(ka) == op_Block) &&
-    (get_irn_visited(ka) < get_irg_visited(current_ir_graph))) {
+        (get_irn_visited(ka) < get_irg_visited(current_ir_graph))) {
       /* We must keep the block alive and copy everything reachable */
       set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
-      irg_walk(ka, copy_node, copy_preds, NULL);
+      irg_walk(ka, copy_node, copy_preds, (void *)copy_node_nr);
       add_End_keepalive(ne, get_new_node(ka));
     }
   }
@@ -351,13 +408,17 @@ copy_graph (void) {
     ka = get_irn_intra_n(oe, i);
     if ((get_irn_op(ka) == op_Phi)) {
       if (get_irn_visited(ka) < get_irg_visited(current_ir_graph)) {
-    /* We didn't copy the Phi yet.  */
-    set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
-    irg_walk(ka, copy_node, copy_preds, NULL);
+        /* We didn't copy the Phi yet.  */
+        set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
+        irg_walk(ka, copy_node, copy_preds, (void *)copy_node_nr);
       }
       add_End_keepalive(ne, get_new_node(ka));
     }
   }
+
+  /* start block sometimes only reached after keep alives */
+  set_nodes_block(nb, get_new_node(get_nodes_block(ob)));
+  set_nodes_block(nm, get_new_node(get_nodes_block(om)));
 }
 
 /**
@@ -365,22 +426,26 @@ copy_graph (void) {
  * in current_ir_graph and fixes the environment.
  * Then fixes the fields in current_ir_graph containing nodes of the
  * graph.
+ *
+ * @param copy_node_nr  If non-zero, the node number will be copied
  */
 static void
-copy_graph_env (void) {
+copy_graph_env (int copy_node_nr) {
   ir_node *old_end;
   /* Not all nodes remembered in current_ir_graph might be reachable
      from the end node.  Assure their link is set to NULL, so that
      we can test whether new nodes have been computed. */
-  set_irn_link(get_irg_frame  (current_ir_graph), NULL);
-  set_irn_link(get_irg_globals(current_ir_graph), NULL);
-  set_irn_link(get_irg_args   (current_ir_graph), NULL);
+  set_irn_link(get_irg_frame      (current_ir_graph), NULL);
+  set_irn_link(get_irg_globals    (current_ir_graph), NULL);
+  set_irn_link(get_irg_args       (current_ir_graph), NULL);
+  set_irn_link(get_irg_initial_mem(current_ir_graph), NULL);
+  set_irn_link(get_irg_no_mem     (current_ir_graph), NULL);
 
   /* we use the block walk flag for removing Bads from Blocks ins. */
   inc_irg_block_visited(current_ir_graph);
 
   /* copy the graph */
-  copy_graph();
+  copy_graph(copy_node_nr);
 
   /* fix the fields in current_ir_graph */
   old_end = get_irg_end(current_ir_graph);
@@ -390,29 +455,41 @@ copy_graph_env (void) {
   free_End(old_end);
   set_irg_end_block  (current_ir_graph, get_new_node(get_irg_end_block(current_ir_graph)));
   if (get_irn_link(get_irg_frame(current_ir_graph)) == NULL) {
-    copy_node (get_irg_frame(current_ir_graph), NULL);
+    copy_node (get_irg_frame(current_ir_graph), (void *)copy_node_nr);
     copy_preds(get_irg_frame(current_ir_graph), NULL);
   }
   if (get_irn_link(get_irg_globals(current_ir_graph)) == NULL) {
-    copy_node (get_irg_globals(current_ir_graph), NULL);
+    copy_node (get_irg_globals(current_ir_graph), (void *)copy_node_nr);
     copy_preds(get_irg_globals(current_ir_graph), NULL);
   }
+  if (get_irn_link(get_irg_initial_mem(current_ir_graph)) == NULL) {
+    copy_node (get_irg_initial_mem(current_ir_graph), (void *)copy_node_nr);
+    copy_preds(get_irg_initial_mem(current_ir_graph), NULL);
+  }
   if (get_irn_link(get_irg_args(current_ir_graph)) == NULL) {
-    copy_node (get_irg_args(current_ir_graph), NULL);
+    copy_node (get_irg_args(current_ir_graph), (void *)copy_node_nr);
     copy_preds(get_irg_args(current_ir_graph), NULL);
   }
-  set_irg_start  (current_ir_graph, get_new_node(get_irg_start(current_ir_graph)));
+  set_irg_start      (current_ir_graph, get_new_node(get_irg_start(current_ir_graph)));
 
   set_irg_start_block(current_ir_graph,
               get_new_node(get_irg_start_block(current_ir_graph)));
-  set_irg_frame  (current_ir_graph, get_new_node(get_irg_frame(current_ir_graph)));
-  set_irg_globals(current_ir_graph, get_new_node(get_irg_globals(current_ir_graph)));
-  set_irg_args   (current_ir_graph, get_new_node(get_irg_args(current_ir_graph)));
+  set_irg_frame      (current_ir_graph, get_new_node(get_irg_frame(current_ir_graph)));
+  set_irg_globals    (current_ir_graph, get_new_node(get_irg_globals(current_ir_graph)));
+  set_irg_initial_mem(current_ir_graph, get_new_node(get_irg_initial_mem(current_ir_graph)));
+  set_irg_args       (current_ir_graph, get_new_node(get_irg_args(current_ir_graph)));
+
   if (get_irn_link(get_irg_bad(current_ir_graph)) == NULL) {
-    copy_node(get_irg_bad(current_ir_graph), NULL);
+    copy_node(get_irg_bad(current_ir_graph), (void *)copy_node_nr);
     copy_preds(get_irg_bad(current_ir_graph), NULL);
   }
   set_irg_bad(current_ir_graph, get_new_node(get_irg_bad(current_ir_graph)));
+
+  if (get_irn_link(get_irg_no_mem(current_ir_graph)) == NULL) {
+    copy_node(get_irg_no_mem(current_ir_graph), (void *)copy_node_nr);
+    copy_preds(get_irg_no_mem(current_ir_graph), NULL);
+  }
+  set_irg_no_mem(current_ir_graph, get_new_node(get_irg_no_mem(current_ir_graph)));
 }
 
 /**
@@ -426,22 +503,22 @@ copy_graph_env (void) {
 void
 dead_node_elimination(ir_graph *irg) {
   ir_graph *rem;
-  int rem_ipview = interprocedural_view;
+  int rem_ipview = get_interprocedural_view();
   struct obstack *graveyard_obst = NULL;
   struct obstack *rebirth_obst   = NULL;
 
+  /* inform statistics that we started a dead-node elimination run */
   stat_dead_node_elim_start(irg);
 
   /* Remember external state of current_ir_graph. */
   rem = current_ir_graph;
   current_ir_graph = irg;
-  interprocedural_view = 0;
+  set_interprocedural_view(false);
 
   /* Handle graph state */
   assert(get_irg_phase_state(current_ir_graph) != phase_building);
-  assert(get_irg_callee_info_state(current_ir_graph) == irg_callee_info_none);
+  free_callee_info(current_ir_graph);
   free_outs(current_ir_graph);
-
   /* @@@ so far we loose loops when copying */
   free_loop_information(current_ir_graph);
 
@@ -461,17 +538,18 @@ dead_node_elimination(ir_graph *irg) {
     irg->value_table = new_identities ();
 
     /* Copy the graph from the old to the new obstack */
-    copy_graph_env();
+    copy_graph_env(1);
 
     /* Free memory from old unoptimized obstack */
     obstack_free(graveyard_obst, 0);  /* First empty the obstack ... */
     xfree (graveyard_obst);           /* ... then free it.           */
   }
 
+  /* inform statistics that the run is over */
   stat_dead_node_elim_stop(irg);
 
   current_ir_graph = rem;
-  interprocedural_view = rem_ipview;
+  set_interprocedural_view(rem_ipview);
 }
 
 /**
@@ -500,17 +578,25 @@ static void relink_bad_block_predecessors(ir_node *n, void *env) {
 
     /* arity changing: set new predecessors without bad nodes */
     if (new_irn_arity < old_irn_arity) {
-      /* get new predecessor array without Block predecessor */
+      /* Get new predecessor array. We do not resize the array, as we must
+        keep the old one to update Phis. */
       new_in = NEW_ARR_D (ir_node *, current_ir_graph->obst, (new_irn_arity+1));
 
       /* set new predeseccors in array */
       new_in[0] = NULL;
       new_irn_n = 1;
-      for (i = 1; i < old_irn_arity; i++) {
-    irn = get_irn_n(n, i);
-    if (!is_Bad(irn)) new_in[new_irn_n++] = irn;
+      for (i = 0; i < old_irn_arity; i++) {
+       irn = get_irn_n(n, i);
+       if (!is_Bad(irn)) {
+         new_in[new_irn_n] = irn;
+         is_backedge(n, i) ? set_backedge(n, new_irn_n-1) : set_not_backedge(n, new_irn_n-1);
+         new_irn_n++;
+       }
       }
+      //ARR_SETLEN(int, n->attr.block.backedge, new_irn_arity);
+      ARR_SHRINKLEN(n->attr.block.backedge, new_irn_arity);
       n->in = new_in;
+
     } /* ir node has bad predecessors */
 
   } /* Block is not relinked */
@@ -535,7 +621,7 @@ static void relink_bad_predecessors(ir_node *n, void *env) {
   if (get_irn_op(n) == op_Phi) {
 
     /* Relink predeseccors of phi's block */
-    block = get_nodes_Block(n);
+    block = get_nodes_block(n);
     if (get_irn_link(block) == NULL)
       relink_bad_block_predecessors(block, env);
 
@@ -545,18 +631,23 @@ static void relink_bad_predecessors(ir_node *n, void *env) {
     /* Relink Phi predeseccors if count of predeseccors changed */
     if (old_irn_arity != ARR_LEN(get_irn_in(block))) {
       /* set new predeseccors in array
-     n->in[0] remains the same block */
+        n->in[0] remains the same block */
       new_irn_arity = 1;
       for(i = 1; i < old_irn_arity; i++)
-    if (!is_Bad((ir_node *)old_in[i])) n->in[new_irn_arity++] = n->in[i];
+       if (!is_Bad((ir_node *)old_in[i])) {
+         n->in[new_irn_arity] = n->in[i];
+         is_backedge(n, i) ? set_backedge(n, new_irn_arity) : set_not_backedge(n, new_irn_arity);
+         new_irn_arity++;
+       }
 
       ARR_SETLEN(ir_node *, n->in, new_irn_arity);
+      ARR_SETLEN(int, n->attr.phi_backedge, new_irn_arity);
     }
 
   } /* n is a Phi node */
 }
 
-/**
+/*
  * Removes Bad Bad predecesors from Blocks and the corresponding
  * inputs to Phi nodes as in dead_node_elimination but without
  * copying the graph.
@@ -614,13 +705,12 @@ static void find_addr(ir_node *node, void *env)
  * - call with compound arguments
  * - graphs that take the address of a parameter
  *
- * check these condition here
+ * check these conditions here
  */
 static int can_inline(ir_node *call, ir_graph *called_graph)
 {
   type *call_type = get_Call_type(call);
   int params, ress, i, res;
-
   assert(is_method_type(call_type));
 
   params = get_method_n_params(call_type);
@@ -661,9 +751,15 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
   type *called_frame;
   irg_inline_property prop = get_irg_inline_property(called_graph);
 
-  if ( (prop != irg_inline_forced) && (!get_opt_optimize() || !get_opt_inline() ||
-      (prop == irg_inline_forbidden))) return 0;
+  if ( (prop != irg_inline_forced) &&
+       (!get_opt_optimize() || !get_opt_inline() || (prop == irg_inline_forbidden))) return 0;
+
+  /* Do not inline variadic functions. */
+  if (get_method_variadicity(get_entity_type(get_irg_entity(called_graph))) == variadicity_variadic)
+    return 0;
 
+  assert(get_method_n_params(get_entity_type(get_irg_entity(called_graph))) ==
+         get_method_n_params(get_Call_type(call)));
 
   /*
    * currently, we cannot inline two cases:
@@ -679,16 +775,18 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
 
   /* Handle graph state */
   assert(get_irg_phase_state(current_ir_graph) != phase_building);
-  assert(get_irg_pinned(current_ir_graph) == pinned);
-  assert(get_irg_pinned(called_graph) == pinned);
+  assert(get_irg_pinned(current_ir_graph) == op_pin_state_pinned);
+  assert(get_irg_pinned(called_graph) == op_pin_state_pinned);
   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
     set_irg_outs_inconsistent(current_ir_graph);
+  set_irg_loopinfo_inconsistent(current_ir_graph);
+  set_irg_callee_info_state(current_ir_graph, irg_callee_info_inconsistent);
 
   /* -- Check preconditions -- */
   assert(get_irn_op(call) == op_Call);
   /* @@@ does not work for InterfaceIII.java after cgana
-     assert(get_Call_type(call) == get_entity_type(get_irg_ent(called_graph)));
-     assert(smaller_type(get_entity_type(get_irg_ent(called_graph)),
+     assert(get_Call_type(call) == get_entity_type(get_irg_entity(called_graph)));
+     assert(smaller_type(get_entity_type(get_irg_entity(called_graph)),
      get_Call_type(call)));
   */
   assert(get_type_tpop(get_Call_type(call)) == type_method);
@@ -702,9 +800,10 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
 
   /* -- Decide how to handle exception control flow: Is there a handler
      for the Call node, or do we branch directly to End on an exception?
-     exc_handling: 0 There is a handler.
-                   1 Branches to End.
-           2 Exception handling not represented in Firm. -- */
+     exc_handling:
+     0 There is a handler.
+     1 Branches to End.
+     2 Exception handling not represented in Firm. -- */
   {
     ir_node *proj, *Mproj = NULL, *Xproj = NULL;
     for (proj = (ir_node *)get_irn_link(call); proj; proj = (ir_node *)get_irn_link(proj)) {
@@ -719,10 +818,10 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
 
 
   /* --
-      the procedure and later replaces the Start node of the called graph.
-      Post_call is the old Call node and collects the results of the called
-      graph. Both will end up being a tuple.  -- */
-  post_bl = get_nodes_Block(call);
+     the procedure and later replaces the Start node of the called graph.
+     Post_call is the old Call node and collects the results of the called
+     graph. Both will end up being a tuple.  -- */
+  post_bl = get_nodes_block(call);
   set_irg_current_block(current_ir_graph, post_bl);
   /* XxMxPxP of Start + parameter of Call */
   in[pn_Start_X_initial_exec] = new_Jmp();
@@ -735,8 +834,8 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
   post_call = call;
 
   /* --
-      The new block gets the ins of the old block, pre_call and all its
-      predecessors and all Phi nodes. -- */
+     The new block gets the ins of the old block, pre_call and all its
+     predecessors and all Phi nodes. -- */
   part_block(pre_call);
 
   /* -- Prepare state for dead node elimination -- */
@@ -752,12 +851,11 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
      Further mark these nodes so that they are not visited by the
      copying. */
   set_irn_link(get_irg_start(called_graph), pre_call);
-  set_irn_visited(get_irg_start(called_graph),
-          get_irg_visited(current_ir_graph));
-  set_irn_link(get_irg_start_block(called_graph),
-           get_nodes_Block(pre_call));
-  set_irn_visited(get_irg_start_block(called_graph),
-          get_irg_visited(current_ir_graph));
+  set_irn_visited(get_irg_start(called_graph), get_irg_visited(current_ir_graph));
+  set_irn_link(get_irg_start_block(called_graph), get_nodes_block(pre_call));
+  set_irn_visited(get_irg_start_block(called_graph), get_irg_visited(current_ir_graph));
+  set_irn_link(get_irg_bad(called_graph), get_irg_bad(current_ir_graph));
+  set_irn_visited(get_irg_bad(called_graph), get_irg_visited(current_ir_graph));
 
   /* Initialize for compaction of in arrays */
   inc_irg_block_visited(current_ir_graph);
@@ -782,7 +880,7 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
      entities. */
   /* @@@ endless loops are not copied!! -- they should be, I think... */
   irg_walk(get_irg_end(called_graph), copy_node_inline, copy_preds,
-       get_irg_frame_type(called_graph));
+           get_irg_frame_type(called_graph));
 
   /* Repair called_graph */
   set_irg_visited(called_graph, get_irg_visited(current_ir_graph));
@@ -792,12 +890,12 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
   /* -- Merge the end of the inlined procedure with the call site -- */
   /* We will turn the old Call node into a Tuple with the following
      predecessors:
-       -1:  Block of Tuple.
-       0: Phi of all Memories of Return statements.
-       1: Jmp from new Block that merges the control flow from all exception
-      predecessors of the old end block.
-       2: Tuple of all arguments.
-       3: Phi of Exception memories.
+     -1:  Block of Tuple.
+     0: Phi of all Memories of Return statements.
+     1: Jmp from new Block that merges the control flow from all exception
+     predecessors of the old end block.
+     2: Tuple of all arguments.
+     3: Phi of Exception memories.
      In case the old Call directly branches to End on an exception we don't
      need the block merging all exceptions nor the Phi of the exception
      memories.
@@ -809,8 +907,8 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
   arity = get_irn_arity(end_bl);    /* arity = n_exc + n_ret  */
   n_res = get_method_n_ress(get_Call_type(call));
 
-  res_pred = (ir_node **) malloc (n_res * sizeof (ir_node *));
-  cf_pred =  (ir_node **) malloc (arity * sizeof (ir_node *));
+  res_pred = (ir_node **) xmalloc (n_res * sizeof (ir_node *));
+  cf_pred =  (ir_node **) xmalloc (arity * sizeof (ir_node *));
 
   set_irg_current_block(current_ir_graph, post_bl); /* just to make sure */
 
@@ -828,7 +926,7 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
     ir_node *ret;
     ret = get_irn_n(end_bl, i);
     if (get_irn_op(ret) == op_Return) {
-      cf_pred[n_ret] = new_r_Jmp(current_ir_graph, get_nodes_Block(ret));
+      cf_pred[n_ret] = new_r_Jmp(current_ir_graph, get_nodes_block(ret));
       n_ret++;
     }
   }
@@ -849,7 +947,7 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
   phi = new_Phi(n_ret, cf_pred, mode_M);
   set_Tuple_pred(call, pn_Call_M_regular, phi);
   /* Conserve Phi-list for further inlinings -- but might be optimized */
-  if (get_nodes_Block(phi) == post_bl) {
+  if (get_nodes_block(phi) == post_bl) {
     set_irn_link(phi, get_irn_link(post_bl));
     set_irn_link(post_bl, phi);
   }
@@ -858,18 +956,21 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
     for (j = 0; j < n_res; j++) {
       n_ret = 0;
       for (i = 0; i < arity; i++) {
-       ret = get_irn_n(end_bl, i);
-       if (get_irn_op(ret) == op_Return) {
-         cf_pred[n_ret] = get_Return_res(ret, j);
-         n_ret++;
-       }
+        ret = get_irn_n(end_bl, i);
+        if (get_irn_op(ret) == op_Return) {
+          cf_pred[n_ret] = get_Return_res(ret, j);
+          n_ret++;
+        }
       }
-      phi = new_Phi(n_ret, cf_pred, get_irn_mode(cf_pred[0]));
+      if (n_ret > 0)
+        phi = new_Phi(n_ret, cf_pred, get_irn_mode(cf_pred[0]));
+      else
+        phi = new_Bad();
       res_pred[j] = phi;
       /* Conserve Phi-list for further inlinings -- but might be optimized */
-      if (get_nodes_Block(phi) == post_bl) {
-       set_irn_link(phi, get_irn_link(post_bl));
-       set_irn_link(post_bl, phi);
+      if (get_nodes_block(phi) == post_bl) {
+        set_irn_link(phi, get_irn_link(post_bl));
+        set_irn_link(post_bl, phi);
       }
     }
     set_Tuple_pred(call, pn_Call_T_result, new_Tuple(n_res, res_pred));
@@ -892,8 +993,8 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
       ir_node *ret;
       ret = get_irn_n(end_bl, i);
       if (is_fragile_op(skip_Proj(ret)) || (get_irn_op(skip_Proj(ret)) == op_Raise)) {
-    cf_pred[n_exc] = ret;
-    n_exc++;
+        cf_pred[n_exc] = ret;
+        n_exc++;
       }
     }
     if (n_exc > 0) {
@@ -902,19 +1003,19 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
       /* The Phi for the memories with the exception objects */
       n_exc = 0;
       for (i = 0; i < arity; i++) {
-    ir_node *ret;
-    ret = skip_Proj(get_irn_n(end_bl, i));
-    if (get_irn_op(ret) == op_Call) {
-      cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 3);
-      n_exc++;
-    } else if (is_fragile_op(ret)) {
-    /* We rely that all cfops have the memory output at the same position. */
-      cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 0);
-      n_exc++;
-    } else if (get_irn_op(ret) == op_Raise) {
-      cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_Block(ret), ret, mode_M, 1);
-      n_exc++;
-    }
+        ir_node *ret;
+        ret = skip_Proj(get_irn_n(end_bl, i));
+        if (get_irn_op(ret) == op_Call) {
+          cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_block(ret), ret, mode_M, 3);
+          n_exc++;
+        } else if (is_fragile_op(ret)) {
+          /* We rely that all cfops have the memory output at the same position. */
+          cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_block(ret), ret, mode_M, 0);
+          n_exc++;
+        } else if (get_irn_op(ret) == op_Raise) {
+          cf_pred[n_exc] = new_r_Proj(current_ir_graph, get_nodes_block(ret), ret, mode_M, 1);
+          n_exc++;
+        }
       }
       set_Tuple_pred(call, pn_Call_M_except, new_Phi(n_exc, cf_pred, mode_M));
     } else {
@@ -938,7 +1039,7 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
     }
     main_end_bl = get_irg_end_block(current_ir_graph);
     main_end_bl_arity = get_irn_arity(main_end_bl);
-    end_preds =  (ir_node **) malloc ((n_exc + main_end_bl_arity) * sizeof (ir_node *));
+    end_preds =  (ir_node **) xmalloc ((n_exc + main_end_bl_arity) * sizeof (ir_node *));
 
     for (i = 0; i < main_end_bl_arity; ++i)
       end_preds[i] = get_irn_n(main_end_bl, i);
@@ -968,27 +1069,27 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
     for (i = 0; i < get_Block_n_cfgpreds(end_bl); i++) {
       cf_op = get_Block_cfgpred(end_bl, i);
       if (get_irn_op(cf_op) == op_Proj) {
-    cf_op = get_Proj_pred(cf_op);
-    if ((get_irn_op(cf_op) == op_Tuple) && (cf_op == call)) {
-      /*  There are unoptimized tuples from inlineing before when no exc */
-      assert(get_Proj_proj(get_Block_cfgpred(end_bl, i)) == pn_Call_X_except);
-      cf_op = get_Tuple_pred(cf_op, pn_Call_X_except);
-      assert(get_irn_op(cf_op) == op_Jmp);
-      break;
-    }
+        cf_op = get_Proj_pred(cf_op);
+        if ((get_irn_op(cf_op) == op_Tuple) && (cf_op == call)) {
+          /*  There are unoptimized tuples from inlineing before when no exc */
+          assert(get_Proj_proj(get_Block_cfgpred(end_bl, i)) == pn_Call_X_except);
+          cf_op = get_Tuple_pred(cf_op, pn_Call_X_except);
+          assert(get_irn_op(cf_op) == op_Jmp);
+          break;
+        }
       }
     }
     /* repair */
     if (i < get_Block_n_cfgpreds(end_bl)) {
-      bl = get_nodes_Block(cf_op);
+      bl = get_nodes_block(cf_op);
       arity = get_Block_n_cfgpreds(end_bl) + get_Block_n_cfgpreds(bl) - 1;
-      cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
+      cf_pred = (ir_node **) xmalloc (arity * sizeof (ir_node *));
       for (j = 0; j < i; j++)
-    cf_pred[j] = get_Block_cfgpred(end_bl, j);
+        cf_pred[j] = get_Block_cfgpred(end_bl, j);
       for (j = j; j < i + get_Block_n_cfgpreds(bl); j++)
-    cf_pred[j] = get_Block_cfgpred(bl, j-i);
+        cf_pred[j] = get_Block_cfgpred(bl, j-i);
       for (j = j; j < arity; j++)
-    cf_pred[j] = get_Block_cfgpred(end_bl, j-get_Block_n_cfgpreds(bl) +1);
+        cf_pred[j] = get_Block_cfgpred(end_bl, j-get_Block_n_cfgpreds(bl) +1);
       set_irn_in(end_bl, arity, cf_pred);
       free(cf_pred);
       /*  Remove the exception pred from post-call Tuple. */
@@ -1025,35 +1126,29 @@ typedef struct _inline_env_t {
  */
 static ir_graph *get_call_called_irg(ir_node *call) {
   ir_node *addr;
-  tarval *tv;
   ir_graph *called_irg = NULL;
 
   assert(get_irn_op(call) == op_Call);
 
   addr = get_Call_ptr(call);
-  if (get_irn_op(addr) == op_Const) {
-    /* Check whether the constant is the pointer to a compiled entity. */
-    tv = get_Const_tarval(addr);
-    if (tarval_to_entity(tv))
-      called_irg = get_entity_irg(tarval_to_entity(tv));
+  if ((get_irn_op(addr) == op_SymConst) && (get_SymConst_kind (addr) == symconst_addr_ent)) {
+    called_irg = get_entity_irg(get_SymConst_entity(addr));
   }
+
   return called_irg;
 }
 
 static void collect_calls(ir_node *call, void *env) {
-  inline_env_t *ienv = env;
   ir_node *addr;
-  tarval *tv;
-  ir_graph *called_irg;
 
   if (get_irn_op(call) != op_Call) return;
 
   addr = get_Call_ptr(call);
-  if (get_irn_op(addr) == op_Const) {
-    /* Check whether the constant is the pointer to a compiled entity. */
-    tv = get_Const_tarval(addr);
-    if (tarval_to_entity(tv)) {
-      called_irg = get_entity_irg(tarval_to_entity(tv));
+
+  if (get_irn_op(addr) == op_SymConst) {
+    if (get_SymConst_kind(addr) == symconst_addr_ent) {
+      ir_graph *called_irg = get_entity_irg(get_SymConst_entity(addr));
+      inline_env_t *ienv = (inline_env_t *)env;
       if (called_irg && ienv->pos < MAX_INLINE) {
         /* The Call node calls a locally defined method.  Remember to inline. */
         ienv->calls[ienv->pos++] = call;
@@ -1073,14 +1168,14 @@ static void collect_calls(ir_node *call, void *env) {
 void inline_small_irgs(ir_graph *irg, int size) {
   int i;
   ir_graph *rem = current_ir_graph;
-  inline_env_t env;
+  inline_env_t env /* = {0, NULL}*/;
 
   if (!(get_opt_optimize() && get_opt_inline())) return;
 
   current_ir_graph = irg;
   /* Handle graph state */
   assert(get_irg_phase_state(current_ir_graph) != phase_building);
-  assert(get_irg_callee_info_state(current_ir_graph) == irg_callee_info_none);
+  free_callee_info(current_ir_graph);
 
   /* Find Call nodes to inline.
      (We can not inline during a walk of the graph, as inlineing the same
@@ -1094,10 +1189,8 @@ void inline_small_irgs(ir_graph *irg, int size) {
     /* There are calls to inline */
     collect_phiprojs(irg);
     for (i = 0; i < env.pos; i++) {
-      tarval *tv;
       ir_graph *callee;
-      tv = get_Const_tarval(get_Call_ptr(env.calls[i]));
-      callee = get_entity_irg(tarval_to_entity(tv));
+      callee = get_entity_irg(get_SymConst_entity(get_Call_ptr(env.calls[i])));
       if (((_obstack_memory_used(callee->obst) - obstack_room(callee->obst)) < size) ||
         (get_irg_inline_property(callee) == irg_inline_forced)) {
         inline_method(env.calls[i], callee);
@@ -1122,7 +1215,7 @@ typedef struct {
 } inline_irg_env;
 
 static inline_irg_env *new_inline_irg_env(void) {
-  inline_irg_env *env = malloc(sizeof(inline_irg_env));
+  inline_irg_env *env = xmalloc(sizeof(inline_irg_env));
   env->n_nodes = -2; /* uncount Start, End */
   env->n_nodes_orig = -2; /* uncount Start, End */
   env->call_nodes = eset_create();
@@ -1197,62 +1290,50 @@ void inline_leave_functions(int maxsize, int leavesize, int size) {
   for (i = 0; i < n_irgs; ++i) {
     current_ir_graph = get_irp_irg(i);
     assert(get_irg_phase_state(current_ir_graph) != phase_building);
-    assert(get_irg_callee_info_state(current_ir_graph) == irg_callee_info_none);
+    free_callee_info(current_ir_graph);
 
     irg_walk(get_irg_end(current_ir_graph), NULL, collect_calls2,
-         get_irg_link(current_ir_graph));
+             get_irg_link(current_ir_graph));
   }
 
-  /* and now inline.
-     Inline leaves recursively -- we might construct new leaves. */
-  /* int itercnt = 1; */
+  /* -- and now inline. -- */
+
+  /* Inline leaves recursively -- we might construct new leaves. */
   while (did_inline) {
-    /* printf("iteration %d\n", itercnt++); */
     did_inline = 0;
+
     for (i = 0; i < n_irgs; ++i) {
       ir_node *call;
-      eset *walkset;
       int phiproj_computed = 0;
 
       current_ir_graph = get_irp_irg(i);
       env = (inline_irg_env *)get_irg_link(current_ir_graph);
 
-      /* we can not walk and change a set, nor remove from it.
-      So recompute.*/
-      walkset = env->call_nodes;
-      env->call_nodes = eset_create();
-      for (call = eset_first(walkset); call; call = eset_next(walkset)) {
-        inline_irg_env *callee_env;
+      for (call = eset_first(env->call_nodes); call; call = eset_next(env->call_nodes)) {
+        if (get_irn_op(call) == op_Tuple) continue;   /* We already inlined. */
         ir_graph *callee = get_call_called_irg(call);
 
-        if (env->n_nodes > maxsize) break;
-        if (callee &&
-        ((is_leave(callee) && is_smaller(callee, leavesize)) ||
-         (get_irg_inline_property(callee) == irg_inline_forced))) {
+        if (env->n_nodes > maxsize) continue; // break;
+
+        if (callee && (is_leave(callee) && is_smaller(callee, leavesize))) {
           if (!phiproj_computed) {
             phiproj_computed = 1;
             collect_phiprojs(current_ir_graph);
           }
-          callee_env = (inline_irg_env *)get_irg_link(callee);
-/*         printf(" %s: Inlineing %s.\n", get_entity_name(get_irg_entity(current_ir_graph)), */
-/*         get_entity_name(get_irg_entity(callee))); */
-          if (inline_method(call, callee)) {
-            did_inline = 1;
-           env->n_call_nodes--;
-           eset_insert_all(env->call_nodes, callee_env->call_nodes);
-           env->n_call_nodes += callee_env->n_call_nodes;
-           env->n_nodes += callee_env->n_nodes;
-           callee_env->n_callers--;
-         }
-        } else {
-          eset_insert(env->call_nodes, call);
+          did_inline = inline_method(call, callee);
+
+          if (did_inline) {
+            /* Do some statistics */
+            inline_irg_env *callee_env = (inline_irg_env *)get_irg_link(callee);
+            env->n_call_nodes --;
+            env->n_nodes += callee_env->n_nodes;
+            callee_env->n_callers--;
+          }
         }
       }
-      eset_destroy(walkset);
     }
   }
 
-  /* printf("Non leaves\n"); */
   /* inline other small functions. */
   for (i = 0; i < n_irgs; ++i) {
     ir_node *call;
@@ -1267,26 +1348,24 @@ void inline_leave_functions(int maxsize, int leavesize, int size) {
     walkset = env->call_nodes;
     env->call_nodes = eset_create();
     for (call = eset_first(walkset); call; call = eset_next(walkset)) {
-      inline_irg_env *callee_env;
+      if (get_irn_op(call) == op_Tuple) continue;   /* We already inlined. */
       ir_graph *callee = get_call_called_irg(call);
 
-      if (env->n_nodes > maxsize) break;
-      if (callee && is_smaller(callee, size)) {
+      if (callee &&
+          ((is_smaller(callee, size) && (env->n_nodes < maxsize)) ||    /* small function */
+           (get_irg_inline_property(callee) == irg_inline_forced))) {
         if (!phiproj_computed) {
             phiproj_computed = 1;
             collect_phiprojs(current_ir_graph);
         }
-        callee_env = (inline_irg_env *)get_irg_link(callee);
-/*       printf(" %s: Inlineing %s.\n", get_entity_name(get_irg_entity(current_ir_graph)), */
-/*       get_entity_name(get_irg_entity(callee))); */
         if (inline_method(call, callee)) {
-         did_inline = 1;
-         env->n_call_nodes--;
-         eset_insert_all(env->call_nodes, callee_env->call_nodes);
-         env->n_call_nodes += callee_env->n_call_nodes;
-         env->n_nodes += callee_env->n_nodes;
-         callee_env->n_callers--;
-       }
+          inline_irg_env *callee_env = (inline_irg_env *)get_irg_link(callee);
+          env->n_call_nodes--;
+          eset_insert_all(env->call_nodes, callee_env->call_nodes);  /* @@@ ??? This are the wrong nodes !? Not the copied ones. */
+          env->n_call_nodes += callee_env->n_call_nodes;
+          env->n_nodes += callee_env->n_nodes;
+          callee_env->n_callers--;
+        }
       } else {
         eset_insert(env->call_nodes, call);
       }
@@ -1299,11 +1378,11 @@ void inline_leave_functions(int maxsize, int leavesize, int size) {
 #if 0
     env = (inline_irg_env *)get_irg_link(current_ir_graph);
     if ((env->n_call_nodes_orig != env->n_call_nodes) ||
-    (env->n_callers_orig != env->n_callers))
+        (env->n_callers_orig != env->n_callers))
       printf("Nodes:%3d ->%3d, calls:%3d ->%3d, callers:%3d ->%3d, -- %s\n",
-         env->n_nodes_orig, env->n_nodes, env->n_call_nodes_orig, env->n_call_nodes,
-         env->n_callers_orig, env->n_callers,
-         get_entity_name(get_irg_entity(current_ir_graph)));
+             env->n_nodes_orig, env->n_nodes, env->n_call_nodes_orig, env->n_call_nodes,
+             env->n_callers_orig, env->n_callers,
+             get_entity_name(get_irg_entity(current_ir_graph)));
 #endif
     free_inline_irg_env((inline_irg_env *)get_irg_link(current_ir_graph));
   }
@@ -1330,16 +1409,17 @@ place_floats_early(ir_node *n, pdeq *worklist)
   mark_irn_visited(n);
 
   /* Place floating nodes. */
-  if (get_op_pinned(get_irn_op(n)) == floats) {
-    int depth = 0;
-    ir_node *b = new_Bad();   /* The block to place this node in */
+  if (get_irn_pinned(n) == op_pin_state_floats) {
+    int depth         = 0;
+    ir_node *b        = new_Bad();   /* The block to place this node in */
+    int bad_recursion = is_Bad(get_nodes_block(n));
 
     assert(get_irn_op(n) != op_Block);
 
     if ((get_irn_op(n) == op_Const) ||
-    (get_irn_op(n) == op_SymConst) ||
-    (is_Bad(n)) ||
-    (get_irn_op(n) == op_Unknown)) {
+        (get_irn_op(n) == op_SymConst) ||
+        (is_Bad(n)) ||
+        (get_irn_op(n) == op_Unknown)) {
       /* These nodes will not be placed by the loop below. */
       b = get_irg_start_block(current_ir_graph);
       depth = 1;
@@ -1350,27 +1430,36 @@ place_floats_early(ir_node *n, pdeq *worklist)
     for (i = 0; i < irn_arity; i++) {
       ir_node *dep = get_irn_n(n, i);
       ir_node *dep_block;
-      if ((irn_not_visited(dep)) &&
-      (get_op_pinned(get_irn_op(dep)) == floats)) {
-       place_floats_early(dep, worklist);
+
+      if ((irn_not_visited(dep))
+         && (get_irn_pinned(dep) == op_pin_state_floats)) {
+        place_floats_early(dep, worklist);
       }
-      /* Because all loops contain at least one pinned node, now all
-         our inputs are either pinned or place_early has already
+
+      /*
+       * A node in the Bad block must stay in the bad block,
+       * so don't compute a new block for it.
+       */
+      if (bad_recursion)
+        continue;
+
+      /* Because all loops contain at least one op_pin_state_pinned node, now all
+         our inputs are either op_pin_state_pinned or place_early has already
          been finished on them.  We do not have any unfinished inputs!  */
-      dep_block = get_nodes_Block(dep);
+      dep_block = get_nodes_block(dep);
       if ((!is_Bad(dep_block)) &&
-         (get_Block_dom_depth(dep_block) > depth)) {
-       b = dep_block;
-       depth = get_Block_dom_depth(dep_block);
+          (get_Block_dom_depth(dep_block) > depth)) {
+        b = dep_block;
+        depth = get_Block_dom_depth(dep_block);
       }
       /* Avoid that the node is placed in the Start block */
-      if ((depth == 1) && (get_Block_dom_depth(get_nodes_Block(n)) > 1)) {
-       b = get_Block_cfg_out(get_irg_start_block(current_ir_graph), 0);
-       assert(b != get_irg_start_block(current_ir_graph));
-       depth = 2;
+      if ((depth == 1) && (get_Block_dom_depth(get_nodes_block(n)) > 1)) {
+        b = get_Block_cfg_out(get_irg_start_block(current_ir_graph), 0);
+        assert(b != get_irg_start_block(current_ir_graph));
+        depth = 2;
       }
     }
-    set_nodes_Block(n, b);
+    set_nodes_block(n, b);
   }
 
   /* Add predecessors of non floating nodes on worklist. */
@@ -1386,11 +1475,11 @@ place_floats_early(ir_node *n, pdeq *worklist)
 
 /**
  * Floating nodes form subgraphs that begin at nodes as Const, Load,
- * Start, Call and end at pinned nodes as Store, Call.  Place_early
+ * Start, Call and that end at op_pin_state_pinned nodes as Store, Call.  Place_early
  * places all floating nodes reachable from its argument through floating
- * nodes and adds all beginnings at pinned nodes to the worklist.
+ * nodes and adds all beginnings at op_pin_state_pinned nodes to the worklist.
  */
-static INLINE void place_early(pdeqworklist) {
+static INLINE void place_early(pdeq *worklist) {
   assert(worklist);
   inc_irg_visited(current_ir_graph);
 
@@ -1404,11 +1493,29 @@ static INLINE void place_early(pdeq* worklist) {
   }
 
   set_irg_outs_inconsistent(current_ir_graph);
-  current_ir_graph->pinned = pinned;
+  current_ir_graph->op_pin_state_pinned = op_pin_state_pinned;
 }
 
+/** Compute the deepest common ancestor of block and dca. */
+static ir_node *calc_dca(ir_node *dca, ir_node *block)
+{
+  assert(block);
+  if (!dca) return block;
+  while (get_Block_dom_depth(block) > get_Block_dom_depth(dca))
+    block = get_Block_idom(block);
+  while (get_Block_dom_depth(dca) > get_Block_dom_depth(block)) {
+    dca = get_Block_idom(dca);
+  }
+  while (block != dca)
+    { block = get_Block_idom(block); dca = get_Block_idom(dca); }
+
+  return dca;
+}
 
-/** deepest common dominance ancestor of DCA and CONSUMER of PRODUCER. */
+/** Deepest common dominance ancestor of DCA and CONSUMER of PRODUCER.
+ * I.e., DCA is the block where we might place PRODUCER.
+ * A data flow edge points from producer to consumer.
+ */
 static ir_node *
 consumer_dom_dca (ir_node *dca, ir_node *consumer, ir_node *producer)
 {
@@ -1420,29 +1527,23 @@ consumer_dom_dca (ir_node *dca, ir_node *consumer, ir_node *producer)
     /* our consumer is a Phi-node, the effective use is in all those
        blocks through which the Phi-node reaches producer */
     int i, irn_arity;
-    ir_node *phi_block = get_nodes_Block(consumer);
+    ir_node *phi_block = get_nodes_block(consumer);
     irn_arity = get_irn_arity(consumer);
+
     for (i = 0;  i < irn_arity; i++) {
       if (get_irn_n(consumer, i) == producer) {
-    block = get_nodes_Block(get_Block_cfgpred(phi_block, i));
+        ir_node *new_block = get_nodes_block(get_Block_cfgpred(phi_block, i));
+
+        block = calc_dca(block, new_block);
       }
     }
   } else {
     assert(is_no_Block(consumer));
-    block = get_nodes_Block(consumer);
+    block = get_nodes_block(consumer);
   }
 
   /* Compute the deepest common ancestor of block and dca. */
-  assert(block);
-  if (!dca) return block;
-  while (get_Block_dom_depth(block) > get_Block_dom_depth(dca))
-    block = get_Block_idom(block);
-  while (get_Block_dom_depth(dca) > get_Block_dom_depth(block))
-    dca = get_Block_idom(dca);
-  while (block != dca)
-    { block = get_Block_idom(block); dca = get_Block_idom(dca); }
-
-  return dca;
+  return calc_dca(dca, block);
 }
 
 static INLINE int get_irn_loop_depth(ir_node *n) {
@@ -1463,23 +1564,23 @@ move_out_of_loops (ir_node *n, ir_node *early)
   /* Find the region deepest in the dominator tree dominating
      dca with the least loop nesting depth, but still dominated
      by our early placement. */
-  dca = get_nodes_Block(n);
+  dca = get_nodes_block(n);
   best = dca;
   while (dca != early) {
     dca = get_Block_idom(dca);
-    if (!dca) break; /* should we put assert(dca)? */
+    if (!dca || is_Bad(dca)) break; /* may be Bad if not reachable from Start */
     if (get_irn_loop_depth(dca) < get_irn_loop_depth(best)) {
       best = dca;
     }
   }
-  if (best != get_nodes_Block(n)) {
+  if (best != get_nodes_block(n)) {
     /* debug output
     printf("Moving out of loop: "); DDMN(n);
     printf(" Outermost block: "); DDMN(early);
     printf(" Best block: "); DDMN(best);
-    printf(" Innermost block: "); DDMN(get_nodes_Block(n));
+    printf(" Innermost block: "); DDMN(get_nodes_block(n));
     */
-    set_nodes_Block(n, best);
+    set_nodes_block(n, best);
   }
 }
 
@@ -1499,62 +1600,78 @@ place_floats_late(ir_node *n, pdeq *worklist)
 
   assert (irn_not_visited(n)); /* no multiple placement */
 
+  mark_irn_visited(n);
+
   /* no need to place block nodes, control nodes are already placed. */
   if ((get_irn_op(n) != op_Block) &&
       (!is_cfop(n)) &&
       (get_irn_mode(n) != mode_X)) {
     /* Remember the early placement of this block to move it
        out of loop no further than the early placement. */
-    early = get_nodes_Block(n);
+    early = get_nodes_block(n);
+
+    /* Do not move code not reachable from Start.  For
+     * these we could not compute dominator information. */
+    if (is_Bad(early) || get_Block_dom_depth(early) == -1)
+      return;
+
     /* Assure that our users are all placed, except the Phi-nodes.
        --- Each data flow cycle contains at least one Phi-node.  We
        have to break the `user has to be placed before the
        producer' dependence cycle and the Phi-nodes are the
        place to do so, because we need to base our placement on the
        final region of our users, which is OK with Phi-nodes, as they
-       are pinned, and they never have to be placed after a
+       are op_pin_state_pinned, and they never have to be placed after a
        producer of one of their inputs in the same block anyway. */
     for (i = 0; i < get_irn_n_outs(n); i++) {
       ir_node *succ = get_irn_out(n, i);
       if (irn_not_visited(succ) && (get_irn_op(succ) != op_Phi))
-    place_floats_late(succ, worklist);
+        place_floats_late(succ, worklist);
     }
 
     /* We have to determine the final block of this node... except for
        constants. */
-    if ((get_op_pinned(get_irn_op(n)) == floats) &&
-    (get_irn_op(n) != op_Const) &&
-    (get_irn_op(n) != op_SymConst)) {
+    if ((get_irn_pinned(n) == op_pin_state_floats) &&
+        (get_irn_op(n) != op_Const) &&
+        (get_irn_op(n) != op_SymConst)) {
       ir_node *dca = NULL;  /* deepest common ancestor in the
                    dominator tree of all nodes'
                    blocks depending on us; our final
                    placement has to dominate DCA. */
       for (i = 0; i < get_irn_n_outs(n); i++) {
-    dca = consumer_dom_dca (dca, get_irn_out(n, i), n);
+        ir_node *out = get_irn_out(n, i);
+        /* ignore if out is in dead code */
+        ir_node *outbl = get_nodes_block(out);
+        if (is_Bad(outbl) || get_Block_dom_depth(outbl) == -1)
+          continue;
+        dca = consumer_dom_dca (dca, out, n);
       }
-      set_nodes_Block(n, dca);
+      if (dca) {
+        set_nodes_block(n, dca);
 
-      move_out_of_loops (n, early);
+        move_out_of_loops (n, early);
+      }
+      /* else all outs are in dead code */
     }
   }
 
-  mark_irn_visited(n);
-
   /* Add predecessors of all non-floating nodes on list. (Those of floating
      nodes are placeded already and therefore are marked.)  */
   for (i = 0; i < get_irn_n_outs(n); i++) {
+    ir_node *succ = get_irn_out(n, i);
     if (irn_not_visited(get_irn_out(n, i))) {
-      pdeq_putr (worklist, get_irn_out(n, i));
+      pdeq_putr (worklist, succ);
     }
   }
 }
 
-static INLINE void place_late(pdeqworklist) {
+static INLINE void place_late(pdeq *worklist) {
   assert(worklist);
   inc_irg_visited(current_ir_graph);
 
   /* This fills the worklist initially. */
   place_floats_late(get_irg_start_block(current_ir_graph), worklist);
+
   /* And now empty the worklist again... */
   while (!pdeq_empty (worklist)) {
     ir_node *n = pdeq_getl (worklist);
@@ -1563,7 +1680,7 @@ static INLINE void place_late(pdeq* worklist) {
 }
 
 void place_code(ir_graph *irg) {
-  pdeqworklist;
+  pdeq *worklist;
   ir_graph *rem = current_ir_graph;
 
   current_ir_graph = irg;
@@ -1597,332 +1714,6 @@ void place_code(ir_graph *irg) {
   current_ir_graph = rem;
 }
 
-
-
-/********************************************************************/
-/* Control flow optimization.                                       */
-/* Removes Bad control flow predecessors and empty blocks.  A block */
-/* is empty if it contains only a Jmp node.                         */
-/* Blocks can only be removed if they are not needed for the        */
-/* semantics of Phi nodes.                                          */
-/********************************************************************/
-
-/**
- * Removes Tuples from Block control flow predecessors.
- * Optimizes blocks with equivalent_node().
- * Replaces n by Bad if n is unreachable control flow.
- */
-static void merge_blocks(ir_node *n, void *env) {
-  int i;
-  set_irn_link(n, NULL);
-
-  if (get_irn_op(n) == op_Block) {
-    /* Remove Tuples */
-    for (i = 0; i < get_Block_n_cfgpreds(n); i++)
-      /* GL @@@ : is this possible? if (get_opt_normalize()) -- added, all tests go through.
-       A different order of optimizations might cause problems. */
-      if (get_opt_normalize())
-       set_Block_cfgpred(n, i, skip_Tuple(get_Block_cfgpred(n, i)));
-  } else if (get_opt_optimize() && (get_irn_mode(n) == mode_X)) {
-    /* We will soon visit a block.  Optimize it before visiting! */
-    ir_node *b = get_nodes_Block(n);
-    ir_node *new_node = equivalent_node(b);
-    while (irn_not_visited(b) && (!is_Bad(new_node)) && (new_node != b)) {
-      /* We would have to run gigo if new is bad, so we
-     promote it directly below. */
-      assert(((b == new_node) ||
-          get_opt_control_flow_straightening() ||
-          get_opt_control_flow_weak_simplification()) &&
-         ("strange flag setting"));
-      exchange (b, new_node);
-      b = new_node;
-      new_node = equivalent_node(b);
-    }
-    /* GL @@@ get_opt_normalize hinzugefuegt, 5.5.2003 */
-    if (is_Bad(new_node) && get_opt_normalize()) exchange(n, new_Bad());
-  }
-}
-
-/**
- * Collects all Phi nodes in link list of Block.
- * Marks all blocks "block_visited" if they contain a node other
- * than Jmp.
- */
-static void collect_nodes(ir_node *n, void *env) {
-  if (is_no_Block(n)) {
-    ir_node *b = get_nodes_Block(n);
-
-    if ((get_irn_op(n) == op_Phi)) {
-      /* Collect Phi nodes to compact ins along with block's ins. */
-      set_irn_link(n, get_irn_link(b));
-      set_irn_link(b, n);
-    } else if (get_irn_op(n) != op_Jmp) {  /* Check for non empty block. */
-      mark_Block_block_visited(b);
-    }
-  }
-}
-
-/** Returns true if pred is predecessor of block. */
-static int is_pred_of(ir_node *pred, ir_node *b) {
-  int i;
-  for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
-    ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
-    if (b_pred == pred) return 1;
-  }
-  return 0;
-}
-
-static int test_whether_dispensable(ir_node *b, int pos) {
-  int i, j, n_preds = 1;
-  int dispensable = 1;
-  ir_node *cfop = get_Block_cfgpred(b, pos);
-  ir_node *pred = get_nodes_Block(cfop);
-
-  if (get_Block_block_visited(pred) + 1
-      < get_irg_block_visited(current_ir_graph)) {
-    if (!get_opt_optimize() || !get_opt_control_flow_strong_simplification()) {
-      /* Mark block so that is will not be removed. */
-      set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
-      return 1;
-    }
-    /* Seems to be empty. */
-    if (!get_irn_link(b)) {
-      /* There are no Phi nodes ==> dispensable. */
-      n_preds = get_Block_n_cfgpreds(pred);
-    } else {
-      /* b's pred blocks and pred's pred blocks must be pairwise disjunct.
-     Work preds < pos as if they were already removed. */
-      for (i = 0; i < pos; i++) {
-       ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
-       if (get_Block_block_visited(b_pred) + 1
-           < get_irg_block_visited(current_ir_graph)) {
-         for (j = 0; j < get_Block_n_cfgpreds(b_pred); j++) {
-           ir_node *b_pred_pred = get_nodes_Block(get_Block_cfgpred(b_pred, j));
-           if (is_pred_of(b_pred_pred, pred)) dispensable = 0;
-         }
-       } else {
-         if (is_pred_of(b_pred, pred)) dispensable = 0;
-       }
-      }
-      for (i = pos +1; i < get_Block_n_cfgpreds(b); i++) {
-       ir_node *b_pred = get_nodes_Block(get_Block_cfgpred(b, i));
-       if (is_pred_of(b_pred, pred)) dispensable = 0;
-      }
-      if (!dispensable) {
-       set_Block_block_visited(pred, get_irg_block_visited(current_ir_graph)-1);
-       n_preds = 1;
-      } else {
-        n_preds = get_Block_n_cfgpreds(pred);
-      }
-    }
-  }
-
-  return n_preds;
-}
-
-static void optimize_blocks(ir_node *b, void *env) {
-  int i, j, k, max_preds, n_preds;
-  ir_node *pred, *phi;
-  ir_node **in;
-
-  /* Count the number of predecessor if this block is merged with pred blocks
-     that are empty. */
-  max_preds = 0;
-  for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
-    max_preds += test_whether_dispensable(b, i);
-  }
-  in = (ir_node **) malloc(max_preds * sizeof(ir_node *));
-
-/*-
-  printf(" working on "); DDMN(b);
-  for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
-    pred = get_nodes_Block(get_Block_cfgpred(b, i));
-    if (is_Bad(get_Block_cfgpred(b, i))) {
-      printf("  removing Bad %i\n ", i);
-    } else if (get_Block_block_visited(pred) +1
-           < get_irg_block_visited(current_ir_graph)) {
-      printf("  removing pred %i ", i); DDMN(pred);
-    } else { printf("  Nothing to do for "); DDMN(pred); }
-  }
-  * end Debug output -*/
-
-  /*- Fix the Phi nodes -*/
-  phi = get_irn_link(b);
-  while (phi) {
-    assert(get_irn_op(phi) == op_Phi);
-    /* Find the new predecessors for the Phi */
-    n_preds = 0;
-    for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
-      pred = get_nodes_Block(get_Block_cfgpred(b, i));
-      if (is_Bad(get_Block_cfgpred(b, i))) {
-       /* Do nothing */
-      } else if (get_Block_block_visited(pred) +1
-         < get_irg_block_visited(current_ir_graph)) {
-       /* It's an empty block and not yet visited. */
-       ir_node *phi_pred = get_Phi_pred(phi, i);
-       for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
-         if (get_nodes_Block(phi_pred) == pred) {
-           assert(get_irn_op(phi_pred) == op_Phi);  /* Block is empty!! */
-           in[n_preds] = get_Phi_pred(phi_pred, j);
-         } else {
-           in[n_preds] = phi_pred;
-         }
-         n_preds++;
-       }
-       /* The Phi_pred node is replaced now if it is a Phi.
-          In Schleifen kann offenbar der entfernte Phi Knoten legal verwendet werden.
-          Daher muss der Phiknoten durch den neuen ersetzt werden.
-          Weiter muss der alte Phiknoten entfernt werden (durch ersetzen oder
-          durch einen Bad) damit er aus den keep_alive verschwinden kann.
-          Man sollte also, falls keine Schleife vorliegt, exchange mit new_Bad
-          aufrufen.  */
-       if (get_nodes_Block(phi_pred) == pred) {
-         /* remove the Phi as it might be kept alive. Further there
-            might be other users. */
-         exchange(phi_pred, phi);  /* geht, ist aber doch semantisch falsch! Warum?? */
-       }
-      } else {
-       in[n_preds] = get_Phi_pred(phi, i);
-       n_preds ++;
-      }
-    }
-    /* Fix the node */
-    set_irn_in(phi, n_preds, in);
-
-    phi = get_irn_link(phi);
-  }
-
-/*-
-      This happens only if merge between loop backedge and single loop entry. -*/
-  for (k = 0; k < get_Block_n_cfgpreds(b); k++) {
-    pred = get_nodes_Block(get_Block_cfgpred(b, k));
-    if (get_Block_block_visited(pred)+1 < get_irg_block_visited(current_ir_graph)) {
-      phi = get_irn_link(pred);
-      while (phi) {
-       if (get_irn_op(phi) == op_Phi) {
-         set_nodes_Block(phi, b);
-
-         n_preds = 0;
-         for (i = 0; i < k; i++) {
-           pred = get_nodes_Block(get_Block_cfgpred(b, i));
-           if (is_Bad(get_Block_cfgpred(b, i))) {
-             /* Do nothing */
-           } else if (get_Block_block_visited(pred) +1
-                  < get_irg_block_visited(current_ir_graph)) {
-             /* It's an empty block and not yet visited. */
-             for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
-           /* @@@ Hier brauche ich Schleifeninformation!!! Kontrollflusskante
-              muss Rueckwaertskante sein! (An allen vier in[n_preds] = phi
-              Anweisungen.) Trotzdem tuts bisher!! */
-           in[n_preds] = phi;
-           n_preds++;
-             }
-           } else {
-             in[n_preds] = phi;
-             n_preds++;
-           }
-         }
-         for (i = 0; i < get_Phi_n_preds(phi); i++) {
-           in[n_preds] = get_Phi_pred(phi, i);
-           n_preds++;
-         }
-         for (i = k+1; i < get_Block_n_cfgpreds(b); i++) {
-           pred = get_nodes_Block(get_Block_cfgpred(b, i));
-           if (is_Bad(get_Block_cfgpred(b, i))) {
-             /* Do nothing */
-           } else if (get_Block_block_visited(pred) +1
-                  < get_irg_block_visited(current_ir_graph)) {
-             /* It's an empty block and not yet visited. */
-             for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
-               in[n_preds] = phi;
-               n_preds++;
-             }
-           } else {
-             in[n_preds] = phi;
-             n_preds++;
-           }
-         }
-         set_irn_in(phi, n_preds, in);
-       }
-       phi = get_irn_link(phi);
-      }
-    }
-  }
-
-  /*- Fix the block -*/
-  n_preds = 0;
-  for (i = 0; i < get_Block_n_cfgpreds(b); i++) {
-    pred = get_nodes_Block(get_Block_cfgpred(b, i));
-    if (is_Bad(get_Block_cfgpred(b, i))) {
-      /* Do nothing */
-    } else if (get_Block_block_visited(pred) +1
-           < get_irg_block_visited(current_ir_graph)) {
-      /* It's an empty block and not yet visited. */
-      assert(get_Block_n_cfgpreds(b) > 1);
-                        /* Else it should be optimized by equivalent_node. */
-      for (j = 0; j < get_Block_n_cfgpreds(pred); j++) {
-       in[n_preds] = get_Block_cfgpred(pred, j);
-       n_preds++;
-      }
-      /* Remove block as it might be kept alive. */
-      exchange(pred, b/*new_Bad()*/);
-    } else {
-      in[n_preds] = get_Block_cfgpred(b, i);
-      n_preds ++;
-    }
-  }
-  set_irn_in(b, n_preds, in);
-  free(in);
-}
-
-void optimize_cf(ir_graph *irg) {
-  int i;
-  ir_node **in;
-  ir_node *end = get_irg_end(irg);
-  ir_graph *rem = current_ir_graph;
-  current_ir_graph = irg;
-
-  /* Handle graph state */
-  assert(get_irg_phase_state(irg) != phase_building);
-  if (get_irg_outs_state(current_ir_graph) == outs_consistent)
-    set_irg_outs_inconsistent(current_ir_graph);
-  if (get_irg_dom_state(current_ir_graph) == dom_consistent)
-    set_irg_dom_inconsistent(current_ir_graph);
-
-  /* Use block visited flag to mark non-empty blocks. */
-  inc_irg_block_visited(irg);
-  irg_walk(end, merge_blocks, collect_nodes, NULL);
-
-  /* Optimize the standard code. */
-  irg_block_walk(get_irg_end_block(irg), optimize_blocks, NULL, NULL);
-
-  /* Walk all keep alives, optimize them if block, add to new in-array
-     for end if useful. */
-  in = NEW_ARR_F (ir_node *, 1);
-  in[0] = get_nodes_Block(end);
-  inc_irg_visited(current_ir_graph);
-  for(i = 0; i < get_End_n_keepalives(end); i++) {
-    ir_node *ka = get_End_keepalive(end, i);
-    if (irn_not_visited(ka)) {
-      if ((get_irn_op(ka) == op_Block) && Block_not_block_visited(ka)) {
-       set_irg_block_visited(current_ir_graph,  /* Don't walk all the way to Start. */
-                     get_irg_block_visited(current_ir_graph)-1);
-       irg_block_walk(ka, optimize_blocks, NULL, NULL);
-       mark_irn_visited(ka);
-       ARR_APP1 (ir_node *, in, ka);
-      } else if (get_irn_op(ka) == op_Phi) {
-       mark_irn_visited(ka);
-       ARR_APP1 (ir_node *, in, ka);
-      }
-    }
-  }
-  /* DEL_ARR_F(end->in);   GL @@@ tut nicht ! */
-  end->in = in;
-
-  current_ir_graph = rem;
-}
-
-
 /**
  * Called by walker of remove_critical_cf_edges().
  *
@@ -1949,20 +1740,20 @@ static void walk_critical_cf_edges(ir_node *n, void *env) {
       pre = get_irn_n(n, i);
       /* Predecessor has multiple successors. Insert new flow edge */
       if ((NULL != pre) &&
-       (op_Proj == get_irn_op(pre)) &&
-       op_Raise != get_irn_op(skip_Proj(pre))) {
-
-       /* set predecessor array for new block */
-       in = NEW_ARR_D (ir_node *, current_ir_graph->obst, 1);
-       /* set predecessor of new block */
-       in[0] = pre;
-       block = new_Block(1, in);
-       /* insert new jmp node to new block */
-       switch_block(block);
-       jmp = new_Jmp();
-       switch_block(n);
-       /* set successor of new block */
-       set_irn_n(n, i, jmp);
+    (op_Proj == get_irn_op(pre)) &&
+    op_Raise != get_irn_op(skip_Proj(pre))) {
+
+    /* set predecessor array for new block */
+    in = NEW_ARR_D (ir_node *, current_ir_graph->obst, 1);
+    /* set predecessor of new block */
+    in[0] = pre;
+    block = new_Block(1, in);
+    /* insert new jmp node to new block */
+    set_cur_block(block);
+    jmp = new_Jmp();
+    set_cur_block(n);
+    /* set successor of new block */
+    set_irn_n(n, i, jmp);
 
       } /* predecessor has multiple successors */
     } /* for all predecessors */