some simple optimizations for execution speed
[libfirm] / ir / ir / irnode.c
index da0cee2..ae0aa29 100644 (file)
@@ -1,25 +1,30 @@
-/* Copyright (C) 1998 - 2000 by Universitaet Karlsruhe
-* All rights reserved.
-*
-* Authors: Martin Trapp, Christian Schaefer, Goetz Lindenmaier
-*
-*/
-
-/* $Id$ */
+/*
+ * Project:     libFIRM
+ * File name:   ir/ir/irnode.c
+ * Purpose:     Representation of an intermediate operation.
+ * Author:      Martin Trapp, Christian Schaefer
+ * Modified by: Goetz Lindenmaier
+ * Created:
+ * CVS-ID:      $Id$
+ * Copyright:   (c) 1998-2003 Universität Karlsruhe
+ * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
+ */
 
 #ifdef HAVE_CONFIG_H
 # include <config.h>
 #endif
 #include <string.h>
 
+#include "ident.h"
 #include "irnode_t.h"
 #include "irgraph_t.h"
 #include "irmode_t.h"
-#include "typegmod_t.h"
+#include "typegmod.h"
 #include "array.h"
 #include "irbackedge_t.h"
 #include "irdump.h"
 #include "irflag.h"
+#include "irop_t.h"
 
 #ifdef DEBUG_libfirm
 #include "irprog_t.h"
@@ -148,20 +153,32 @@ is_ir_node (void *thing) {
 
 /* returns the number of predecessors without the block predecessor. */
 INLINE int
-get_irn_arity (const ir_node *node) {
+get_irn_intra_arity (const ir_node *node) {
   assert(node);
-  if (interprocedural_view) { /* handle Filter and Block specially */
-    if (get_irn_opcode(node) == iro_Filter) {
-      assert(node->attr.filter.in_cg);
-      return ARR_LEN(node->attr.filter.in_cg) - 1;
-    } else if (get_irn_opcode(node) == iro_Block && node->attr.block.in_cg) {
-      return ARR_LEN(node->attr.block.in_cg) - 1;
-    }
-    /* else fall through */
-  }
   return ARR_LEN(node->in) - 1;
 }
 
+/* returns the number of predecessors without the block predecessor. */
+INLINE int
+get_irn_inter_arity (const ir_node *node) {
+  assert(node);
+  if (get_irn_opcode(node) == iro_Filter) {
+    assert(node->attr.filter.in_cg);
+    return ARR_LEN(node->attr.filter.in_cg) - 1;
+  } else if (get_irn_opcode(node) == iro_Block && node->attr.block.in_cg) {
+    return ARR_LEN(node->attr.block.in_cg) - 1;
+  }
+  return get_irn_intra_arity(node);
+}
+
+/* returns the number of predecessors without the block predecessor. */
+INLINE int
+get_irn_arity (const ir_node *node) {
+  assert(node);
+  if (interprocedural_view) return get_irn_inter_arity(node);
+  return get_irn_intra_arity(node);
+}
+
 /* Returns the array with ins. This array is shifted with respect to the
    array accessed by get_irn_n: The block operand is at position 0 not -1.
    (@@@ This should be changed.)
@@ -208,6 +225,24 @@ set_irn_in (ir_node *node, int arity, ir_node **in) {
   memcpy((*arr) + 1, in, sizeof(ir_node *) * arity);
 }
 
+INLINE ir_node *
+get_irn_intra_n (ir_node *node, int n) {
+  return (node->in[n + 1] = skip_nop(node->in[n + 1]));
+}
+
+INLINE ir_node*
+get_irn_inter_n (ir_node *node, int n) {
+  /* handle Filter and Block specially */
+  if (get_irn_opcode(node) == iro_Filter) {
+    assert(node->attr.filter.in_cg);
+    return (node->attr.filter.in_cg[n + 1] = skip_nop(node->attr.filter.in_cg[n + 1]));
+  } else if (get_irn_opcode(node) == iro_Block && node->attr.block.in_cg) {
+    return (node->attr.block.in_cg[n + 1] = skip_nop(node->attr.block.in_cg[n + 1]));
+  }
+
+  return get_irn_intra_n (node, n);
+}
+
 /* to iterate through the predecessors without touching the array */
 /* To iterate over the operands iterate from 0 to i < get_irn_arity(),
    to iterate includind the Block predecessor iterate from i = -1 to
@@ -215,24 +250,12 @@ set_irn_in (ir_node *node, int arity, ir_node **in) {
    If it is a block, the entry -1 is NULL. */
 INLINE ir_node *
 get_irn_n (ir_node *node, int n) {
-  /* debug @@@
-  if (-1 > n || get_irn_arity(node) <= n) {
-    printf("pos: %d, arity: %d ", n, get_irn_arity(node));
-    DDMN(node);
-    } */
   assert(node); assert(-1 <= n && n < get_irn_arity(node));
-  if (interprocedural_view) { /* handle Filter and Block specially */
-    if (get_irn_opcode(node) == iro_Filter) {
-      assert(node->attr.filter.in_cg);
-      return (node->attr.filter.in_cg[n + 1] = skip_nop(node->attr.filter.in_cg[n + 1]));
-    } else if (get_irn_opcode(node) == iro_Block && node->attr.block.in_cg) {
-      return (node->attr.block.in_cg[n + 1] = skip_nop(node->attr.block.in_cg[n + 1]));
-    }
-    /* else fall through */
-  }
-  return (node->in[n + 1] = skip_nop(node->in[n + 1]));
+  if (interprocedural_view)  return get_irn_inter_n (node, n);
+  return get_irn_intra_n (node, n);
 }
 
+
 INLINE void
 set_irn_n (ir_node *node, int n, ir_node *in) {
   assert(node && -1 <= n && n < get_irn_arity(node));
@@ -279,6 +302,13 @@ get_irn_modecode (const ir_node *node)
   return node->mode->code;
 }
 
+/** Gets the string representation of the mode .*/
+INLINE const char *
+get_irn_modename (const ir_node *node)
+{
+  assert(node);
+  return get_mode_name(node->mode);
+}
 
 INLINE ident *
 get_irn_modeident (const ir_node *node)
@@ -315,7 +345,7 @@ INLINE const char *
 get_irn_opname (const ir_node *node)
 {
   assert(node);
-  return id_to_str(node->op->name);
+  return get_id_str(node->op->name);
 }
 
 INLINE ident *
@@ -380,11 +410,11 @@ get_irn_node_nr(const ir_node *node) {
 #ifdef DEBUG_libfirm
   return node->node_nr;
 #else
-  return 0;
+  return (long)&node;
 #endif
 }
 
-INLINE tarval *
+INLINE const_attr
 get_irn_const_attr (ir_node *node)
 {
   assert (node->op == op_Const);
@@ -462,6 +492,42 @@ set_nodes_Block (ir_node *node, ir_node *block) {
   set_irn_n(node, -1, block);
 }
 
+/* Test whether arbitrary node is frame pointer, i.e. Proj(pn_Start_P_frame_base)
+ * from Start.  If so returns frame type, else Null. */
+type *is_frame_pointer(ir_node *n) {
+  if ((get_irn_op(n) == op_Proj) &&
+      (get_Proj_proj(n) == pn_Start_P_frame_base)) {
+    ir_node *start = get_Proj_pred(n);
+    if (get_irn_op(start) == op_Start) {
+      return get_irg_frame_type(get_irn_irg(start));
+    }
+  }
+  return NULL;
+}
+
+/* Test whether arbitrary node is globals pointer, i.e. Proj(pn_Start_P_globals)
+ * from Start.  If so returns global type, else Null. */
+type *is_globals_pointer(ir_node *n) {
+  if ((get_irn_op(n) == op_Proj) &&
+      (get_Proj_proj(n) == pn_Start_P_globals)) {
+    ir_node *start = get_Proj_pred(n);
+    if (get_irn_op(start) == op_Start) {
+      return get_glob_type();
+    }
+  }
+  return NULL;
+}
+
+/* Test whether arbitrary node is value arg base, i.e. Proj(pn_Start_P_value_arg_base)
+ * from Start.  If so returns 1, else 0. */
+int is_value_arg_pointer(ir_node *n) {
+  if ((get_irn_op(n) == op_Proj) &&
+      (get_Proj_proj(n) == pn_Start_P_value_arg_base) &&
+      (get_irn_op(get_Proj_pred(n)) == op_Start))
+    return 1;
+  return 0;
+}
+
 /* Returns an array with the predecessors of the Block. Depending on
    the implementation of the graph datastructure this can be a copy of
    the internal representation of predecessors as well as the internal
@@ -547,7 +613,7 @@ set_Block_graph_arr (ir_node *node, int pos, ir_node *value) {
   node->attr.block.graph_arr[pos+1] = value;
 }
 
-/* handler handling for Blocks */
+/* handler handling for Blocks * /
 void
 set_Block_handler (ir_node *block, ir_node *handler)  {
   assert ((block->op == op_Block));
@@ -561,7 +627,7 @@ get_Block_handler (ir_node *block) {
   return (block->attr.block.handler_entry);
 }
 
-/* handler handling for Nodes */
+/ * handler handling for Nodes * /
 void
 set_Node_handler (ir_node *node, ir_node *handler) {
   set_Block_handler (get_nodes_Block (node), handler);
@@ -572,7 +638,7 @@ get_Node_handler (ir_node *node) {
   return (get_Block_handler (get_nodes_Block (node)));
 }
 
-/* exc_t handling for Blocks */
+/ * exc_t handling for Blocks * /
 void set_Block_exc (ir_node *block, exc_t exc) {
   assert ((block->op == op_Block));
   block->attr.block.exc = exc;
@@ -580,11 +646,10 @@ void set_Block_exc (ir_node *block, exc_t exc) {
 
 exc_t get_Block_exc (ir_node *block) {
   assert ((block->op == op_Block));
-
   return (block->attr.block.exc);
 }
 
-/* exc_t handling for Nodes */
+/ * exc_t handling for Nodes * /
 void set_Node_exc (ir_node *node, exc_t exc) {
   set_Block_exc (get_nodes_Block (node), exc);
 }
@@ -592,6 +657,7 @@ void set_Node_exc (ir_node *node, exc_t exc) {
 exc_t get_Node_exc (ir_node *node) {
   return (get_Block_exc (get_nodes_Block (node)));
 }
+*/
 
 void set_Block_cg_cfgpred_arr(ir_node * node, int arity, ir_node ** in) {
   assert(node->op == op_Block);
@@ -638,6 +704,20 @@ void remove_Block_cg_cfgpred_arr(ir_node * node) {
   node->attr.block.in_cg = NULL;
 }
 
+/* Start references the irg it is in. */
+INLINE ir_graph *
+get_Start_irg(ir_node *node) {
+  return get_irn_irg(node);
+}
+
+INLINE void
+set_Start_irg(ir_node *node, ir_graph *irg) {
+  assert(node->op == op_Start);
+  assert(is_ir_graph(irg));
+  assert(0 && " Why set irg? ");
+  //node->attr.start.irg = irg;
+}
+
 INLINE int
 get_End_n_keepalives(ir_node *end) {
   assert (end->op == op_End);
@@ -665,19 +745,18 @@ set_End_keepalive(ir_node *end, int pos, ir_node *ka) {
 INLINE void
 free_End (ir_node *end) {
   assert (end->op == op_End);
-  /* DEL_ARR_F(end->in);   GL @@@ tut nicht ! */
+  end->kind = k_BAD;
+  DEL_ARR_F(end->in);  /* GL @@@ tut nicht ! */
   end->in = NULL;   /* @@@ make sure we get an error if we use the
                       in array afterwards ... */
 }
 
-ir_graph *get_EndReg_irg (const ir_node *end) {
-  assert (end->op == op_EndReg);
-  return end->attr.end.irg;
+ir_graph *get_EndReg_irg (ir_node *end) {
+  return get_irn_irg(end);
 }
 
-ir_graph *get_EndExcept_irg  (const ir_node *end) {
-  assert (end->op == op_EndReg);
-  return end->attr.end.irg;
+ir_graph *get_EndExcept_irg  (ir_node *end) {
+  return get_irn_irg(end);
 }
 
 /*
@@ -785,7 +864,7 @@ set_Return_res (ir_node *node, int pos, ir_node *res){
 
 INLINE ir_node *
 get_Raise_mem (ir_node *node) {
-  assert (node->op == op_Return);
+  assert (node->op == op_Raise);
   return get_irn_n(node, 0);
 }
 
@@ -809,15 +888,41 @@ set_Raise_exo_ptr (ir_node *node, ir_node *exo_ptr) {
 
 INLINE tarval *get_Const_tarval (ir_node *node) {
   assert (node->op == op_Const);
-  return get_irn_const_attr(node);
+  return node->attr.con.tv;
 }
 
 INLINE void
 set_Const_tarval (ir_node *node, tarval *con) {
   assert (node->op == op_Const);
-  node->attr.con = con;
+  node->attr.con.tv = con;
+}
+
+
+/* The source language type.  Must be an atomic type.  Mode of type must
+   be mode of node. For tarvals from entities type must be pointer to
+   entity type. */
+INLINE type *
+get_Const_type (ir_node *node) {
+  assert (node->op == op_Const);
+  return node->attr.con.tp;
+}
+
+INLINE void
+set_Const_type (ir_node *node, type *tp) {
+  assert (node->op == op_Const);
+  if (tp != unknown_type) {
+    assert (is_atomic_type(tp));
+    assert (get_type_mode(tp) == get_irn_mode(node));
+    assert (!tarval_is_entity(get_Const_tarval(node)) ||
+           (is_pointer_type(tp) &&
+            (get_pointer_points_to_type(tp) ==
+             get_entity_type(get_tarval_entity(get_Const_tarval(node))))));
+  }
+
+  node->attr.con.tp = tp;
 }
 
+
 INLINE symconst_kind
 get_SymConst_kind (const ir_node *node) {
   assert (node->op == op_SymConst);
@@ -976,7 +1081,7 @@ set_InstOf_obj (ir_node *node, ir_node *obj) {
 /* For unary and binary arithmetic operations the access to the
    operands can be factored out.  Left is the first, right the
    second arithmetic value  as listed in tech report 0999-33.
-   unops are: Minus, Abs, Not, Conv
+   unops are: Minus, Abs, Not, Conv, Cast
    binops are: Add, Sub, Mul, Quot, DivMod, Div, Mod, And, Or, Eor, Shl,
    Shr, Shrs, Rotate, Cmp */
 
@@ -1054,6 +1159,10 @@ set_Call_type (ir_node *node, type *tp) {
   node->attr.call.cld_tp = tp;
 }
 
+int Call_has_callees(ir_node *node) {
+  return (node->attr.call.callee_arr != NULL);
+}
+
 int get_Call_n_callees(ir_node * node) {
   assert(node->op == op_Call && node->attr.call.callee_arr);
   return ARR_LEN(node->attr.call.callee_arr);
@@ -1086,8 +1195,7 @@ void set_CallBegin_ptr (ir_node *node, ir_node *ptr) {
   set_irn_n(node, 0, ptr);
 }
 ir_graph * get_CallBegin_irg (ir_node *node) {
-  assert(node->op == op_CallBegin);
-  return node->attr.callbegin.irg;
+  return get_irn_irg(node);
 }
 ir_node * get_CallBegin_call (ir_node *node) {
   assert(node->op == op_CallBegin);
@@ -1558,50 +1666,67 @@ set_Conv_op (ir_node *node, ir_node *op) {
   set_irn_n(node, 0, op);
 }
 
+INLINE ir_node *
+get_Cast_op (ir_node *node) {
+  assert (node->op == op_Cast);
+  return get_irn_n(node, 0);
+}
 
+INLINE void
+set_Cast_op (ir_node *node, ir_node *op) {
+  assert (node->op == op_Cast);
+  set_irn_n(node, 0, op);
+}
 
-int
+INLINE type *
+get_Cast_type (ir_node *node) {
+  assert (node->op == op_Cast);
+  return node->attr.cast.totype;
+}
+
+INLINE void
+set_Cast_type (ir_node *node, type *to_tp) {
+  assert (node->op == op_Cast);
+  node->attr.cast.totype = to_tp;
+}
+
+INLINE int
 is_unop (ir_node *node) {
-  return ( node->op == op_Minus ||
-           node->op == op_Abs  ||
-          node->op == op_Not  ||
-           node->op == op_Conv );
+  return (node->op->opar == oparity_unary);
 }
 
 INLINE ir_node *
 get_unop_op (ir_node *node) {
-  assert ( node->op == op_Minus ||
-           node->op == op_Abs  ||
-           node->op == op_Not  ||
-           node->op == op_Conv );
+  assert (is_unop(node));
   switch (get_irn_opcode (node)) {
     case iro_Minus: return get_Minus_op(node); break;
     case iro_Abs:   return get_Abs_op(node);   break;
     case iro_Not:   return get_Not_op(node);   break;
     case iro_Conv:  return get_Conv_op(node);  break;
+    case iro_Cast:  return get_Cast_op(node);  break;
     default: return NULL;
   }
 }
 
 INLINE void
 set_unop_op (ir_node *node, ir_node *op) {
-    assert (node->op == op_Minus ||
-           node->op == op_Abs   ||
-           node->op == op_Not   ||
-           node->op == op_Conv    );
-    switch (get_irn_opcode (node)) {
+  assert (is_unop(node));
+  switch (get_irn_opcode (node)) {
     case iro_Minus:   set_Minus_op(node, op); break;
     case iro_Abs:     set_Abs_op(node, op);   break;
     case iro_Not:     set_Not_op(node, op);   break;
     case iro_Conv:    set_Conv_op(node, op);  break;
+    case iro_Cast:    set_Cast_op(node, op);  break;
     default:  ;
-    }
+  }
 
 }
 
 int
 is_binop (ir_node *node) {
-  return (node->op == op_Add    ||
+  return (node->op->opar == oparity_binary);
+  /*  return (node->op == op_Add    ||
+          node->op == op_Cmp    ||
           node->op == op_Sub    ||
           node->op == op_Mul    ||
           node->op == op_Quot   ||
@@ -1614,27 +1739,13 @@ is_binop (ir_node *node) {
           node->op == op_Shl    ||
           node->op == op_Shr    ||
           node->op == op_Shrs   ||
-         node->op == op_Rot    ||
-          node->op == op_Cmp      );
+         node->op == op_Rot      );
+  */
 }
 
 INLINE ir_node *
 get_binop_left (ir_node *node) {
-  assert (node->op == op_Add    ||
-          node->op == op_Sub    ||
-          node->op == op_Mul    ||
-          node->op == op_Quot   ||
-          node->op == op_DivMod ||
-          node->op == op_Div    ||
-          node->op == op_Mod    ||
-          node->op == op_And    ||
-          node->op == op_Or     ||
-          node->op == op_Eor    ||
-          node->op == op_Shl    ||
-          node->op == op_Shr    ||
-          node->op == op_Shrs   ||
-         node->op == op_Rot    ||
-          node->op == op_Cmp      );
+  assert (node->op->opar == oparity_binary);
 
     switch (get_irn_opcode (node)) {
       case iro_Add   :     return get_Add_left(node);  break;
@@ -1658,21 +1769,7 @@ get_binop_left (ir_node *node) {
 
 INLINE void
 set_binop_left (ir_node *node, ir_node *left) {
-  assert (node->op == op_Add    ||
-          node->op == op_Sub    ||
-          node->op == op_Mul    ||
-          node->op == op_Quot   ||
-          node->op == op_DivMod ||
-          node->op == op_Div    ||
-          node->op == op_Mod    ||
-          node->op == op_And    ||
-          node->op == op_Or     ||
-          node->op == op_Eor    ||
-          node->op == op_Shl    ||
-          node->op == op_Shr    ||
-         node->op == op_Shrs   ||
-         node->op == op_Rot    ||
-          node->op == op_Cmp      );
+  assert (node->op->opar == oparity_binary);
 
     switch (get_irn_opcode (node)) {
       case iro_Add   :     set_Add_left(node, left);  break;
@@ -1696,21 +1793,7 @@ set_binop_left (ir_node *node, ir_node *left) {
 
 INLINE ir_node *
 get_binop_right (ir_node *node) {
-  assert (node->op == op_Add    ||
-          node->op == op_Sub    ||
-          node->op == op_Mul    ||
-          node->op == op_Quot   ||
-          node->op == op_DivMod ||
-          node->op == op_Div    ||
-          node->op == op_Mod    ||
-          node->op == op_And    ||
-          node->op == op_Or     ||
-          node->op == op_Eor    ||
-          node->op == op_Shl    ||
-          node->op == op_Shr    ||
-          node->op == op_Shrs   ||
-          node->op == op_Rot    ||
-          node->op == op_Cmp      );
+  assert (node->op->opar == oparity_binary);
 
     switch (get_irn_opcode (node)) {
       case iro_Add   :     return get_Add_right(node);  break;
@@ -1734,21 +1817,7 @@ get_binop_right (ir_node *node) {
 
 INLINE void
 set_binop_right (ir_node *node, ir_node *right) {
-  assert (node->op == op_Add    ||
-          node->op == op_Sub    ||
-          node->op == op_Mul    ||
-          node->op == op_Quot   ||
-          node->op == op_DivMod ||
-          node->op == op_Div    ||
-          node->op == op_Mod    ||
-          node->op == op_And    ||
-          node->op == op_Or     ||
-          node->op == op_Eor    ||
-          node->op == op_Shl    ||
-          node->op == op_Shr    ||
-          node->op == op_Shrs   ||
-          node->op == op_Rot    ||
-          node->op == op_Cmp      );
+  assert (node->op->opar == oparity_binary);
 
     switch (get_irn_opcode (node)) {
       case iro_Add   :     set_Add_right(node, right);  break;
@@ -1770,6 +1839,11 @@ set_binop_right (ir_node *node, ir_node *right) {
   };
 }
 
+INLINE int is_Phi (ir_node *n) {
+  assert(n);
+  return ((get_irn_op(n) == op_Phi) ||
+         (get_irn_op(n) == op_Filter && interprocedural_view));
+}
 
 INLINE ir_node **
 get_Phi_preds_arr (ir_node *node) {
@@ -1779,7 +1853,7 @@ get_Phi_preds_arr (ir_node *node) {
 
 INLINE int
 get_Phi_n_preds (ir_node *node) {
-  assert (node->op == op_Phi);
+  assert (is_Phi(node));
   return (get_irn_arity(node));
 }
 
@@ -1791,13 +1865,13 @@ INLINE void set_Phi_n_preds (ir_node *node, int n_preds) {
 
 INLINE ir_node *
 get_Phi_pred (ir_node *node, int pos) {
-  assert (node->op == op_Phi);
+  assert (is_Phi(node));
   return get_irn_n(node, pos);
 }
 
 INLINE void
 set_Phi_pred (ir_node *node, int pos, ir_node *pred) {
-  assert (node->op == op_Phi);
+  assert (is_Phi(node));
   set_irn_n(node, pos, pred);
 }
 
@@ -2062,6 +2136,31 @@ set_Id_pred (ir_node *node, ir_node *pred) {
   set_irn_n(node, 0, pred);
 }
 
+INLINE ir_node *get_Confirm_value (ir_node *node) {
+  assert (node->op == op_Confirm);
+  return get_irn_n(node, 0);
+}
+INLINE void     set_Confirm_value (ir_node *node, ir_node *value) {
+  assert (node->op == op_Confirm);
+  set_irn_n(node, 0, value);
+}
+INLINE ir_node *get_Confirm_bound (ir_node *node) {
+  assert (node->op == op_Confirm);
+  return get_irn_n(node, 1);
+}
+INLINE void     set_Confirm_bound (ir_node *node, ir_node *bound) {
+  assert (node->op == op_Confirm);
+  set_irn_n(node, 0, bound);
+}
+INLINE pn_Cmp   get_Confirm_cmp   (ir_node *node) {
+  assert (node->op == op_Confirm);
+  return node->attr.confirm_cmp;
+}
+INLINE void     set_Confirm_cmp   (ir_node *node, pn_Cmp cmp) {
+  assert (node->op == op_Confirm);
+  node->attr.confirm_cmp = cmp;
+}
+
 
 INLINE ir_node *
 get_Filter_pred (ir_node *node) {
@@ -2118,15 +2217,10 @@ ir_node *get_Filter_cg_pred(ir_node *node, int pos) {
 
 INLINE ir_graph *
 get_irn_irg(ir_node *node) {
-  if (get_irn_op(node) == op_CallBegin) {
-    return node->attr.callbegin.irg;
-  } else if (get_irn_op(node) == op_EndReg ||
-            get_irn_op(node) == op_EndExcept) {
-    return node->attr.end.irg;
-  } else {
-    assert(0 && "no irg attr");
-    return NULL;
-  }
+  if (get_irn_op(node) != op_Block)
+    node = get_nodes_block(node);
+  assert(get_irn_op(node) == op_Block);
+  return node->attr.block.irg;
 }
 
 
@@ -2161,6 +2255,7 @@ skip_Tuple (ir_node *node) {
   return node;
 }
 
+#if 0
 /* This should compact Id-cycles to self-cycles. It has the same (or less?) complexity
    than any other approach, as Id chains are resolved and all point to the real node, or
    all id's are self loops. */
@@ -2188,6 +2283,40 @@ skip_nop (ir_node *node) {
     return node;
   }
 }
+#else
+/* This should compact Id-cycles to self-cycles. It has the same (or less?) complexity
+   than any other approach, as Id chains are resolved and all point to the real node, or
+   all id's are self loops. */
+extern int opt_normalize;
+INLINE ir_node *
+skip_nop (ir_node *node) {
+  ir_node *pred;
+  /* don't assert node !!! */
+
+  if (!opt_normalize) return node;
+
+  /* Don't use get_Id_pred:  We get into an endless loop for
+     self-referencing Ids. */
+  if (node && (node->op == op_Id) && (node != (pred = node->in[0+1]))) {
+    if (pred->op != op_Id) return pred; /* shortcut */
+    ir_node *rem_pred = pred;
+    ir_node *res;
+
+    assert (get_irn_arity (node) > 0);
+
+    node->in[0+1] = node;
+    res = skip_nop(rem_pred);
+    if (res->op == op_Id) /* self-loop */ return node;
+
+    node->in[0+1] = res;
+    return res;
+  } else {
+    return node;
+  }
+}
+#endif
+
+
 
 INLINE ir_node *
 skip_Id (ir_node *node) {
@@ -2214,6 +2343,13 @@ is_Block (ir_node *node) {
   return (get_irn_opcode(node) == iro_Block);
 }
 
+/* returns true if node is a Unknown node. */
+INLINE int
+is_Unknown (ir_node *node) {
+  assert(node);
+  return (get_irn_opcode(node) == iro_Unknown);
+}
+
 INLINE int
 is_Proj (const ir_node *node) {
   assert(node);
@@ -2234,17 +2370,7 @@ INLINE int is_ip_cfop(ir_node *node) {
 }
 
 ir_graph *get_ip_cfop_irg(ir_node *n) {
-  switch (get_irn_opcode(n)) {
-  case iro_EndReg:
-    return get_EndReg_irg(n);
-  case iro_EndExcept:
-    return get_EndExcept_irg(n);
-  case iro_CallBegin:
-    return get_CallBegin_irg(n);
-  default:
-    assert(is_ip_cfop(n));
-  }
-  return NULL; /* should never be reached */
+  return get_irn_irg(n);
 }
 
 /* Returns true if the operation can change the control flow because