some simple optimizations for execution speed
[libfirm] / ir / ir / irnode.c
index fa12ad8..ae0aa29 100644 (file)
@@ -24,6 +24,7 @@
 #include "irbackedge_t.h"
 #include "irdump.h"
 #include "irflag.h"
+#include "irop_t.h"
 
 #ifdef DEBUG_libfirm
 #include "irprog_t.h"
@@ -152,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.)
@@ -212,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
@@ -219,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));
@@ -283,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)
@@ -587,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));
@@ -601,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);
@@ -612,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;
@@ -620,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);
 }
@@ -632,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);
@@ -681,15 +707,15 @@ void remove_Block_cg_cfgpred_arr(ir_node * node) {
 /* Start references the irg it is in. */
 INLINE ir_graph *
 get_Start_irg(ir_node *node) {
-  assert(node->op == op_Start);
-  return node->attr.start.irg;
+  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));
-  node->attr.start.irg = irg;
+  assert(0 && " Why set irg? ");
+  //node->attr.start.irg = irg;
 }
 
 INLINE int
@@ -720,19 +746,17 @@ INLINE void
 free_End (ir_node *end) {
   assert (end->op == op_End);
   end->kind = k_BAD;
-  /* DEL_ARR_F(end->in);   GL @@@ tut nicht ! */
+  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);
 }
 
 /*
@@ -1135,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);
@@ -1167,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);
@@ -1665,11 +1692,7 @@ set_Cast_type (ir_node *node, type *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 ||
-           node->op == op_Cast );
+  return (node->op->opar == oparity_unary);
 }
 
 INLINE ir_node *
@@ -1701,7 +1724,9 @@ set_unop_op (ir_node *node, ir_node *op) {
 
 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   ||
@@ -1714,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;
@@ -1758,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;
@@ -1796,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;
@@ -1834,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;
@@ -1870,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) {
@@ -1879,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));
 }
 
@@ -1891,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);
 }
 
@@ -2243,17 +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 if (get_irn_op(node) == op_Start) {
-    return node->attr.start.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;
 }
 
 
@@ -2288,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. */
@@ -2315,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) {
@@ -2341,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);
@@ -2361,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