renamed to firm_init_reflect()
[libfirm] / ir / ir / irgopt.c
index 659fe09..603fc02 100644 (file)
 
 
 #ifdef HAVE_CONFIG_H
-# include <config.h>
+# include "config.h"
 #endif
 
 #include <assert.h>
-#include <stdbool.h>
 
 #include "irnode_t.h"
 #include "irgraph_t.h"
@@ -32,6 +31,7 @@
 #include "pset.h"
 #include "eset.h"
 #include "pdeq.h"       /* Fuer code placement */
+#include "xmalloc.h"
 
 #include "irouts.h"
 #include "irloop_t.h"
@@ -39,7 +39,8 @@
 #include "cgana.h"
 
 #include "irflag_t.h"
-#include "firmstat.h"
+#include "irhooks.h"
+#include "iredges_t.h"
 
 /* Defined in iropt.c */
 pset *new_identities (void);
@@ -207,9 +208,11 @@ static INLINE void new_backedge_info(ir_node *n) {
  *
  * @param n    The node to be copied
  * @param env  if non-NULL, the node number attribute will be copied to the new node
+ *
+ * Note: Also used for loop unrolling.
  */
 static void
-copy_node (ir_node *n, void *env) {
+firm_copy_node (ir_node *n, void *env) {
   ir_node *nn, *block;
   int new_arity;
   opcode op = get_irn_opcode(n);
@@ -245,7 +248,7 @@ copy_node (ir_node *n, void *env) {
   /* Copy the attributes.  These might point to additional data.  If this
      was allocated on the old obstack the pointers now are dangling.  This
      frees e.g. the memory of the graph_arr allocated in new_immBlock. */
-  copy_attrs(n, nn);
+  copy_node_attr(n, nn);
   new_backedge_info(nn);
   set_new_node(n, nn);
 
@@ -264,7 +267,7 @@ copy_node (ir_node *n, void *env) {
  * Copies new predecessors of old node to new node remembered in link.
  * Spare the Bad predecessors of Phi and Block nodes.
  */
-static void
+void
 copy_preds (ir_node *n, void *env) {
   ir_node *nn, *block;
   int i, j, irn_arity;
@@ -343,7 +346,7 @@ copy_preds (ir_node *n, void *env) {
  */
 static void
 copy_graph (int copy_node_nr) {
-  ir_node *oe, *ne, *ob, *nb; /* old end, new end, old bad, new bad */
+  ir_node *oe, *ne, *ob, *nb, *om, *nm; /* old end, new end, old bad, new bad, old NoMem, new NoMem */
   ir_node *ka;      /* keep alive */
   int i, irn_arity;
 
@@ -357,9 +360,10 @@ copy_graph (int copy_node_nr) {
            -1,
            NULL);
   /* Copy the attributes.  Well, there might be some in the future... */
-  copy_attrs(oe, ne);
+  copy_node_attr(oe, ne);
   set_new_node(oe, ne);
 
+  /* copy the Bad node */
   ob = get_irg_bad(current_ir_graph);
   nb =  new_ir_node(get_irn_dbg_info(ob),
            current_ir_graph,
@@ -370,8 +374,19 @@ copy_graph (int copy_node_nr) {
            NULL);
   set_new_node(ob, nb);
 
+  /* copy the NoMem node */
+  om = get_irg_no_mem(current_ir_graph);
+  nm =  new_ir_node(get_irn_dbg_info(om),
+           current_ir_graph,
+           NULL,
+           op_NoMem,
+           mode_M,
+           0,
+           NULL);
+  set_new_node(om, nm);
+
   /* copy the live nodes */
-  irg_walk(get_nodes_block(oe), copy_node, copy_preds, (void *)copy_node_nr);
+  irg_walk(get_nodes_block(oe), firm_copy_node, copy_preds, (void *)copy_node_nr);
   /* copy_preds for the end node ... */
   set_nodes_block(ne, get_new_node(get_nodes_block(oe)));
 
@@ -385,7 +400,7 @@ copy_graph (int copy_node_nr) {
         (get_irn_visited(ka) < get_irg_visited(current_ir_graph))) {
       /* We must keep the block alive and copy everything reachable */
       set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
-      irg_walk(ka, copy_node, copy_preds, (void *)copy_node_nr);
+      irg_walk(ka, firm_copy_node, copy_preds, (void *)copy_node_nr);
       add_End_keepalive(ne, get_new_node(ka));
     }
   }
@@ -398,14 +413,15 @@ copy_graph (int copy_node_nr) {
       if (get_irn_visited(ka) < get_irg_visited(current_ir_graph)) {
         /* We didn't copy the Phi yet.  */
         set_irg_visited(current_ir_graph, get_irg_visited(current_ir_graph)-1);
-        irg_walk(ka, copy_node, copy_preds, (void *)copy_node_nr);
+        irg_walk(ka, firm_copy_node, copy_preds, (void *)copy_node_nr);
       }
       add_End_keepalive(ne, get_new_node(ka));
     }
   }
 
-  /* start block somtimes only reached after keep alives */
+  /* start block sometimes only reached after keep alives */
   set_nodes_block(nb, get_new_node(get_nodes_block(ob)));
+  set_nodes_block(nm, get_new_node(get_nodes_block(om)));
 }
 
 /**
@@ -426,6 +442,7 @@ copy_graph_env (int copy_node_nr) {
   set_irn_link(get_irg_globals    (current_ir_graph), NULL);
   set_irn_link(get_irg_args       (current_ir_graph), NULL);
   set_irn_link(get_irg_initial_mem(current_ir_graph), NULL);
+  set_irn_link(get_irg_no_mem     (current_ir_graph), NULL);
 
   /* we use the block walk flag for removing Bads from Blocks ins. */
   inc_irg_block_visited(current_ir_graph);
@@ -441,19 +458,19 @@ copy_graph_env (int copy_node_nr) {
   free_End(old_end);
   set_irg_end_block  (current_ir_graph, get_new_node(get_irg_end_block(current_ir_graph)));
   if (get_irn_link(get_irg_frame(current_ir_graph)) == NULL) {
-    copy_node (get_irg_frame(current_ir_graph), (void *)copy_node_nr);
+    firm_copy_node (get_irg_frame(current_ir_graph), (void *)copy_node_nr);
     copy_preds(get_irg_frame(current_ir_graph), NULL);
   }
   if (get_irn_link(get_irg_globals(current_ir_graph)) == NULL) {
-    copy_node (get_irg_globals(current_ir_graph), (void *)copy_node_nr);
+    firm_copy_node (get_irg_globals(current_ir_graph), (void *)copy_node_nr);
     copy_preds(get_irg_globals(current_ir_graph), NULL);
   }
   if (get_irn_link(get_irg_initial_mem(current_ir_graph)) == NULL) {
-    copy_node (get_irg_initial_mem(current_ir_graph), (void *)copy_node_nr);
+    firm_copy_node (get_irg_initial_mem(current_ir_graph), (void *)copy_node_nr);
     copy_preds(get_irg_initial_mem(current_ir_graph), NULL);
   }
   if (get_irn_link(get_irg_args(current_ir_graph)) == NULL) {
-    copy_node (get_irg_args(current_ir_graph), (void *)copy_node_nr);
+    firm_copy_node (get_irg_args(current_ir_graph), (void *)copy_node_nr);
     copy_preds(get_irg_args(current_ir_graph), NULL);
   }
   set_irg_start      (current_ir_graph, get_new_node(get_irg_start(current_ir_graph)));
@@ -466,10 +483,16 @@ copy_graph_env (int copy_node_nr) {
   set_irg_args       (current_ir_graph, get_new_node(get_irg_args(current_ir_graph)));
 
   if (get_irn_link(get_irg_bad(current_ir_graph)) == NULL) {
-    copy_node(get_irg_bad(current_ir_graph), (void *)copy_node_nr);
+    firm_copy_node(get_irg_bad(current_ir_graph), (void *)copy_node_nr);
     copy_preds(get_irg_bad(current_ir_graph), NULL);
   }
   set_irg_bad(current_ir_graph, get_new_node(get_irg_bad(current_ir_graph)));
+
+  if (get_irn_link(get_irg_no_mem(current_ir_graph)) == NULL) {
+    firm_copy_node(get_irg_no_mem(current_ir_graph), (void *)copy_node_nr);
+    copy_preds(get_irg_no_mem(current_ir_graph), NULL);
+  }
+  set_irg_no_mem(current_ir_graph, get_new_node(get_irg_no_mem(current_ir_graph)));
 }
 
 /**
@@ -487,8 +510,10 @@ dead_node_elimination(ir_graph *irg) {
   struct obstack *graveyard_obst = NULL;
   struct obstack *rebirth_obst   = NULL;
 
+       edges_init_graph(irg);
+
   /* inform statistics that we started a dead-node elimination run */
-  stat_dead_node_elim_start(irg);
+  hook_dead_node_elim_start(irg);
 
   /* Remember external state of current_ir_graph. */
   rem = current_ir_graph;
@@ -509,7 +534,7 @@ dead_node_elimination(ir_graph *irg) {
     graveyard_obst = irg->obst;
 
     /* A new obstack, where the reachable nodes will be copied to. */
-    rebirth_obst = (struct obstack *) xmalloc (sizeof (struct obstack));
+    rebirth_obst = xmalloc (sizeof(*rebirth_obst));
     current_ir_graph->obst = rebirth_obst;
     obstack_init (current_ir_graph->obst);
 
@@ -526,7 +551,7 @@ dead_node_elimination(ir_graph *irg) {
   }
 
   /* inform statistics that the run is over */
-  stat_dead_node_elim_stop(irg);
+  hook_dead_node_elim_stop(irg);
 
   current_ir_graph = rem;
   set_interprocedural_view(rem_ipview);
@@ -558,17 +583,25 @@ static void relink_bad_block_predecessors(ir_node *n, void *env) {
 
     /* arity changing: set new predecessors without bad nodes */
     if (new_irn_arity < old_irn_arity) {
-      /* get new predecessor array without Block predecessor */
+      /* Get new predecessor array. We do not resize the array, as we must
+        keep the old one to update Phis. */
       new_in = NEW_ARR_D (ir_node *, current_ir_graph->obst, (new_irn_arity+1));
 
       /* set new predeseccors in array */
       new_in[0] = NULL;
       new_irn_n = 1;
-      for (i = 1; i < old_irn_arity; i++) {
-    irn = get_irn_n(n, i);
-    if (!is_Bad(irn)) new_in[new_irn_n++] = irn;
+      for (i = 0; i < old_irn_arity; i++) {
+       irn = get_irn_n(n, i);
+       if (!is_Bad(irn)) {
+         new_in[new_irn_n] = irn;
+         is_backedge(n, i) ? set_backedge(n, new_irn_n-1) : set_not_backedge(n, new_irn_n-1);
+         new_irn_n++;
+       }
       }
+      //ARR_SETLEN(int, n->attr.block.backedge, new_irn_arity);
+      ARR_SHRINKLEN(n->attr.block.backedge, new_irn_arity);
       n->in = new_in;
+
     } /* ir node has bad predecessors */
 
   } /* Block is not relinked */
@@ -603,18 +636,23 @@ static void relink_bad_predecessors(ir_node *n, void *env) {
     /* Relink Phi predeseccors if count of predeseccors changed */
     if (old_irn_arity != ARR_LEN(get_irn_in(block))) {
       /* set new predeseccors in array
-     n->in[0] remains the same block */
+        n->in[0] remains the same block */
       new_irn_arity = 1;
       for(i = 1; i < old_irn_arity; i++)
-    if (!is_Bad((ir_node *)old_in[i])) n->in[new_irn_arity++] = n->in[i];
+       if (!is_Bad((ir_node *)old_in[i])) {
+         n->in[new_irn_arity] = n->in[i];
+         is_backedge(n, i) ? set_backedge(n, new_irn_arity) : set_not_backedge(n, new_irn_arity);
+         new_irn_arity++;
+       }
 
       ARR_SETLEN(ir_node *, n->in, new_irn_arity);
+      ARR_SETLEN(int, n->attr.phi_backedge, new_irn_arity);
     }
 
   } /* n is a Phi node */
 }
 
-/**
+/*
  * Removes Bad Bad predecesors from Blocks and the corresponding
  * inputs to Phi nodes as in dead_node_elimination but without
  * copying the graph.
@@ -636,7 +674,7 @@ void remove_bad_predecessors(ir_graph *irg) {
  * Copy node for inlineing.  Updates attributes that change when
  * inlineing but not for dead node elimination.
  *
- * Copies the node by calling copy_node and then updates the entity if
+ * Copies the node by calling firm_copy_node and then updates the entity if
  * it's a local one.  env must be a pointer of the frame type of the
  * inlined procedure. The new entities must be in the link field of
  * the entities.
@@ -646,7 +684,7 @@ copy_node_inline (ir_node *n, void *env) {
   ir_node *new;
   type *frame_tp = (type *)env;
 
-  copy_node(n, NULL);
+  firm_copy_node(n, NULL);
   if (get_irn_op(n) == op_Sel) {
     new = get_new_node (n);
     assert(get_irn_op(new) == op_Sel);
@@ -678,7 +716,7 @@ static int can_inline(ir_node *call, ir_graph *called_graph)
 {
   type *call_type = get_Call_type(call);
   int params, ress, i, res;
-  assert(is_method_type(call_type));
+  assert(is_Method_type(call_type));
 
   params = get_method_n_params(call_type);
   ress   = get_method_n_ress(call_type);
@@ -747,6 +785,7 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
   if (get_irg_outs_state(current_ir_graph) == outs_consistent)
     set_irg_outs_inconsistent(current_ir_graph);
   set_irg_loopinfo_inconsistent(current_ir_graph);
+  set_irg_callee_info_state(current_ir_graph, irg_callee_info_inconsistent);
 
   /* -- Check preconditions -- */
   assert(get_irn_op(call) == op_Call);
@@ -762,7 +801,7 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
   }
 
   /* here we know we WILL inline, so inform the statistics */
-  stat_inline(call, called_graph);
+  hook_inline(call, called_graph);
 
   /* -- Decide how to handle exception control flow: Is there a handler
      for the Call node, or do we branch directly to End on an exception?
@@ -873,8 +912,8 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
   arity = get_irn_arity(end_bl);    /* arity = n_exc + n_ret  */
   n_res = get_method_n_ress(get_Call_type(call));
 
-  res_pred = (ir_node **) malloc (n_res * sizeof (ir_node *));
-  cf_pred =  (ir_node **) malloc (arity * sizeof (ir_node *));
+  res_pred = xmalloc (n_res * sizeof(*res_pred));
+  cf_pred  = xmalloc (arity * sizeof(*res_pred));
 
   set_irg_current_block(current_ir_graph, post_bl); /* just to make sure */
 
@@ -884,7 +923,7 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
     add_End_keepalive(get_irg_end(current_ir_graph), get_irn_n(end, i));
 
   /* The new end node will die.  We need not free as the in array is on the obstack:
-     copy_node only generated 'D' arrays. */
+     firm_copy_node only generated 'D' arrays. */
 
   /* -- Replace Return nodes by Jump nodes. -- */
   n_ret = 0;
@@ -1005,7 +1044,7 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
     }
     main_end_bl = get_irg_end_block(current_ir_graph);
     main_end_bl_arity = get_irn_arity(main_end_bl);
-    end_preds =  (ir_node **) malloc ((n_exc + main_end_bl_arity) * sizeof (ir_node *));
+    end_preds =  xmalloc ((n_exc + main_end_bl_arity) * sizeof(*end_preds));
 
     for (i = 0; i < main_end_bl_arity; ++i)
       end_preds[i] = get_irn_n(main_end_bl, i);
@@ -1049,7 +1088,7 @@ int inline_method(ir_node *call, ir_graph *called_graph) {
     if (i < get_Block_n_cfgpreds(end_bl)) {
       bl = get_nodes_block(cf_op);
       arity = get_Block_n_cfgpreds(end_bl) + get_Block_n_cfgpreds(bl) - 1;
-      cf_pred = (ir_node **) malloc (arity * sizeof (ir_node *));
+      cf_pred = xmalloc (arity * sizeof(*cf_pred));
       for (j = 0; j < i; j++)
         cf_pred[j] = get_Block_cfgpred(end_bl, j);
       for (j = j; j < i + get_Block_n_cfgpreds(bl); j++)
@@ -1157,7 +1196,7 @@ void inline_small_irgs(ir_graph *irg, int size) {
     for (i = 0; i < env.pos; i++) {
       ir_graph *callee;
       callee = get_entity_irg(get_SymConst_entity(get_Call_ptr(env.calls[i])));
-      if (((_obstack_memory_used(callee->obst) - obstack_room(callee->obst)) < size) ||
+      if (((_obstack_memory_used(callee->obst) - (int)obstack_room(callee->obst)) < size) ||
         (get_irg_inline_property(callee) == irg_inline_forced)) {
         inline_method(env.calls[i], callee);
       }
@@ -1181,7 +1220,7 @@ typedef struct {
 } inline_irg_env;
 
 static inline_irg_env *new_inline_irg_env(void) {
-  inline_irg_env *env = malloc(sizeof(inline_irg_env));
+  inline_irg_env *env = xmalloc(sizeof(*env));
   env->n_nodes = -2; /* uncount Start, End */
   env->n_nodes_orig = -2; /* uncount Start, End */
   env->call_nodes = eset_create();
@@ -1248,7 +1287,7 @@ void inline_leave_functions(int maxsize, int leavesize, int size) {
 
   if (!(get_opt_optimize() && get_opt_inline())) return;
 
-  /* extend all irgs by a temporary data structure for inlineing. */
+  /* extend all irgs by a temporary data structure for inlining. */
   for (i = 0; i < n_irgs; ++i)
     set_irg_link(get_irp_irg(i), new_inline_irg_env());
 
@@ -1276,8 +1315,10 @@ void inline_leave_functions(int maxsize, int leavesize, int size) {
       env = (inline_irg_env *)get_irg_link(current_ir_graph);
 
       for (call = eset_first(env->call_nodes); call; call = eset_next(env->call_nodes)) {
+        ir_graph *callee;
+
         if (get_irn_op(call) == op_Tuple) continue;   /* We already inlined. */
-        ir_graph *callee = get_call_called_irg(call);
+        callee = get_call_called_irg(call);
 
         if (env->n_nodes > maxsize) continue; // break;
 
@@ -1314,8 +1355,10 @@ void inline_leave_functions(int maxsize, int leavesize, int size) {
     walkset = env->call_nodes;
     env->call_nodes = eset_create();
     for (call = eset_first(walkset); call; call = eset_next(walkset)) {
+      ir_graph *callee;
+
       if (get_irn_op(call) == op_Tuple) continue;   /* We already inlined. */
-      ir_graph *callee = get_call_called_irg(call);
+      callee = get_call_called_irg(call);
 
       if (callee &&
           ((is_smaller(callee, size) && (env->n_nodes < maxsize)) ||    /* small function */
@@ -1462,6 +1505,21 @@ static INLINE void place_early(pdeq *worklist) {
   current_ir_graph->op_pin_state_pinned = op_pin_state_pinned;
 }
 
+/** Compute the deepest common ancestor of block and dca. */
+static ir_node *calc_dca(ir_node *dca, ir_node *block)
+{
+  assert(block);
+  if (!dca) return block;
+  while (get_Block_dom_depth(block) > get_Block_dom_depth(dca))
+    block = get_Block_idom(block);
+  while (get_Block_dom_depth(dca) > get_Block_dom_depth(block)) {
+    dca = get_Block_idom(dca);
+  }
+  while (block != dca)
+    { block = get_Block_idom(block); dca = get_Block_idom(dca); }
+
+  return dca;
+}
 
 /** Deepest common dominance ancestor of DCA and CONSUMER of PRODUCER.
  * I.e., DCA is the block where we might place PRODUCER.
@@ -1483,7 +1541,9 @@ consumer_dom_dca (ir_node *dca, ir_node *consumer, ir_node *producer)
 
     for (i = 0;  i < irn_arity; i++) {
       if (get_irn_n(consumer, i) == producer) {
-        block = get_nodes_block(get_Block_cfgpred(phi_block, i));
+        ir_node *new_block = get_nodes_block(get_Block_cfgpred(phi_block, i));
+
+        block = calc_dca(block, new_block);
       }
     }
   } else {
@@ -1492,17 +1552,7 @@ consumer_dom_dca (ir_node *dca, ir_node *consumer, ir_node *producer)
   }
 
   /* Compute the deepest common ancestor of block and dca. */
-  assert(block);
-  if (!dca) return block;
-  while (get_Block_dom_depth(block) > get_Block_dom_depth(dca))
-    block = get_Block_idom(block);
-  while (get_Block_dom_depth(dca) > get_Block_dom_depth(block)) {
-    dca = get_Block_idom(dca);
-  }
-  while (block != dca)
-    { block = get_Block_idom(block); dca = get_Block_idom(dca); }
-
-  return dca;
+  return calc_dca(dca, block);
 }
 
 static INLINE int get_irn_loop_depth(ir_node *n) {
@@ -1617,8 +1667,9 @@ place_floats_late(ir_node *n, pdeq *worklist)
   /* Add predecessors of all non-floating nodes on list. (Those of floating
      nodes are placeded already and therefore are marked.)  */
   for (i = 0; i < get_irn_n_outs(n); i++) {
+    ir_node *succ = get_irn_out(n, i);
     if (irn_not_visited(get_irn_out(n, i))) {
-      pdeq_putr (worklist, get_irn_out(n, i));
+      pdeq_putr (worklist, succ);
     }
   }
 }