Removed USE_FAST_PHI_CONSTRUCTION and USE_EXPLICIT_PHI_IN_STACK
[libfirm] / ir / ir / ircons.c
index af614d0..d4ad8f9 100644 (file)
@@ -104,7 +104,7 @@ new_bd_##instr(dbg_info *db, ir_node *block,                    \
 #define NEW_BD_DIVOP(instr)                                     \
 static ir_node *                                                \
 new_bd_##instr(dbg_info *db, ir_node *block,                    \
-            ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode) \
+            ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) \
 {                                                               \
   ir_node  *in[3];                                              \
   ir_node  *res;                                                \
@@ -113,7 +113,7 @@ new_bd_##instr(dbg_info *db, ir_node *block,                    \
   in[1] = op1;                                                  \
   in[2] = op2;                                                  \
   res = new_ir_node(db, irg, block, op_##instr, mode_T, 3, in); \
-  res->attr.divmod.exc.pin_state = op_pin_state_pinned;         \
+  res->attr.divmod.exc.pin_state = state;                       \
   res->attr.divmod.res_mode = mode;                             \
   res = optimize_node(res);                                     \
   IRN_VRFY_IRG(res, irg);                                       \
@@ -152,12 +152,12 @@ new_rd_##instr(dbg_info *db, ir_graph *irg, ir_node *block,     \
 #define NEW_RD_DIVOP(instr)                                     \
 ir_node *                                                       \
 new_rd_##instr(dbg_info *db, ir_graph *irg, ir_node *block,     \
-            ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode) \
+            ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) \
 {                                                               \
   ir_node  *res;                                                \
   ir_graph *rem = current_ir_graph;                             \
   current_ir_graph = irg;                                       \
-  res = new_bd_##instr(db, block, memop, op1, op2, mode);       \
+  res = new_bd_##instr(db, block, memop, op1, op2, mode, state);\
   current_ir_graph = rem;                                       \
   return res;                                                   \
 }
@@ -193,18 +193,20 @@ new_bd_Block(dbg_info *db, int arity, ir_node **in) {
        res->in[0] = res;
 
        res->attr.block.is_dead     = 0;
-    res->attr.block.is_mb_head  = 1;
+       res->attr.block.is_mb_head  = 1;
+       res->attr.block.has_label   = 0;
        res->attr.block.irg         = irg;
        res->attr.block.backedge    = new_backedge_arr(irg->obst, arity);
        res->attr.block.in_cg       = NULL;
        res->attr.block.cg_backedge = NULL;
        res->attr.block.extblk      = NULL;
-    res->attr.block.mb_depth    = 0;
+       res->attr.block.mb_depth    = 0;
+       res->attr.block.label       = 0;
 
        set_Block_matured(res, 1);
        set_Block_block_visited(res, 0);
 
-    IRN_VRFY_IRG(res, irg);
+       IRN_VRFY_IRG(res, irg);
        return res;
 }  /* new_bd_Block */
 
@@ -270,6 +272,7 @@ static ir_node *
 new_bd_Const_type(dbg_info *db, ir_node *block, ir_mode *mode, tarval *con, ir_type *tp) {
        ir_node  *res;
        ir_graph *irg = current_ir_graph;
+       (void) block;
 
        res = new_ir_node(db, irg, get_irg_start_block(irg), op_Const, mode, 0, NULL);
        res->attr.con.tv = con;
@@ -379,6 +382,7 @@ NEW_BD_BINOP(Add)
 NEW_BD_BINOP(Sub)
 NEW_BD_UNOP(Minus)
 NEW_BD_BINOP(Mul)
+NEW_BD_BINOP(Mulh)
 NEW_BD_DIVOP(Quot)
 NEW_BD_DIVOP(DivMod)
 NEW_BD_DIVOP(Div)
@@ -413,8 +417,8 @@ new_bd_Jmp(dbg_info *db, ir_node *block) {
        ir_node  *res;
        ir_graph *irg = current_ir_graph;
 
-       res = new_ir_node (db, irg, block, op_Jmp, mode_X, 0, NULL);
-       res = optimize_node (res);
+       res = new_ir_node(db, irg, block, op_Jmp, mode_X, 0, NULL);
+       res = optimize_node(res);
        IRN_VRFY_IRG(res, irg);
        return res;
 }  /* new_bd_Jmp */
@@ -424,12 +428,9 @@ new_bd_IJmp(dbg_info *db, ir_node *block, ir_node *tgt) {
        ir_node  *res;
        ir_graph *irg = current_ir_graph;
 
-       res = new_ir_node (db, irg, block, op_IJmp, mode_X, 1, &tgt);
-       res = optimize_node (res);
+       res = new_ir_node(db, irg, block, op_IJmp, mode_X, 1, &tgt);
+       res = optimize_node(res);
        IRN_VRFY_IRG(res, irg);
-
-       if (get_irn_op(res) == op_IJmp) /* still an IJmp */
-               keep_alive(res);
        return res;
 }  /* new_bd_IJmp */
 
@@ -438,11 +439,11 @@ new_bd_Cond(dbg_info *db, ir_node *block, ir_node *c) {
        ir_node  *res;
        ir_graph *irg = current_ir_graph;
 
-       res = new_ir_node (db, irg, block, op_Cond, mode_T, 1, &c);
+       res = new_ir_node(db, irg, block, op_Cond, mode_T, 1, &c);
        res->attr.cond.kind         = dense;
        res->attr.cond.default_proj = 0;
        res->attr.cond.pred         = COND_JMP_PRED_NONE;
-       res = optimize_node (res);
+       res = optimize_node(res);
        IRN_VRFY_IRG(res, irg);
        return res;
 }  /* new_bd_Cond */
@@ -503,6 +504,7 @@ new_bd_Load(dbg_info *db, ir_node *block,
        res->attr.load.exc.pin_state = op_pin_state_pinned;
        res->attr.load.load_mode     = mode;
        res->attr.load.volatility    = volatility_non_volatile;
+       res->attr.load.aligned       = align_is_aligned;
        res = optimize_node(res);
        IRN_VRFY_IRG(res, irg);
        return res;
@@ -521,6 +523,7 @@ new_bd_Store(dbg_info *db, ir_node *block,
        res = new_ir_node(db, irg, block, op_Store, mode_T, 3, in);
        res->attr.store.exc.pin_state = op_pin_state_pinned;
        res->attr.store.volatility    = volatility_non_volatile;
+       res->attr.store.aligned       = align_is_aligned;
        res = optimize_node(res);
        IRN_VRFY_IRG(res, irg);
        return res;
@@ -629,9 +632,9 @@ new_bd_Confirm(dbg_info *db, ir_node *block, ir_node *val, ir_node *bound, pn_Cm
 
        in[0] = val;
        in[1] = bound;
-       res = new_ir_node (db, irg, block, op_Confirm, get_irn_mode(val), 2, in);
-       res->attr.confirm_cmp = cmp;
-       res = optimize_node (res);
+       res = new_ir_node(db, irg, block, op_Confirm, get_irn_mode(val), 2, in);
+       res->attr.confirm.cmp = cmp;
+       res = optimize_node(res);
        IRN_VRFY_IRG(res, irg);
        return res;
 }  /* new_bd_Confirm */
@@ -837,19 +840,21 @@ new_bd_Pin(dbg_info *db, ir_node *block, ir_node *node) {
 }  /* new_bd_Pin */
 
 static ir_node *
-new_bd_ASM(dbg_info *db, ir_node *block, ir_node *store, int arity, ir_node *inputs[], ident *asm_text) {
-       ir_node  *res, **in;
+new_bd_ASM(dbg_info *db, ir_node *block, int arity, ir_node *in[], ir_asm_constraint *inputs,
+           int n_outs, ir_asm_constraint *outputs, int n_clobber, ident *clobber[], ident *asm_text) {
+       ir_node  *res;
        ir_graph *irg = current_ir_graph;
-       int      i;
+       (void) clobber;
 
-       NEW_ARR_A(ir_node *, in, arity + 1);
+       res = new_ir_node(db, irg, block, op_ASM, mode_T, arity, in);
+       res->attr.assem.pin_state = op_pin_state_pinned;
+       res->attr.assem.inputs    = NEW_ARR_D(ir_asm_constraint, irg->obst, arity);
+       res->attr.assem.outputs   = NEW_ARR_D(ir_asm_constraint, irg->obst, n_outs);
+    res->attr.assem.clobber   = NEW_ARR_D(ident *, irg->obst, n_clobber);
+       res->attr.assem.asm_text  = asm_text;
 
-       in[0] = store;
-       for (i = 0; i < arity; ++i)
-               in[i + 1] = inputs[i];
-
-       res = new_ir_node(db, irg, block, op_ASM, mode_T, arity + 1, in);
-       res->attr.asm.asm_text = asm_text;
+    memcpy(res->attr.assem.inputs,  inputs,  sizeof(inputs[0]) * arity);
+    memcpy(res->attr.assem.outputs, outputs, sizeof(outputs[0]) * n_outs);
 
        res = optimize_node(res);
        IRN_VRFY_IRG(res, irg);
@@ -892,7 +897,7 @@ new_rd_End(dbg_info *db, ir_graph *irg, ir_node *block) {
        ir_node  *res;
        ir_graph *rem = current_ir_graph;
 
-       current_ir_graph = rem;
+       current_ir_graph = irg;
        res = new_bd_End(db, block);
        current_ir_graph = rem;
 
@@ -1020,6 +1025,7 @@ NEW_RD_BINOP(Add)
 NEW_RD_BINOP(Sub)
 NEW_RD_UNOP(Minus)
 NEW_RD_BINOP(Mul)
+NEW_RD_BINOP(Mulh)
 NEW_RD_DIVOP(Quot)
 NEW_RD_DIVOP(DivMod)
 NEW_RD_DIVOP(Div)
@@ -1438,13 +1444,15 @@ ir_node *new_rd_Pin(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *node)
        return res;
 }  /* new_rd_Pin */
 
-ir_node *new_rd_ASM(dbg_info *db, ir_graph *irg, ir_node *block, ir_node *store,
-                    int arity, ir_node *inputs[], ident *asm_text) {
+ir_node *new_rd_ASM(dbg_info *db, ir_graph *irg, ir_node *block,
+                    int arity, ir_node *in[], ir_asm_constraint *inputs,
+                    int n_outs, ir_asm_constraint *outputs,
+                    int n_clobber, ident *clobber[], ident *asm_text) {
        ir_node  *res;
        ir_graph *rem = current_ir_graph;
 
        current_ir_graph = irg;
-       res = new_bd_ASM(db, block, store, arity, inputs, asm_text);
+       res = new_bd_ASM(db, block, arity, in, inputs, n_outs, outputs, n_clobber, clobber, asm_text);
        current_ir_graph = rem;
 
        return res;
@@ -1519,21 +1527,25 @@ ir_node *new_r_Mul(ir_graph *irg, ir_node *block,
                    ir_node *op1, ir_node *op2, ir_mode *mode) {
        return new_rd_Mul(NULL, irg, block, op1, op2, mode);
 }
+ir_node *new_r_Mulh(ir_graph *irg, ir_node *block,
+                   ir_node *op1, ir_node *op2, ir_mode *mode) {
+       return new_rd_Mulh(NULL, irg, block, op1, op2, mode);
+}
 ir_node *new_r_Quot(ir_graph *irg, ir_node *block,
-                    ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode) {
-       return new_rd_Quot(NULL, irg, block, memop, op1, op2, mode);
+                    ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
+       return new_rd_Quot(NULL, irg, block, memop, op1, op2, mode, state);
 }
 ir_node *new_r_DivMod(ir_graph *irg, ir_node *block,
-                      ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode) {
-       return new_rd_DivMod(NULL, irg, block, memop, op1, op2, mode);
+                      ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
+       return new_rd_DivMod(NULL, irg, block, memop, op1, op2, mode, state);
 }
 ir_node *new_r_Div(ir_graph *irg, ir_node *block,
-                   ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode) {
-       return new_rd_Div(NULL, irg, block, memop, op1, op2, mode);
+                   ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
+       return new_rd_Div(NULL, irg, block, memop, op1, op2, mode, state);
 }
 ir_node *new_r_Mod(ir_graph *irg, ir_node *block,
-                   ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode) {
-       return new_rd_Mod(NULL, irg, block, memop, op1, op2, mode);
+                   ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
+       return new_rd_Mod(NULL, irg, block, memop, op1, op2, mode, state);
 }
 ir_node *new_r_Abs(ir_graph *irg, ir_node *block,
                    ir_node *op, ir_mode *mode) {
@@ -1633,7 +1645,7 @@ ir_node *new_r_Bad(ir_graph *irg) {
        return new_rd_Bad(irg);
 }
 ir_node *new_r_Confirm(ir_graph *irg, ir_node *block, ir_node *val, ir_node *bound, pn_Cmp cmp) {
-       return new_rd_Confirm (NULL, irg, block, val, bound, cmp);
+       return new_rd_Confirm(NULL, irg, block, val, bound, cmp);
 }
 ir_node *new_r_Unknown(ir_graph *irg, ir_mode *m) {
        return new_rd_Unknown(irg, m);
@@ -1684,9 +1696,11 @@ ir_node *new_r_Bound(ir_graph *irg, ir_node *block,
 ir_node *new_r_Pin(ir_graph *irg, ir_node *block, ir_node *node) {
        return new_rd_Pin(NULL, irg, block, node);
 }
-ir_node *new_r_ASM(ir_graph *irg, ir_node *block, ir_node *store,
-                   int arity, ir_node *inputs[], ident *asm_text) {
-       return new_rd_ASM(NULL, irg, block, store, arity, inputs, asm_text);
+ir_node *new_r_ASM(ir_graph *irg, ir_node *block,
+                   int arity, ir_node *in[], ir_asm_constraint *inputs,
+                   int n_outs, ir_asm_constraint *outputs,
+                   int n_clobber, ident *clobber[], ident *asm_text) {
+       return new_rd_ASM(NULL, irg, block, arity, in, inputs, n_outs, outputs, n_clobber, clobber, asm_text);
 }
 
 /** ********************/
@@ -1792,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 *) malloc ( 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,
@@ -2315,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
@@ -2323,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
@@ -2373,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();
                }
@@ -2417,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. */
@@ -2432,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) {
@@ -2525,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 */
-
 /* ************************************************************************** */
 
 /*
@@ -2539,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 */
@@ -2607,6 +2315,7 @@ new_d_Proj(dbg_info *db, ir_node *arg, ir_mode *mode, long proj) {
 ir_node *
 new_d_defaultProj(dbg_info *db, ir_node *arg, long max_proj) {
        ir_node *res;
+       (void) db;
        assert(arg->op == op_Cond);
        arg->attr.cond.kind = fragmentary;
        arg->attr.cond.default_proj = max_proj;
@@ -2638,6 +2347,7 @@ NEW_D_BINOP(Add)
 NEW_D_BINOP(Sub)
 NEW_D_UNOP(Minus)
 NEW_D_BINOP(Mul)
+NEW_D_BINOP(Mulh)
 
 /**
  * Allocate the frag array.
@@ -2653,9 +2363,9 @@ static void allocate_frag_arr(ir_node *res, ir_op *op, ir_node ***frag_store) {
 }  /* allocate_frag_arr */
 
 ir_node *
-new_d_Quot(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode) {
+new_d_Quot(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
        ir_node *res;
-       res = new_bd_Quot(db, current_ir_graph->current_block, memop, op1, op2, mode);
+       res = new_bd_Quot(db, current_ir_graph->current_block, memop, op1, op2, mode, state);
 #if PRECISE_EXC_CONTEXT
        allocate_frag_arr(res, op_Quot, &res->attr.except.frag_arr);  /* Could be optimized away. */
 #endif
@@ -2664,9 +2374,9 @@ new_d_Quot(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mo
 }  /* new_d_Quot */
 
 ir_node *
-new_d_DivMod(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode) {
+new_d_DivMod(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
        ir_node *res;
-       res = new_bd_DivMod(db, current_ir_graph->current_block, memop, op1, op2, mode);
+       res = new_bd_DivMod(db, current_ir_graph->current_block, memop, op1, op2, mode, state);
 #if PRECISE_EXC_CONTEXT
        allocate_frag_arr(res, op_DivMod, &res->attr.except.frag_arr);  /* Could be optimized away. */
 #endif
@@ -2675,9 +2385,9 @@ new_d_DivMod(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *
 }  /* new_d_DivMod */
 
 ir_node *
-new_d_Div(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode) {
+new_d_Div(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
        ir_node *res;
-       res = new_bd_Div(db, current_ir_graph->current_block, memop, op1, op2, mode);
+       res = new_bd_Div(db, current_ir_graph->current_block, memop, op1, op2, mode, state);
 #if PRECISE_EXC_CONTEXT
        allocate_frag_arr(res, op_Div, &res->attr.except.frag_arr);  /* Could be optimized away. */
 #endif
@@ -2686,9 +2396,9 @@ new_d_Div(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mod
 }
 
 ir_node *
-new_d_Mod(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode) {
+new_d_Mod(dbg_info *db, ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
        ir_node *res;
-       res = new_bd_Mod(db, current_ir_graph->current_block, memop, op1, op2, mode);
+       res = new_bd_Mod(db, current_ir_graph->current_block, memop, op1, op2, mode, state);
 #if PRECISE_EXC_CONTEXT
        allocate_frag_arr(res, op_Mod, &res->attr.except.frag_arr);  /* Could be optimized away. */
 #endif
@@ -2923,8 +2633,10 @@ new_d_Pin(dbg_info *db, ir_node *node) {
 }  /* new_d_Pin */
 
 ir_node *
-new_d_ASM(dbg_info *db, ir_node *store, int arity, ir_node *inputs[], ident *asm_text) {
-       return new_bd_ASM(db, current_ir_graph->current_block, store, arity, inputs, asm_text);
+new_d_ASM(dbg_info *db, int arity, ir_node *in[], ir_asm_constraint *inputs,
+          int n_outs, ir_asm_constraint *outputs,
+          int n_clobber, ident *clobber[], ident *asm_text) {
+       return new_bd_ASM(db, current_ir_graph->current_block, arity, in, inputs, n_outs, outputs, n_clobber, clobber, asm_text);
 }  /* new_d_ASM */
 
 /* ********************************************************************* */
@@ -2943,19 +2655,21 @@ new_d_immBlock(dbg_info *db) {
        res = new_ir_node(db, current_ir_graph, NULL, op_Block, mode_BB, -1, NULL);
        current_ir_graph->current_block = res;
 
-    /* macroblock head */
-    res->in[0] = res;
+       /* macroblock head */
+       res->in[0] = res;
 
        res->attr.block.is_matured  = 0;
        res->attr.block.is_dead     = 0;
-    res->attr.block.is_mb_head  = 1;
+       res->attr.block.is_mb_head  = 1;
+       res->attr.block.has_label   = 0;
        res->attr.block.irg         = current_ir_graph;
        res->attr.block.backedge    = NULL;
        res->attr.block.in_cg       = NULL;
        res->attr.block.cg_backedge = NULL;
        res->attr.block.extblk      = NULL;
        res->attr.block.region      = NULL;
-    res->attr.block.mb_depth    = 0;
+       res->attr.block.mb_depth    = 0;
+       res->attr.block.label       = 0;
 
        set_Block_block_visited(res, 0);
 
@@ -2982,11 +2696,11 @@ new_d_immPartBlock(dbg_info *db, ir_node *pred_jmp) {
        ir_node *blk = get_nodes_block(pred_jmp);
 
        res->in[0] = blk->in[0];
+       add_immBlock_pred(res, pred_jmp);
+
        res->attr.block.is_mb_head = 0;
        res->attr.block.mb_depth = blk->attr.block.mb_depth + 1;
 
-       add_immBlock_pred(res, pred_jmp);
-
        return res;
 }  /* new_d_immPartBlock */
 
@@ -3024,6 +2738,7 @@ get_d_value(dbg_info *db, int pos, ir_mode *mode) {
        ir_graph *irg = current_ir_graph;
        assert(get_irg_phase_state(irg) == phase_building);
        inc_irg_visited(irg);
+       (void) db;
 
        return get_r_value_internal(irg->current_block, pos + 1, mode);
 }  /* get_d_value */
@@ -3204,17 +2919,20 @@ ir_node *new_Minus(ir_node *op,  ir_mode *mode) {
 ir_node *new_Mul(ir_node *op1, ir_node *op2, ir_mode *mode) {
        return new_d_Mul(NULL, op1, op2, mode);
 }
-ir_node *new_Quot(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode) {
-       return new_d_Quot(NULL, memop, op1, op2, mode);
+ir_node *new_Mulh(ir_node *op1, ir_node *op2, ir_mode *mode) {
+       return new_d_Mulh(NULL, op1, op2, mode);
+}
+ir_node *new_Quot(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
+       return new_d_Quot(NULL, memop, op1, op2, mode, state);
 }
-ir_node *new_DivMod(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode) {
-       return new_d_DivMod(NULL, memop, op1, op2, mode);
+ir_node *new_DivMod(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
+       return new_d_DivMod(NULL, memop, op1, op2, mode, state);
 }
-ir_node *new_Div(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode) {
-       return new_d_Div(NULL, memop, op1, op2, mode);
+ir_node *new_Div(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
+       return new_d_Div(NULL, memop, op1, op2, mode, state);
 }
-ir_node *new_Mod(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode) {
-       return new_d_Mod(NULL, memop, op1, op2, mode);
+ir_node *new_Mod(ir_node *memop, ir_node *op1, ir_node *op2, ir_mode *mode, op_pin_state state) {
+       return new_d_Mod(NULL, memop, op1, op2, mode, state);
 }
 ir_node *new_Abs(ir_node *op, ir_mode *mode) {
        return new_d_Abs(NULL, op, mode);
@@ -3297,7 +3015,7 @@ ir_node *new_Bad(void) {
        return new_d_Bad();
 }
 ir_node *new_Confirm(ir_node *val, ir_node *bound, pn_Cmp cmp) {
-       return new_d_Confirm (NULL, val, bound, cmp);
+       return new_d_Confirm(NULL, val, bound, cmp);
 }
 ir_node *new_Unknown(ir_mode *m) {
        return new_d_Unknown(m);
@@ -3341,6 +3059,15 @@ ir_node *new_Bound(ir_node *store, ir_node *idx, ir_node *lower, ir_node *upper)
 ir_node *new_Pin(ir_node *node) {
        return new_d_Pin(NULL, node);
 }
-ir_node *new_ASM(ir_node *store, int arity, ir_node *inputs[], ident *asm_text) {
-       return new_d_ASM(NULL, store, arity, inputs, asm_text);
+ir_node *new_ASM(int arity, ir_node *in[], ir_asm_constraint *inputs,
+                 int n_outs, ir_asm_constraint *outputs,
+                 int n_clobber, ident *clobber[], ident *asm_text) {
+       return new_d_ASM(NULL, arity, in, inputs, n_outs, outputs, n_clobber, clobber, asm_text);
+}
+
+/* create a new anchor node */
+ir_node *new_Anchor(ir_graph *irg) {
+       ir_node *in[anchor_last];
+       memset(in, 0, sizeof(in));
+       return new_ir_node(NULL, irg, NULL, op_Anchor, mode_ANY, anchor_last, in);
 }