Removed USE_FAST_PHI_CONSTRUCTION and USE_EXPLICIT_PHI_IN_STACK
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 27 Sep 2007 09:51:41 +0000 (09:51 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Thu, 27 Sep 2007 09:51:41 +0000 (09:51 +0000)
options: This code is neither used nor usefull in current Firm

Fixed handling of exceptional memory.

[r15935]

include/libfirm/irnode.h
ir/common/firm_common_t.h
ir/ir/ircons.c

index 6d8b2d4..1d321ff 100644 (file)
  */
 
 /**
- *   you can work on the graph without considering the different types
- *   of nodes, it's just a big graph.
+ * Some projection numbers must be always equal to support automatic phi construction
  */
+enum pn_generic {
+       pn_Generic_M_regular = 0,  /**< The memory result. */
+       pn_Generic_X_regular = 1,  /**< Execution result if no exception occurred. */
+       pn_Generic_X_except  = 2,  /**< The control flow result branching to the exception handler */
+       pn_Generic_other     = 3   /**< First free projection number */
+};
 
 /**
  *   Checks whether a pointer points to a ir node.
@@ -585,15 +590,15 @@ void       set_Sel_entity (ir_node *node, ir_entity *ent);
  * Projection numbers for result of Call node: use for Proj nodes!
  */
 typedef enum {
-       pn_Call_M_regular = 0,       /**< The memory result. */
-       pn_Call_X_regular = 1,       /**< The control flow result when no exception occurs. */
-       pn_Call_X_except  = 2,       /**< The control flow result branching to the exception handler. */
-       pn_Call_T_result  = 3,       /**< The tuple containing all (0, 1, 2, ...) results. */
-       pn_Call_M_except  = 4,       /**< The memory result in case the called method terminated with
-                                         an exception. */
-       pn_Call_P_value_res_base = 5,/**< A pointer to the memory region containing copied results
-                                         passed by value (for compound result types). */
-       pn_Call_max       = 6        /**< number of projections from a Call */
+       pn_Call_M_regular = pn_Generic_M_regular, /**< The memory result. */
+       pn_Call_X_regular = pn_Generic_X_regular, /**< The control flow result when no exception occurs. */
+       pn_Call_X_except  = pn_Generic_X_except,  /**< The control flow result branching to the exception handler. */
+       pn_Call_T_result  = pn_Generic_other,     /**< The tuple containing all (0, 1, 2, ...) results. */
+       pn_Call_M_except,                         /**< The memory result in case the called method terminated with
+                                                      an exception. */
+       pn_Call_P_value_res_base,                 /**< A pointer to the memory region containing copied results
+                                                      passed by value (for compound result types). */
+       pn_Call_max                               /**< number of projections from a Call */
 } pn_Call;   /* Projection numbers for Call. */
 #define pn_Call_M pn_Call_M_regular
 
@@ -698,11 +703,11 @@ void     set_Quot_resmode(ir_node *node, ir_mode *mode);
  * Projection numbers for Quot: use for Proj nodes!
  */
 typedef enum {
-       pn_Quot_M,           /**< Memory result. */
-       pn_Quot_X_regular,   /**< Execution result if no exception occurred. */
-       pn_Quot_X_except,    /**< Execution result if exception occurred. */
-       pn_Quot_res,         /**< Result of computation. */
-       pn_Quot_max          /**< number of projections from a Quot */
+       pn_Quot_M         = pn_Generic_M_regular, /**< Memory result. */
+       pn_Quot_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
+       pn_Quot_X_except  = pn_Generic_X_except,  /**< Execution result if exception occurred. */
+       pn_Quot_res       = pn_Generic_other,     /**< Result of computation. */
+       pn_Quot_max                               /**< number of projections from a Quot */
 } pn_Quot;  /* Projection numbers for Quot. */
 
 ir_node *get_DivMod_left(const ir_node *node);
@@ -718,12 +723,12 @@ void     set_DivMod_resmode(ir_node *node, ir_mode *mode);
  * Projection numbers for DivMod: use for Proj nodes!
  */
 typedef enum {
-       pn_DivMod_M,           /**< Memory result. */
-       pn_DivMod_X_regular,   /**< Execution result if no exception occurred. */
-       pn_DivMod_X_except,    /**< Execution result if exception occurred. */
-       pn_DivMod_res_div,     /**< Result of computation a / b. */
-       pn_DivMod_res_mod,     /**< Result of computation a % b. */
-       pn_DivMod_max          /**< number of projections from a DivMod */
+       pn_DivMod_M         = pn_Generic_M_regular, /**< Memory result. */
+       pn_DivMod_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
+       pn_DivMod_X_except  = pn_Generic_X_except,  /**< Execution result if exception occurred. */
+       pn_DivMod_res_div   = pn_Generic_other,     /**< Result of computation a / b. */
+       pn_DivMod_res_mod,                          /**< Result of computation a % b. */
+       pn_DivMod_max                               /**< number of projections from a DivMod */
 } pn_DivMod;  /* Projection numbers for DivMod. */
 
 ir_node *get_Div_left(const ir_node *node);
@@ -739,11 +744,11 @@ void     set_Div_resmode(ir_node *node, ir_mode *mode);
  * Projection numbers for Div: use for Proj nodes!
  */
 typedef enum {
-       pn_Div_M,           /**< Memory result. */
-       pn_Div_X_regular,   /**< Execution result if no exception occurred. */
-       pn_Div_X_except,    /**< Execution result if exception occurred. */
-       pn_Div_res,         /**< Result of computation. */
-       pn_Div_max          /**< number of projections from a Div */
+       pn_Div_M         = pn_Generic_M_regular, /**< Memory result. */
+       pn_Div_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
+       pn_Div_X_except  = pn_Generic_X_except,  /**< Execution result if exception occurred. */
+       pn_Div_res       = pn_Generic_other,     /**< Result of computation. */
+       pn_Div_max                               /**< number of projections from a Div */
 } pn_Div;  /* Projection numbers for Div. */
 
 ir_node *get_Mod_left(const ir_node *node);
@@ -759,11 +764,11 @@ void     set_Mod_resmode(ir_node *node, ir_mode *mode);
  * Projection numbers for Mod: use for Proj nodes!
  */
 typedef enum {
-       pn_Mod_M,           /**< Memory result.    */
-       pn_Mod_X_regular,   /**< Execution result if no exception occurred. */
-       pn_Mod_X_except,    /**< Execution result if exception occurred. */
-       pn_Mod_res,         /**< Result of computation. */
-       pn_Mod_max          /**< number of projections from a Mod */
+       pn_Mod_M         = pn_Generic_M_regular, /**< Memory result.    */
+       pn_Mod_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
+       pn_Mod_X_except  = pn_Generic_X_except,  /**< Execution result if exception occurred. */
+       pn_Mod_res       = pn_Generic_other,     /**< Result of computation. */
+       pn_Mod_max                               /**< number of projections from a Mod */
 } pn_Mod;  /* Projection numbers for Mod. */
 
 ir_node *get_Abs_op(const ir_node *node);
@@ -926,11 +931,11 @@ void     set_memop_ptr(ir_node *node, ir_node *ptr);
  * Projection numbers for Load: use for Proj nodes!
  */
 typedef enum {
-       pn_Load_M,         /**< Memory result. */
-       pn_Load_X_regular, /**< Execution result if no exception occurred. */
-       pn_Load_X_except,  /**< Execution result if exception occurred. */
-       pn_Load_res,       /**< Result of load operation. */
-       pn_Load_max        /**< number of projections from a Load */
+       pn_Load_M         = pn_Generic_M_regular, /**< Memory result. */
+       pn_Load_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
+       pn_Load_X_except  = pn_Generic_X_except,  /**< Execution result if exception occurred. */
+       pn_Load_res       = pn_Generic_other,     /**< Result of load operation. */
+       pn_Load_max                               /**< number of projections from a Load */
 } pn_Load;  /* Projection numbers for Load. */
 
 ir_node       *get_Load_mem(ir_node *node);
@@ -948,10 +953,10 @@ void           set_Load_align(ir_node *node, ir_align align);
  * Projection numbers for Store: use for Proj nodes!
  */
 typedef enum {
-  pn_Store_M,         /**< Memory result. */
-  pn_Store_X_regular, /**< Execution result if no exception occurred. */
-  pn_Store_X_except,  /**< Execution result if exception occurred. */
-  pn_Store_max        /**< number of projections from a Store */
+  pn_Store_M         = pn_Generic_M_regular, /**< Memory result. */
+  pn_Store_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
+  pn_Store_X_except  = pn_Generic_X_except,  /**< Execution result if exception occurred. */
+  pn_Store_max       = pn_Generic_other      /**< number of projections from a Store */
 } pn_Store;  /* Projection numbers for Store. */
 
 ir_node       *get_Store_mem(ir_node *node);
@@ -969,11 +974,11 @@ void           set_Store_align(ir_node *node, ir_align align);
  * Projection numbers for Alloc: use for Proj nodes!
  */
 typedef enum {
-       pn_Alloc_M,         /**< Memory result. */
-       pn_Alloc_X_regular, /**< Execution result if no exception occurred. */
-       pn_Alloc_X_except,  /**< Execution result if exception occurred. */
-       pn_Alloc_res,       /**< Result of allocation. */
-       pn_Alloc_max        /**< number of projections from an Alloc */
+       pn_Alloc_M         = pn_Generic_M_regular, /**< Memory result. */
+       pn_Alloc_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
+       pn_Alloc_X_except  = pn_Generic_X_except,  /**< Execution result if exception occurred. */
+       pn_Alloc_res       = pn_Generic_other,     /**< Result of allocation. */
+       pn_Alloc_max                               /**< number of projections from an Alloc */
 } pn_Alloc;  /* Projection numbers for Alloc. */
 
 ir_node *get_Alloc_mem(ir_node *node);
@@ -1063,12 +1068,12 @@ int      get_Psi_n_conds(ir_node *node);
  * Projection numbers for result of CopyB node: use for Proj nodes!
  */
 typedef enum {
-       pn_CopyB_M_regular = 0,  /**< The memory result. */
-       pn_CopyB_X_regular = 1,  /**< Execution result if no exception occurred. */
-       pn_CopyB_X_except  = 2,  /**< The control flow result branching to the exception handler */
-       pn_CopyB_M_except  = 3,  /**< The memory result in case the runtime function terminated with
-                                     an exception */
-       pn_CopyB_max       = 4   /**< number of projections from a CopyB */
+       pn_CopyB_M_regular = pn_Generic_M_regular, /**< The memory result. */
+       pn_CopyB_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
+       pn_CopyB_X_except  = pn_Generic_X_except,  /**< The control flow result branching to the exception handler */
+       pn_CopyB_M_except  = pn_Generic_other,     /**< The memory result in case the runtime function terminated with
+                                                       an exception */
+       pn_CopyB_max                               /**< number of projections from a CopyB */
 } pn_CopyB;   /* Projection numbers for CopyB. */
 #define pn_CopyB_M pn_CopyB_M_regular
 
@@ -1085,13 +1090,13 @@ void     set_CopyB_type(ir_node *node, ir_type *data_type);
  * Projection numbers for result of InstOf node: use for Proj nodes!
  */
 typedef enum {
-       pn_InstOf_M_regular = 0,   /**< The memory result. */
-       pn_InstOf_X_regular = 1,   /**< Execution result if no exception occurred. */
-       pn_InstOf_X_except = 2,    /**< The control flow result branching to the exception handler */
-       pn_InstOf_res = 3,         /**< The checked object pointer. */
-       pn_InstOf_M_except = 4,    /**< The memory result in case the runtime function terminated with
-                                      an exception */
-       pn_InstOf_max = 5          /**< number of projections from an InstOf */
+       pn_InstOf_M_regular = pn_Generic_M_regular, /**< The memory result. */
+       pn_InstOf_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
+       pn_InstOf_X_except  = pn_Generic_X_except,  /**< The control flow result branching to the exception handler */
+       pn_InstOf_res       = pn_Generic_other,     /**< The checked object pointer. */
+       pn_InstOf_M_except,                         /**< The memory result in case the runtime function terminated with
+                                                        an exception */
+       pn_InstOf_max                               /**< number of projections from an InstOf */
 } pn_InstOf;
 #define pn_InstOf_M pn_InstOf_M_regular
 
@@ -1121,11 +1126,11 @@ void     set_Raise_exo_ptr(ir_node *node, ir_node *exoptr);
  * Projection numbers for result of Bound node: use for Proj nodes!
  */
 typedef enum {
-       pn_Bound_M = 0,           /**< The memory result. */
-       pn_Bound_X_regular = 1,   /**< Execution result if no exception occurred. */
-       pn_Bound_X_except = 2,    /**< The control flow result branching to the exception handler */
-       pn_Bound_res = 3,         /**< The checked index. */
-       pn_Bound_max = 4          /**< number of projections from a Bound */
+       pn_Bound_M         = pn_Generic_M_regular, /**< The memory result. */
+       pn_Bound_X_regular = pn_Generic_X_regular, /**< Execution result if no exception occurred. */
+       pn_Bound_X_except  = pn_Generic_X_except,  /**< The control flow result branching to the exception handler */
+       pn_Bound_res       = pn_Generic_other,     /**< The checked index. */
+       pn_Bound_max                               /**< number of projections from a Bound */
 } pn_Bound;
 
 /** Returns the memory input of a Bound operation. */
index b89af03..3525962 100644 (file)
  *  block with the fragile operation. */
 #define PRECISE_EXC_CONTEXT 1
 
-/** There are two implementations of the Phi node construction.  The first
- *  is faster, but does not work for blocks with more than 2 predecessors.
- *  The second works always but is slower and causes more unnecessary Phi
- *  nodes.
- *  Select the implementations by the following preprocessor flag: */
-#define USE_FAST_PHI_CONSTRUCTION 0
-
-/** Further there are two versions of the fast Phi node construction.
- *  If the following flag is set, new_r_Phi_in uses an explicit stack for
- *  allocating and deallocating Phi nodes.  Else it uses the obstack
- *  as a stack! */
-#define USE_EXPLICIT_PHI_IN_STACK 0
-
 /** If this and DEBUG_libfirm are defined irdump uses the nodeid numbers as
  *  labels for the vcg nodes.  This makes the vcg graph better readable.
  *  Sometimes it's useful to see the pointer values, though. */
index ee564ec..d4ad8f9 100644 (file)
@@ -1806,333 +1806,6 @@ new_rd_Phi0(ir_graph *irg, ir_node *block, ir_mode *mode) {
        return res;
 }  /* new_rd_Phi0 */
 
-/* There are two implementations of the Phi node construction.  The first
-   is faster, but does not work for blocks with more than 2 predecessors.
-   The second works always but is slower and causes more unnecessary Phi
-   nodes.
-   Select the implementations by the following preprocessor flag set in
-   common/common.h: */
-#if USE_FAST_PHI_CONSTRUCTION
-
-/* This is a stack used for allocating and deallocating nodes in
-   new_rd_Phi_in.  The original implementation used the obstack
-   to model this stack, now it is explicit.  This reduces side effects.
-*/
-#if USE_EXPLICIT_PHI_IN_STACK
-Phi_in_stack *
-new_Phi_in_stack(void) {
-       Phi_in_stack *res;
-
-       res = (Phi_in_stack *) xmalloc(sizeof(Phi_in_stack));
-
-       res->stack = NEW_ARR_F(ir_node *, 0);
-       res->pos = 0;
-
-       return res;
-}  /* new_Phi_in_stack */
-
-void
-free_Phi_in_stack(Phi_in_stack *s) {
-       DEL_ARR_F(s->stack);
-       free(s);
-}  /* free_Phi_in_stack */
-
-static INLINE void
-free_to_Phi_in_stack(ir_node *phi) {
-       if (ARR_LEN(current_ir_graph->Phi_in_stack->stack) ==
-           current_ir_graph->Phi_in_stack->pos)
-               ARR_APP1 (ir_node *, current_ir_graph->Phi_in_stack->stack, phi);
-       else
-               current_ir_graph->Phi_in_stack->stack[current_ir_graph->Phi_in_stack->pos] = phi;
-
-       (current_ir_graph->Phi_in_stack->pos)++;
-}  /* free_to_Phi_in_stack */
-
-static INLINE ir_node *
-alloc_or_pop_from_Phi_in_stack(ir_graph *irg, ir_node *block, ir_mode *mode,
-                               int arity, ir_node **in) {
-       ir_node *res;
-       ir_node **stack = current_ir_graph->Phi_in_stack->stack;
-       int pos = current_ir_graph->Phi_in_stack->pos;
-
-
-       if (pos == 0) {
-               /* We need to allocate a new node */
-               res = new_ir_node (db, irg, block, op_Phi, mode, arity, in);
-               res->attr.phi_backedge = new_backedge_arr(irg->obst, arity);
-       } else {
-               /* reuse the old node and initialize it again. */
-               res = stack[pos-1];
-
-               assert(res->kind == k_ir_node);
-               assert(res->op == op_Phi);
-               res->mode = mode;
-               res->visited = 0;
-               res->link = NULL;
-               assert(arity >= 0);
-               /* ???!!! How to free the old in array??  Not at all: on obstack ?!! */
-               res->in = NEW_ARR_D(ir_node *, irg->obst, (arity+1));
-               res->in[0] = block;
-               memcpy (&res->in[1], in, sizeof (ir_node *) * arity);
-
-               (current_ir_graph->Phi_in_stack->pos)--;
-       }
-       return res;
-}  /* alloc_or_pop_from_Phi_in_stack */
-#endif /* USE_EXPLICIT_PHI_IN_STACK */
-
-/**
- * Creates a Phi node with a given, fixed array **in of predecessors.
- * If the Phi node is unnecessary, as the same value reaches the block
- * through all control flow paths, it is eliminated and the value
- * returned directly.  This constructor is only intended for use in
- * the automatic Phi node generation triggered by get_value or mature.
- * The implementation is quite tricky and depends on the fact, that
- * the nodes are allocated on a stack:
- * The in array contains predecessors and NULLs.  The NULLs appear,
- * if get_r_value_internal, that computed the predecessors, reached
- * the same block on two paths.  In this case the same value reaches
- * this block on both paths, there is no definition in between.  We need
- * not allocate a Phi where these path's merge, but we have to communicate
- * this fact to the caller.  This happens by returning a pointer to the
- * node the caller _will_ allocate.  (Yes, we predict the address. We can
- * do so because the nodes are allocated on the obstack.)  The caller then
- * finds a pointer to itself and, when this routine is called again,
- * eliminates itself.
- */
-static INLINE ir_node *
-new_rd_Phi_in(ir_graph *irg, ir_node *block, ir_mode *mode, ir_node **in, int ins) {
-       int i;
-       ir_node *res, *known;
-
-       /* Allocate a new node on the obstack.  This can return a node to
-          which some of the pointers in the in-array already point.
-          Attention: the constructor copies the in array, i.e., the later
-          changes to the array in this routine do not affect the
-          constructed node!  If the in array contains NULLs, there will be
-          missing predecessors in the returned node.  Is this a possible
-          internal state of the Phi node generation? */
-#if USE_EXPLICIT_PHI_IN_STACK
-       res = known = alloc_or_pop_from_Phi_in_stack(irg, block, mode, ins, in);
-#else
-       res = known = new_ir_node (NULL, irg, block, op_Phi, mode, ins, in);
-       res->attr.phi_backedge = new_backedge_arr(irg->obst, ins);
-#endif
-
-       /* The in-array can contain NULLs.  These were returned by
-          get_r_value_internal if it reached the same block/definition on a
-          second path.  The NULLs are replaced by the node itself to
-          simplify the test in the next loop. */
-       for (i = 0;  i < ins;  ++i) {
-               if (in[i] == NULL)
-                       in[i] = res;
-       }
-
-       /* This loop checks whether the Phi has more than one predecessor.
-          If so, it is a real Phi node and we break the loop.  Else the Phi
-          node merges the same definition on several paths and therefore is
-          not needed. */
-       for (i = 0;  i < ins;  ++i) {
-               if (in[i] == res || in[i] == known)
-                       continue;
-
-               if (known == res)
-                       known = in[i];
-               else
-                       break;
-       }
-
-       /* i==ins: there is at most one predecessor, we don't need a phi node. */
-       if (i==ins) {
-#if USE_EXPLICIT_PHI_IN_STACK
-               free_to_Phi_in_stack(res);
-#else
-               edges_node_deleted(res, current_ir_graph);
-               obstack_free(current_ir_graph->obst, res);
-#endif
-               res = known;
-       } else {
-               res = optimize_node (res);
-               IRN_VRFY_IRG(res, irg);
-       }
-
-       /* return the pointer to the Phi node.  This node might be deallocated! */
-       return res;
-}  /* new_rd_Phi_in */
-
-static ir_node *
-get_r_value_internal(ir_node *block, int pos, ir_mode *mode);
-
-/**
- * Allocates and returns this node.  The routine called to allocate the
- * node might optimize it away and return a real value, or even a pointer
- * to a deallocated Phi node on top of the obstack!
- * This function is called with an in-array of proper size.
- */
-static ir_node *
-phi_merge(ir_node *block, int pos, ir_mode *mode, ir_node **nin, int ins) {
-       ir_node *prevBlock, *res;
-       int i;
-
-       /* This loop goes to all predecessor blocks of the block the Phi node is in
-          and there finds the operands of the Phi node by calling
-          get_r_value_internal. */
-       for (i = 1;  i <= ins;  ++i) {
-               assert (block->in[i]);
-               prevBlock = block->in[i]->in[0]; /* go past control flow op to prev block */
-               assert (prevBlock);
-               nin[i-1] = get_r_value_internal (prevBlock, pos, mode);
-       }
-
-       /* After collecting all predecessors into the array nin a new Phi node
-          with these predecessors is created.  This constructor contains an
-          optimization: If all predecessors of the Phi node are identical it
-          returns the only operand instead of a new Phi node.  If the value
-          passes two different control flow edges without being defined, and
-          this is the second path treated, a pointer to the node that will be
-          allocated for the first path (recursion) is returned.  We already
-          know the address of this node, as it is the next node to be allocated
-          and will be placed on top of the obstack. (The obstack is a _stack_!) */
-       res = new_rd_Phi_in (current_ir_graph, block, mode, nin, ins);
-
-       /* Now we now the value for "pos" and can enter it in the array with
-          all known local variables.  Attention: this might be a pointer to
-          a node, that later will be allocated!!! See new_rd_Phi_in().
-          If this is called in mature, after some set_value() in the same block,
-          the proper value must not be overwritten:
-          The call order
-            get_value    (makes Phi0, put's it into graph_arr)
-            set_value    (overwrites Phi0 in graph_arr)
-            mature_immBlock (upgrades Phi0, puts it again into graph_arr, overwriting
-                          the proper value.)
-          fails. */
-       if (!block->attr.block.graph_arr[pos]) {
-               block->attr.block.graph_arr[pos] = res;
-       } else {
-               /*  printf(" value already computed by %s\n",
-               get_id_str(block->attr.block.graph_arr[pos]->op->name));  */
-       }
-
-       return res;
-}
-
-/**
- * This function returns the last definition of a variable.  In case
- * this variable was last defined in a previous block, Phi nodes are
- * inserted.  If the part of the firm graph containing the definition
- * is not yet constructed, a dummy Phi node is returned.
- */
-static ir_node *
-get_r_value_internal(ir_node *block, int pos, ir_mode *mode)
-{
-       ir_node *res;
-       /* There are 4 cases to treat.
-
-          1. The block is not mature and we visit it the first time.  We can not
-             create a proper Phi node, therefore a Phi0, i.e., a Phi without
-             predecessors is returned.  This node is added to the linked list (field
-             "link") of the containing block to be completed when this block is
-             matured. (Completion will add a new Phi and turn the Phi0 into an Id
-             node.)
-
-          2. The value is already known in this block, graph_arr[pos] is set and we
-             visit the block the first time.  We can return the value without
-             creating any new nodes.
-
-          3. The block is mature and we visit it the first time.  A Phi node needs
-             to be created (phi_merge).  If the Phi is not needed, as all it's
-             operands are the same value reaching the block through different
-             paths, it's optimized away and the value itself is returned.
-
-          4. The block is mature, and we visit it the second time.  Now two
-             subcases are possible:
-             * The value was computed completely the last time we were here. This
-               is the case if there is no loop.  We can return the proper value.
-             * The recursion that visited this node and set the flag did not
-               return yet.  We are computing a value in a loop and need to
-               break the recursion without knowing the result yet.
-           @@@ strange case.  Straight forward we would create a Phi before
-           starting the computation of it's predecessors.  In this case we will
-           find a Phi here in any case.  The problem is that this implementation
-           only creates a Phi after computing the predecessors, so that it is
-           hard to compute self references of this Phi.  @@@
-             There is no simple check for the second subcase.  Therefore we check
-             for a second visit and treat all such cases as the second subcase.
-             Anyways, the basic situation is the same:  we reached a block
-             on two paths without finding a definition of the value:  No Phi
-             nodes are needed on both paths.
-             We return this information "Two paths, no Phi needed" by a very tricky
-             implementation that relies on the fact that an obstack is a stack and
-             will return a node with the same address on different allocations.
-             Look also at phi_merge and new_rd_phi_in to understand this.
-         @@@ Unfortunately this does not work, see testprogram
-         three_cfpred_example.
-
-       */
-
-       /* case 4 -- already visited. */
-       if (get_irn_visited(block) == get_irg_visited(current_ir_graph)) return NULL;
-
-       /* visited the first time */
-       set_irn_visited(block, get_irg_visited(current_ir_graph));
-
-       /* Get the local valid value */
-       res = block->attr.block.graph_arr[pos];
-
-       /* case 2 -- If the value is actually computed, return it. */
-       if (res) return res;
-
-       if (block->attr.block.is_matured) { /* case 3 */
-
-               /* The Phi has the same amount of ins as the corresponding block. */
-               int ins = get_irn_arity(block);
-               ir_node **nin;
-               NEW_ARR_A(ir_node *, nin, ins);
-
-               /* Phi merge collects the predecessors and then creates a node. */
-               res = phi_merge(block, pos, mode, nin, ins);
-
-       } else {  /* case 1 */
-               /* The block is not mature, we don't know how many in's are needed.  A Phi
-                  with zero predecessors is created.  Such a Phi node is called Phi0
-                  node.  (There is also an obsolete Phi0 opcode.) The Phi0 is then added
-                  to the list of Phi0 nodes in this block to be matured by mature_immBlock
-                  later.
-                  The Phi0 has to remember the pos of it's internal value.  If the real
-                  Phi is computed, pos is used to update the array with the local
-                  values. */
-
-               res = new_rd_Phi0(current_ir_graph, block, mode);
-               res->attr.phi0_pos = pos;
-               res->link = block->link;
-               block->link = res;
-       }
-
-       /* If we get here, the frontend missed a use-before-definition error */
-       if (!res) {
-               /* Error Message */
-               printf("Error: no value set.  Use of undefined variable.  Initializing to zero.\n");
-               assert(mode->code >= irm_F && mode->code <= irm_P);
-               res = new_rd_Const(NULL, current_ir_graph, block, mode, tarval_mode_null[mode->code]);
-       }
-
-       /* The local valid value is available now. */
-       block->attr.block.graph_arr[pos] = res;
-
-       return res;
-}  /* get_r_value_internal */
-
-#else /* if 0 */
-
-/**
-    it starts the recursion.  This causes an Id at the entry of
-    every block that has no definition of the value! **/
-
-#if USE_EXPLICIT_PHI_IN_STACK
-/* Just dummies */
-Phi_in_stack * new_Phi_in_stack() { return NULL; }
-void free_Phi_in_stack(Phi_in_stack *s) {}
-#endif
 
 static INLINE ir_node *
 new_rd_Phi_in(ir_graph *irg, ir_node *block, ir_mode *mode,
@@ -2329,6 +2002,28 @@ get_r_frag_value_internal(ir_node *block, ir_node *cfOp, int pos, ir_mode *mode)
 }  /* get_r_frag_value_internal */
 #endif /* PRECISE_EXC_CONTEXT */
 
+/**
+ * check whether a control flow cf_pred is a exception flow.
+ *
+ * @param cf_pred     the control flow node
+ * @param prev_cf_op  if cf_pred is a Proj, the predecessor node, else equal to cf_pred
+ */
+static int is_exception_flow(ir_node *cf_pred, ir_node *prev_cf_op) {
+       /* all projections from a raise are exceptional control flow */
+       if (is_Raise(prev_cf_op))
+               return 1;
+       if (is_fragile_op(prev_cf_op)) {
+               if (is_Proj(cf_pred) && get_Proj_proj(cf_pred) == pn_Generic_X_regular) {
+                       /* the regular control flow, NO exception */
+                       return 0;
+               }
+               /* Hmm, exception but not a Proj? */
+               assert(!"unexpected condition: fragile op without a proj");
+               return 1;
+       }
+       return 0;
+}  /* is_exception_flow */
+
 /**
  * Computes the predecessors for the real phi node, and then
  * allocates and returns this node.  The routine called to allocate the
@@ -2337,7 +2032,7 @@ get_r_frag_value_internal(ir_node *block, ir_node *cfOp, int pos, ir_mode *mode)
  */
 static ir_node *
 phi_merge(ir_node *block, int pos, ir_mode *mode, ir_node **nin, int ins) {
-       ir_node *prevBlock, *prevCfOp, *res, *phi0, *phi0_all;
+       ir_node *prevBlock, *res, *phi0, *phi0_all;
        int i;
 
        /* If this block has no value at pos create a Phi0 and remember it
@@ -2387,26 +2082,26 @@ phi_merge(ir_node *block, int pos, ir_mode *mode, ir_node **nin, int ins) {
        /* This loop goes to all predecessor blocks of the block the Phi node
           is in and there finds the operands of the Phi node by calling
           get_r_value_internal.  */
-       for (i = 1;  i <= ins;  ++i) {
-               prevCfOp = skip_Proj(block->in[i]);
-               assert (prevCfOp);
+       for (i = 1; i <= ins; ++i) {
+               ir_node *cf_pred = block->in[i];
+               ir_node *prevCfOp = skip_Proj(cf_pred);
+               assert(prevCfOp);
                if (is_Bad(prevCfOp)) {
                        /* In case a Cond has been optimized we would get right to the start block
                        with an invalid definition. */
                        nin[i-1] = new_Bad();
                        continue;
                }
-               prevBlock = block->in[i]->in[0]; /* go past control flow op to prev block */
-               assert (prevBlock);
+               prevBlock = prevCfOp->in[0]; /* go past control flow op to prev block */
+               assert(prevBlock);
                if (!is_Bad(prevBlock)) {
 #if PRECISE_EXC_CONTEXT
-                       if (get_opt_precise_exc_context() &&
-                               is_fragile_op(prevCfOp) && (get_irn_op (prevCfOp) != op_Bad)) {
-                                       assert(get_r_frag_value_internal (prevBlock, prevCfOp, pos, mode));
-                                       nin[i-1] = get_r_frag_value_internal (prevBlock, prevCfOp, pos, mode);
+                       if (get_opt_precise_exc_context() && is_exception_flow(cf_pred, prevCfOp)) {
+                               assert(get_r_frag_value_internal(prevBlock, prevCfOp, pos, mode));
+                               nin[i-1] = get_r_frag_value_internal(prevBlock, prevCfOp, pos, mode);
                        } else
 #endif
-                               nin[i-1] = get_r_value_internal (prevBlock, pos, mode);
+                               nin[i-1] = get_r_value_internal(prevBlock, pos, mode);
                } else {
                        nin[i-1] = new_Bad();
                }
@@ -2431,7 +2126,7 @@ phi_merge(ir_node *block, int pos, ir_mode *mode, ir_node **nin, int ins) {
           with these predecessors is created.  This constructor contains an
           optimization: If all predecessors of the Phi node are identical it
           returns the only operand instead of a new Phi node.  */
-       res = new_rd_Phi_in (current_ir_graph, block, mode, nin, ins, phi0_all);
+       res = new_rd_Phi_in(current_ir_graph, block, mode, nin, ins, phi0_all);
 
        /* In case we allocated a Phi0 node at the beginning of this procedure,
           we need to exchange this Phi0 with the real Phi. */
@@ -2446,10 +2141,14 @@ phi_merge(ir_node *block, int pos, ir_mode *mode, ir_node **nin, int ins) {
 }  /* phi_merge */
 
 /**
- * This function returns the last definition of a variable.  In case
- * this variable was last defined in a previous block, Phi nodes are
+ * This function returns the last definition of a value.  In case
+ * this value was last defined in a previous block, Phi nodes are
  * inserted.  If the part of the firm graph containing the definition
  * is not yet constructed, a dummy Phi node is returned.
+ *
+ * @param block   the current block
+ * @param pos     the value number of the value searched
+ * @param mode    the mode of this value (needed for Phi construction)
  */
 static ir_node *
 get_r_value_internal(ir_node *block, int pos, ir_mode *mode) {
@@ -2539,8 +2238,6 @@ get_r_value_internal(ir_node *block, int pos, ir_mode *mode) {
        return res;
 }  /* get_r_value_internal */
 
-#endif /* USE_FAST_PHI_CONSTRUCTION */
-
 /* ************************************************************************** */
 
 /*
@@ -2553,10 +2250,7 @@ mature_immBlock(ir_node *block) {
        ir_node *n, **nin;
        ir_node *next;
 
-       assert(get_irn_opcode(block) == iro_Block);
-       /* @@@ should be commented in
-          assert (!get_Block_matured(block) && "Block already matured"); */
-
+       assert(is_Block(block));
        if (!get_Block_matured(block)) {
                ins = ARR_LEN(block->in)-1;
                /* Fix block parameters */