fixed doxygen output
[libfirm] / ir / opt / ldstopt.c
index 8664a76..a74aae4 100644 (file)
@@ -36,6 +36,7 @@
 #include "irflag_t.h"
 #include "array.h"
 #include "irhooks.h"
+#include "iredges.h"
 #include "irtools.h"
 #include "opt_polymorphy.h"
 
@@ -169,9 +170,7 @@ static unsigned update_exc(ldst_info_t *info, ir_node *block, int pos)
 }
 
 /** Return the number of uses of an address node */
-#define get_irn_n_uses(adr)     (unsigned)PTR_TO_INT(get_irn_link(adr))
-/** Sets the number of uses of an address node */
-#define set_irn_n_uses(adr, n)  set_irn_link(adr, INT_TO_PTR(n))
+#define get_irn_n_uses(adr)     get_irn_n_edges(adr)
 
 /**
  * walker, collects all Load/Store/Proj nodes
@@ -199,8 +198,6 @@ static void collect_nodes(ir_node *node, void *env)
 
       if ((ldst_info->flags & LDST_VISITED) == 0) {
         adr = get_Load_ptr(pred);
-        set_irn_n_uses(adr, get_irn_n_uses(adr) + 1);
-
         ldst_info->flags |= LDST_VISITED;
       }
 
@@ -224,8 +221,6 @@ static void collect_nodes(ir_node *node, void *env)
 
       if ((ldst_info->flags & LDST_VISITED) == 0) {
         adr = get_Store_ptr(pred);
-        set_irn_n_uses(adr, get_irn_n_uses(adr) + 1);
-
         ldst_info->flags |= LDST_VISITED;
       }
 
@@ -243,7 +238,7 @@ static void collect_nodes(ir_node *node, void *env)
       }
     }
   }
-  else if (op == op_Block) { /* check, if it's an exception block */
+  else if (op == op_Block) {
     int i;
 
     for (i = get_Block_n_cfgpreds(node) - 1; i >= 0; --i) {
@@ -260,7 +255,7 @@ static void collect_nodes(ir_node *node, void *env)
       bl_info    = get_block_info(pred_block, wenv);
 
       if (is_fragile_op(pred))
-             bl_info->flags |= BLOCK_HAS_EXC;
+        bl_info->flags |= BLOCK_HAS_EXC;
       else if (is_irn_forking(pred))
         bl_info->flags |= BLOCK_HAS_COND;
 
@@ -276,7 +271,7 @@ static void collect_nodes(ir_node *node, void *env)
 /**
  * Returns an entity if the address ptr points to a constant one.
  */
-static entity *find_constant_entity(ir_node *ptr)
+static ir_entity *find_constant_entity(ir_node *ptr)
 {
   for (;;) {
     ir_op *op = get_irn_op(ptr);
@@ -285,8 +280,8 @@ static entity *find_constant_entity(ir_node *ptr)
       return get_SymConst_entity(ptr);
     }
     else if (op == op_Sel) {
-      entity  *ent = get_Sel_entity(ptr);
-      ir_type *tp  = get_entity_owner(ent);
+      ir_entity *ent = get_Sel_entity(ptr);
+      ir_type   *tp  = get_entity_owner(ent);
 
       /* Do not fiddle with polymorphism. */
       if (is_Class_type(get_entity_owner(ent)) &&
@@ -355,7 +350,7 @@ static long get_Sel_array_index_long(ir_node *n, int dim) {
  */
 static compound_graph_path *rec_get_accessed_path(ir_node *ptr, int depth) {
   compound_graph_path *res = NULL;
-  entity              *root, *field;
+  ir_entity           *root, *field;
   int                 path_len, pos;
 
   if (get_irn_op(ptr) == op_SymConst) {
@@ -412,6 +407,7 @@ static void handle_load_update(ir_node *load) {
 
     /* a Load which value is neither used nor exception checked, remove it */
     exchange(info->projs[pn_Load_M], mem);
+    exchange(load, new_Bad());
     reduce_adr_usage(ptr);
   }
 }
@@ -421,14 +417,9 @@ static void handle_load_update(ir_node *load) {
  * node and update the counters.
  */
 static void reduce_adr_usage(ir_node *ptr) {
-  int use_count = get_irn_n_uses(ptr);
-  --use_count;
-  assert(use_count >= 0);
-  set_irn_n_uses(ptr, use_count);
-
   if (is_Proj(ptr)) {
-    if (use_count <= 0) {
-      /* this Proj is now dead, update the Load/Store info */
+    if (get_irn_n_edges(ptr) <= 0) {
+      /* this Proj is dead now */
       ir_node *pred = get_Proj_pred(ptr);
       opcode code = get_irn_opcode(pred);
 
@@ -501,6 +492,7 @@ static unsigned follow_Load_chain(ir_node *load, ir_node *curr) {
         if (info->projs[pn_Load_res])
           exchange(info->projs[pn_Load_res], value);
 
+        exchange(load, new_Bad());
         reduce_adr_usage(ptr);
         return res | DF_CHANGED;
       }
@@ -546,6 +538,7 @@ static unsigned follow_Load_chain(ir_node *load, ir_node *curr) {
           res |= CF_CHANGED;
         }
 
+        exchange(load, new_Bad());
         reduce_adr_usage(ptr);
         return res |= DF_CHANGED;
       }
@@ -581,9 +574,8 @@ static unsigned follow_Load_chain(ir_node *load, ir_node *curr) {
 static unsigned optimize_load(ir_node *load)
 {
   ldst_info_t *info = get_irn_link(load);
-  ir_mode *load_mode = get_Load_mode(load);
   ir_node *mem, *ptr, *new_node;
-  entity *ent;
+  ir_entity *ent;
   unsigned res = 0;
 
   /* do NOT touch volatile loads for now */
@@ -607,9 +599,9 @@ static unsigned optimize_load(ir_node *load)
 
       if (get_irn_op(skip_Proj(mem)) == op_Alloc) {
         /* ok, check the types */
-        entity  *ent    = get_Sel_entity(ptr);
-        ir_type *s_type = get_entity_type(ent);
-        ir_type *a_type = get_Alloc_type(mem);
+        ir_entity *ent    = get_Sel_entity(ptr);
+        ir_type   *s_type = get_entity_type(ent);
+        ir_type   *a_type = get_Alloc_type(mem);
 
         if (is_SubClass_of(s_type, a_type)) {
           /* ok, condition met: there can't be an exception because
@@ -641,6 +633,7 @@ static unsigned optimize_load(ir_node *load)
     /* a Load which value is neither used nor exception checked, remove it */
     exchange(info->projs[pn_Load_M], mem);
 
+    exchange(load, new_Bad());
     reduce_adr_usage(ptr);
     return res | DF_CHANGED;
   }
@@ -660,6 +653,7 @@ static unsigned optimize_load(ir_node *load)
     if (info->projs[pn_Load_res])
       exchange(info->projs[pn_Load_res], new_node);
 
+    exchange(load, new_Bad());
     reduce_adr_usage(ptr);
     return res | DF_CHANGED;
   }
@@ -704,6 +698,7 @@ static unsigned optimize_load(ir_node *load)
             res |= DF_CHANGED;
           }
         }
+        exchange(load, new_Bad());
         reduce_adr_usage(ptr);
         return res;
       }
@@ -718,7 +713,7 @@ static unsigned optimize_load(ir_node *load)
           {
             int j;
             for (j = 0; j < get_compound_graph_path_length(path); ++j) {
-              entity *node = get_compound_graph_path_node(path, j);
+              ir_entity *node = get_compound_graph_path_node(path, j);
               fprintf(stdout, ".%s", get_entity_name(node));
               if (is_Array_type(get_entity_owner(node)))
                       fprintf(stdout, "[%d]", get_compound_graph_path_array_index(path, j));
@@ -740,6 +735,7 @@ static unsigned optimize_load(ir_node *load)
             exchange(info->projs[pn_Load_res], copy_const_value(get_irn_dbg_info(load), c));
             res |= DF_CHANGED;
           }
+          exchange(load, new_Bad());
           reduce_adr_usage(ptr);
           return res;
         }
@@ -809,6 +805,7 @@ static unsigned follow_Load_chain_for_Store(ir_node *store, ir_node *curr) {
       if (get_Store_volatility(pred) != volatility_is_volatile && !pred_info->projs[pn_Store_X_except]) {
         DBG_OPT_WAW(pred, store);
         exchange( pred_info->projs[pn_Store_M], get_Store_mem(pred) );
+        exchange(pred, new_Bad());
         reduce_adr_usage(ptr);
         return DF_CHANGED;
       }
@@ -822,6 +819,7 @@ static unsigned follow_Load_chain_for_Store(ir_node *store, ir_node *curr) {
       if (! info->projs[pn_Store_X_except]) {
         DBG_OPT_WAR(store, pred);
         exchange( info->projs[pn_Store_M], mem );
+        exchange(store, new_Bad());
         reduce_adr_usage(ptr);
         return DF_CHANGED;
       }
@@ -855,7 +853,6 @@ static unsigned follow_Load_chain_for_Store(ir_node *store, ir_node *curr) {
  */
 static unsigned optimize_store(ir_node *store)
 {
-  ldst_info_t *info = get_irn_link(store);
   ir_node *ptr, *mem;
 
   if (get_Store_volatility(store) == volatility_is_volatile)
@@ -882,10 +879,10 @@ static unsigned optimize_store(ir_node *store)
  *
  *   val1   val2   val3          val1  val2  val3
  *    |      |      |               \    |    /
- *   Str    Str    Str               \   |   /
+ *  Store  Store  Store              \   |   /
  *      \    |    /                   PhiData
  *       \   |   /                       |
- *        \  |  /                       Str
+ *        \  |  /                      Store
  *          PhiM
  *
  * @endverbatim
@@ -897,9 +894,9 @@ static unsigned optimize_store(ir_node *store)
 static unsigned optimize_phi(ir_node *phi, walk_env_t *wenv)
 {
   int i, n;
-  ir_node *store, *old_store, *ptr, *block, *phiM, *phiD, *exc, *projM;
+  ir_node *store, *old_store, *ptr, *block, *phi_block, *phiM, *phiD, *exc, *projM;
   ir_mode *mode;
-  ir_node **inM, **inD;
+  ir_node **inM, **inD, **stores;
   int *idx;
   dbg_info *db = NULL;
   ldst_info_t *info;
@@ -919,13 +916,20 @@ static unsigned optimize_phi(ir_node *phi, walk_env_t *wenv)
   if (get_irn_op(store) != op_Store)
     return 0;
 
+  block = get_nodes_block(store);
+
   /* abort on dead blocks */
-  if (is_Block_dead(get_nodes_block(store)))
+  if (is_Block_dead(block))
     return 0;
 
-  /* check if the block has only one successor */
-  bl_info = get_irn_link(get_nodes_block(store));
-  if (bl_info->flags)
+  /* check if the block is post dominated by Phi-block
+     and has no exception exit */
+  bl_info = get_irn_link(block);
+  if (bl_info->flags & BLOCK_HAS_EXC)
+    return 0;
+
+  phi_block = get_nodes_block(phi);
+  if (! block_postdominates(phi_block, block))
     return 0;
 
   /* this is the address of the store */
@@ -950,12 +954,18 @@ static unsigned optimize_phi(ir_node *phi, walk_env_t *wenv)
       return 0;
 
     /* abort on dead blocks */
-    if (is_Block_dead(get_nodes_block(store)))
+    block = get_nodes_block(pred);
+    if (is_Block_dead(block))
       return 0;
 
-    /* check if the block has only one successor */
-    bl_info = get_irn_link(get_nodes_block(store));
-    if (bl_info->flags)
+    /* check if the block is post dominated by Phi-block
+       and has no exception exit. Note that block must be different from
+          Phi-block, else we would move a Store from end End of a block to its
+          Start... */
+    bl_info = get_irn_link(block);
+    if (bl_info->flags & BLOCK_HAS_EXC)
+      return 0;
+    if (block == phi_block || ! block_postdominates(phi_block, block))
       return 0;
   }
 
@@ -976,24 +986,42 @@ static unsigned optimize_phi(ir_node *phi, walk_env_t *wenv)
    * Is only allowed if the predecessor blocks have only one successor.
    */
 
-  /* first step: collect all inputs */
+  NEW_ARR_A(ir_node *, stores, n);
   NEW_ARR_A(ir_node *, inM, n);
   NEW_ARR_A(ir_node *, inD, n);
   NEW_ARR_A(int, idx, n);
 
+  /* Prepare: Collect all Store nodes.  We must do this
+     first because we otherwise may loose a store when exchanging its
+     memory Proj.
+   */
+  for (i = 0; i < n; ++i)
+    stores[i] = skip_Proj(get_Phi_pred(phi, i));
+
+  /* Prepare: Skip the memory Proj: we need this in the case some stores
+     are cascaded.
+     Beware: One Store might be included more than once in the stores[]
+     list, so we must prevent to do the exchange more than once.
+   */
   for (i = 0; i < n; ++i) {
-    ir_node *pred = skip_Proj(get_Phi_pred(phi, i));
-    info = get_irn_link(pred);
+    ir_node *store = stores[i];
+    ir_node *proj_m;
 
-    inM[i] = get_Store_mem(pred);
-    inD[i] = get_Store_value(pred);
-    idx[i] = info->exc_idx;
+    info = get_irn_link(store);
+    proj_m = info->projs[pn_Store_M];
 
-    /* Should we here replace the Proj after the Store by
-     * the Store's memory? Would be save but should not be needed,
-     * because we checked that all pred blocks have only one
-     * control flow successor.
-     */
+    if (is_Proj(proj_m) && get_Proj_pred(proj_m) == store)
+      exchange(proj_m, get_Store_mem(store));
+  }
+
+  /* first step: collect all inputs */
+  for (i = 0; i < n; ++i) {
+    ir_node *store = stores[i];
+    info = get_irn_link(store);
+
+    inM[i] = get_Store_mem(store);
+    inD[i] = get_Store_value(store);
+    idx[i] = info->exc_idx;
   }
   block = get_nodes_block(phi);
 
@@ -1008,8 +1036,6 @@ static unsigned optimize_phi(ir_node *phi, walk_env_t *wenv)
 #ifdef DO_CACHEOPT
   co_set_irn_name(store, co_get_irn_ident(old_store));
 #endif
-  /* we replaced n uses by 1 */
-  set_irn_n_uses(ptr, get_irn_n_uses(ptr) - n + 1);
 
   projM = new_rd_Proj(NULL, current_ir_graph, block, store, mode_M, pn_Store_M);
 
@@ -1080,6 +1106,11 @@ void optimize_load_store(ir_graph *irg)
   if (! get_opt_redundant_loadstore())
     return;
 
+  edges_assure(irg);
+
+  /* for Phi optimization post-dominators are needed ... */
+  assure_postdoms(irg);
+
   obstack_init(&env.obst);
   env.changes = 0;