OSDN Git Service

* configure.ac (gcc_cv_nm): Don't use an in-tree nm if
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-loop-im.c
index 810f3cf..4dcda9f 100644 (file)
@@ -15,8 +15,8 @@ for more details.
    
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -102,7 +102,7 @@ struct lim_aux_data
 
 #define LIM_DATA(STMT) (TREE_CODE (STMT) == PHI_NODE \
                        ? NULL \
-                       : (struct lim_aux_data *) (stmt_ann (STMT)->aux))
+                       : (struct lim_aux_data *) (stmt_ann (STMT)->common.aux))
 
 /* Description of a memory reference location for store motion.  */
 
@@ -124,6 +124,13 @@ struct mem_ref
   struct mem_ref_loc *locs;    /* The locations where it is found.  */
   bitmap vops;                 /* Vops corresponding to this memory
                                   location.  */
+  struct mem_ref *next;                /* Next memory reference in the list.
+                                  Memory references are stored in a hash
+                                  table, but the hash function depends
+                                  on values of pointers. Thus we cannot use
+                                  htab_traverse, since then we would get
+                                  miscompares during bootstrap (although the
+                                  produced code would be correct).  */
 };
 
 /* Minimum cost of an expensive expression.  */
@@ -194,6 +201,21 @@ for_each_index (tree *addr_p, bool (*cbck) (tree, tree *, void *), void *data)
        case PARM_DECL:
        case STRING_CST:
        case RESULT_DECL:
+       case VECTOR_CST:
+       case COMPLEX_CST:
+       case INTEGER_CST:
+       case REAL_CST:
+         return true;
+
+       case TARGET_MEM_REF:
+         idx = &TMR_BASE (*addr_p);
+         if (*idx
+             && !cbck (*addr_p, idx, data))
+           return false;
+         idx = &TMR_INDEX (*addr_p);
+         if (*idx
+             && !cbck (*addr_p, idx, data))
+           return false;
          return true;
 
        default:
@@ -379,7 +401,7 @@ add_dependency (tree def, struct lim_aux_data *data, struct loop *loop,
       && def_bb->loop_father == loop)
     data->cost += LIM_DATA (def_stmt)->cost;
 
-  dep = xmalloc (sizeof (struct depend));
+  dep = XNEW (struct depend);
   dep->stmt = def_stmt;
   dep->next = data->depends;
   data->depends = dep;
@@ -590,6 +612,7 @@ determine_invariantness_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
          && (rhs = TREE_OPERAND (stmt, 1)) != NULL
          && TREE_CODE (rhs) == RDIV_EXPR
          && flag_unsafe_math_optimizations
+         && !flag_trapping_math
          && outermost_invariant_loop_expr (TREE_OPERAND (rhs, 1),
                                            loop_containing_stmt (stmt)) != NULL
          && outermost_invariant_loop_expr (rhs,
@@ -620,11 +643,11 @@ determine_invariantness_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
          bsi_insert_after (&bsi, stmt2, BSI_NEW_STMT);
          SSA_NAME_DEF_STMT (lhs) = stmt2;
 
-         /* Continue processing with invariant reciprocal statment.  */
+         /* Continue processing with invariant reciprocal statement.  */
          stmt = stmt1;
        }
 
-      stmt_ann (stmt)->aux = xcalloc (1, sizeof (struct lim_aux_data));
+      stmt_ann (stmt)->common.aux = xcalloc (1, sizeof (struct lim_aux_data));
       LIM_DATA (stmt)->always_executed_in = outermost;
 
       if (maybe_never && pos == MOVE_PRESERVE_EXECUTION)
@@ -715,7 +738,7 @@ move_computations_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
       cost = LIM_DATA (stmt)->cost;
       level = LIM_DATA (stmt)->tgt_loop;
       free_lim_aux_data (LIM_DATA (stmt));
-      stmt_ann (stmt)->aux = NULL;
+      stmt_ann (stmt)->common.aux = NULL;
 
       if (!level)
        {
@@ -736,7 +759,7 @@ move_computations_stmt (struct dom_walk_data *dw_data ATTRIBUTE_UNUSED,
                   cost, level->num);
        }
       bsi_insert_on_edge (loop_preheader_edge (level), stmt);
-      bsi_remove (&bsi);
+      bsi_remove (&bsi, false);
     }
 }
 
@@ -864,7 +887,7 @@ force_move_till (tree ref, tree *index, void *data)
 static void
 record_mem_ref_loc (struct mem_ref_loc **mem_refs, tree stmt, tree *ref)
 {
-  struct mem_ref_loc *aref = xmalloc (sizeof (struct mem_ref_loc));
+  struct mem_ref_loc *aref = XNEW (struct mem_ref_loc);
 
   aref->stmt = stmt;
   aref->ref = ref;
@@ -906,6 +929,109 @@ rewrite_mem_refs (tree tmp_var, struct mem_ref_loc *mem_refs)
     }
 }
 
+/* The name and the length of the currently generated variable
+   for lsm.  */
+#define MAX_LSM_NAME_LENGTH 40
+static char lsm_tmp_name[MAX_LSM_NAME_LENGTH + 1];
+static int lsm_tmp_name_length;
+
+/* Adds S to lsm_tmp_name.  */
+
+static void
+lsm_tmp_name_add (const char *s)
+{
+  int l = strlen (s) + lsm_tmp_name_length;
+  if (l > MAX_LSM_NAME_LENGTH)
+    return;
+
+  strcpy (lsm_tmp_name + lsm_tmp_name_length, s);
+  lsm_tmp_name_length = l;
+}
+
+/* Stores the name for temporary variable that replaces REF to
+   lsm_tmp_name.  */
+
+static void
+gen_lsm_tmp_name (tree ref)
+{
+  const char *name;
+
+  switch (TREE_CODE (ref))
+    {
+    case MISALIGNED_INDIRECT_REF:
+    case ALIGN_INDIRECT_REF:
+    case INDIRECT_REF:
+      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+      lsm_tmp_name_add ("_");
+      break;
+
+    case BIT_FIELD_REF:
+    case VIEW_CONVERT_EXPR:
+    case ARRAY_RANGE_REF:
+      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+      break;
+
+    case REALPART_EXPR:
+      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+      lsm_tmp_name_add ("_RE");
+      break;
+      
+    case IMAGPART_EXPR:
+      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+      lsm_tmp_name_add ("_IM");
+      break;
+
+    case COMPONENT_REF:
+      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+      lsm_tmp_name_add ("_");
+      name = get_name (TREE_OPERAND (ref, 1));
+      if (!name)
+       name = "F";
+      lsm_tmp_name_add ("_");
+      lsm_tmp_name_add (name);
+
+    case ARRAY_REF:
+      gen_lsm_tmp_name (TREE_OPERAND (ref, 0));
+      lsm_tmp_name_add ("_I");
+      break;
+
+    case SSA_NAME:
+      ref = SSA_NAME_VAR (ref);
+      /* Fallthru.  */
+
+    case VAR_DECL:
+    case PARM_DECL:
+      name = get_name (ref);
+      if (!name)
+       name = "D";
+      lsm_tmp_name_add (name);
+      break;
+
+    case STRING_CST:
+      lsm_tmp_name_add ("S");
+      break;
+
+    case RESULT_DECL:
+      lsm_tmp_name_add ("R");
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
+/* Determines name for temporary variable that replaces REF.
+   The name is accumulated into the lsm_tmp_name variable.  */
+
+static char *
+get_lsm_tmp_name (tree ref)
+{
+  lsm_tmp_name_length = 0;
+  gen_lsm_tmp_name (ref);
+  lsm_tmp_name_add ("_lsm");
+  return lsm_tmp_name;
+}
+
 /* Records request for store motion of memory reference REF from LOOP.
    MEM_REFS is the list of occurrences of the reference REF inside LOOP;
    these references are rewritten by a new temporary variable.
@@ -931,7 +1057,8 @@ schedule_sm (struct loop *loop, edge *exits, unsigned n_exits, tree ref,
       fprintf (dump_file, " from loop %d\n", loop->num);
     }
 
-  tmp_var = make_rename_temp (TREE_TYPE (ref), "lsm_tmp");
+  tmp_var = make_rename_temp (TREE_TYPE (ref),
+                             get_lsm_tmp_name (ref));
 
   fmt_data.loop = loop;
   fmt_data.orig_loop = loop;
@@ -943,8 +1070,8 @@ schedule_sm (struct loop *loop, edge *exits, unsigned n_exits, tree ref,
       LIM_DATA (aref->stmt)->sm_done = true;
 
   /* Emit the load & stores.  */
-  load = build (MODIFY_EXPR, void_type_node, tmp_var, ref);
-  get_stmt_ann (load)->aux = xcalloc (1, sizeof (struct lim_aux_data));
+  load = build2 (MODIFY_EXPR, void_type_node, tmp_var, ref);
+  get_stmt_ann (load)->common.aux = xcalloc (1, sizeof (struct lim_aux_data));
   LIM_DATA (load)->max_loop = loop;
   LIM_DATA (load)->tgt_loop = loop;
 
@@ -954,8 +1081,8 @@ schedule_sm (struct loop *loop, edge *exits, unsigned n_exits, tree ref,
 
   for (i = 0; i < n_exits; i++)
     {
-      store = build (MODIFY_EXPR, void_type_node,
-                    unshare_expr (ref), tmp_var);
+      store = build2 (MODIFY_EXPR, void_type_node,
+                     unshare_expr (ref), tmp_var);
       bsi_insert_on_edge (exits[i], store);
     }
 }
@@ -1018,28 +1145,18 @@ determine_lsm_ref (struct loop *loop, edge *exits, unsigned n_exits,
   schedule_sm (loop, exits, n_exits, ref->mem, ref->locs);
 }
 
-/* Attempts to hoist memory reference described in SLOT out of loop
-   described in DATA.  Callback for htab_traverse.  */
-
-struct hmr_data
-{
-  struct loop *loop;   /* Loop from that the reference should be hoisted.  */
-  edge *exits;         /* Exits of the loop.  */
-  unsigned n_exits;    /* Length of the exits array.  */
-  bitmap clobbered_vops;/* The vops clobbered by call in loop or accessed by
-                          multiple memory references.  */
-};
+/* Hoists memory references MEM_REFS out of LOOP.  CLOBBERED_VOPS is the list
+   of vops clobbered by call in loop or accessed by multiple memory references.
+   EXITS is the list of N_EXITS exit edges of the LOOP.  */
 
-static int
-hoist_memory_reference (void **slot, void *data)
+static void
+hoist_memory_references (struct loop *loop, struct mem_ref *mem_refs,
+                        bitmap clobbered_vops, edge *exits, unsigned n_exits)
 {
-  struct mem_ref *ref = *slot;
-  struct hmr_data *hmr_data = data;
-
-  determine_lsm_ref (hmr_data->loop, hmr_data->exits, hmr_data->n_exits,
-                    hmr_data->clobbered_vops, ref);
+  struct mem_ref *ref;
 
-  return 1;
+  for (ref = mem_refs; ref; ref = ref->next)
+    determine_lsm_ref (loop, exits, n_exits, clobbered_vops, ref);
 }
 
 /* Checks whether LOOP (with N_EXITS exits stored in EXITS array) is suitable
@@ -1080,25 +1197,15 @@ memref_eq (const void *obj1, const void *obj2)
   return operand_equal_p (mem1->mem, (tree) obj2, 0);
 }
 
-/* A function to free the struct mem_ref object OBJ.  */
-
-static void
-memref_del (void *obj)
-{
-  struct mem_ref *mem = obj;
-
-  free_mem_ref_locs (mem->locs);
-  BITMAP_FREE (mem->vops);
-  free (mem);
-}
-
 /* Gathers memory references in statement STMT in LOOP, storing the
    information about them in MEM_REFS hash table.  Note vops accessed through
-   unrecognized statements in CLOBBERED_VOPS.  */
+   unrecognized statements in CLOBBERED_VOPS.  The newly created references
+   are also stored to MEM_REF_LIST.  */
 
 static void
 gather_mem_refs_stmt (struct loop *loop, htab_t mem_refs,
-                     bitmap clobbered_vops, tree stmt)
+                     bitmap clobbered_vops, tree stmt,
+                     struct mem_ref **mem_ref_list)
 {
   tree *lhs, *rhs, *mem = NULL;
   hashval_t hash;
@@ -1151,81 +1258,104 @@ gather_mem_refs_stmt (struct loop *loop, htab_t mem_refs,
     ref = *slot;
   else
     {
-      ref = xmalloc (sizeof (struct mem_ref));
+      ref = XNEW (struct mem_ref);
       ref->mem = *mem;
       ref->hash = hash;
       ref->locs = NULL;
       ref->is_stored = false;
       ref->vops = BITMAP_ALLOC (NULL);
+      ref->next = *mem_ref_list;
+      *mem_ref_list = ref;
       *slot = ref;
     }
   ref->is_stored |= is_stored;
 
   FOR_EACH_SSA_TREE_OPERAND (vname, stmt, oi,
                             SSA_OP_VIRTUAL_USES | SSA_OP_VIRTUAL_KILLS)
-    {
-      bitmap_set_bit (ref->vops,
-                     var_ann (SSA_NAME_VAR (vname))->uid);
-    }
+    bitmap_set_bit (ref->vops, DECL_UID (SSA_NAME_VAR (vname)));
   record_mem_ref_loc (&ref->locs, stmt, mem);
   return;
 
 fail:
   FOR_EACH_SSA_TREE_OPERAND (vname, stmt, oi,
                             SSA_OP_VIRTUAL_USES | SSA_OP_VIRTUAL_KILLS)
-    {
-      bitmap_set_bit (clobbered_vops,
-                     var_ann (SSA_NAME_VAR (vname))->uid);
-    }
+    bitmap_set_bit (clobbered_vops, DECL_UID (SSA_NAME_VAR (vname)));
 }
 
-/* Gathers memory references in LOOP, storing the information about them
-   in MEM_REFS hash table.  Note vops accessed through unrecognized
-   statements in CLOBBERED_VOPS.  */
+/* Gathers memory references in LOOP.  Notes vops accessed through unrecognized
+   statements in CLOBBERED_VOPS.  The list of the references found by
+   the function is returned.  */
 
-static void
-gather_mem_refs (struct loop *loop, htab_t mem_refs, bitmap clobbered_vops)
+static struct mem_ref *
+gather_mem_refs (struct loop *loop, bitmap clobbered_vops)
 {
   basic_block *body = get_loop_body (loop);
   block_stmt_iterator bsi;
   unsigned i;
+  struct mem_ref *mem_ref_list = NULL;
+  htab_t mem_refs = htab_create (100, memref_hash, memref_eq, NULL);
 
   for (i = 0; i < loop->num_nodes; i++)
     {
       for (bsi = bsi_start (body[i]); !bsi_end_p (bsi); bsi_next (&bsi))
-       gather_mem_refs_stmt (loop, mem_refs, clobbered_vops, bsi_stmt (bsi));
+       gather_mem_refs_stmt (loop, mem_refs, clobbered_vops, bsi_stmt (bsi),
+                             &mem_ref_list);
     }
 
   free (body);
+
+  htab_delete (mem_refs);
+  return mem_ref_list;
 }
 
-/* Finds the vops accessed by memory reference described in SLOT as well as
-   some other reference(s) and marks them in DATA->clobbered_vops.
-   Callback for htab_traverse.  */
+/* Finds the vops accessed by more than one of the memory references described
+   in MEM_REFS and marks them in CLOBBERED_VOPS.  */
 
-struct fmrv_data
+static void
+find_more_ref_vops (struct mem_ref *mem_refs, bitmap clobbered_vops)
 {
-  bitmap clobbered_vops;       /* The vops clobbered by call in loop or accessed by
-                          multiple memory references.  */
-  bitmap all_vops;     /* All vops referenced in the loop.  */
-};
+  bitmap_head tmp, all_vops;
+  struct mem_ref *ref;
 
-static int
-find_more_ref_vops (void **slot, void *data)
+  bitmap_initialize (&tmp, &bitmap_default_obstack);
+  bitmap_initialize (&all_vops, &bitmap_default_obstack);
+
+  for (ref = mem_refs; ref; ref = ref->next)
+    {
+      /* The vops that are already in all_vops are accessed by more than
+        one memory reference.  */
+      bitmap_and (&tmp, &all_vops, ref->vops);
+      bitmap_ior_into (clobbered_vops, &tmp);
+      bitmap_clear (&tmp);
+
+      bitmap_ior_into (&all_vops, ref->vops);
+    }
+
+  bitmap_clear (&all_vops);
+}
+
+/* Releases the memory occupied by REF.  */
+
+static void
+free_mem_ref (struct mem_ref *ref)
 {
-  struct mem_ref *ref = *slot;
-  struct fmrv_data *fmrv_data = data;
-  bitmap_head tmp;
+  free_mem_ref_locs (ref->locs);
+  BITMAP_FREE (ref->vops);
+  free (ref);
+}
 
-  /* The vops that are already in all_vops are accessed by more than
-     one memory reference.  */
-  bitmap_initialize (&tmp, &bitmap_default_obstack);
-  bitmap_and (&tmp, fmrv_data->all_vops, ref->vops);
-  bitmap_ior_into (fmrv_data->clobbered_vops, &tmp);
-  bitmap_clear (&tmp);
+/* Releases the memory occupied by REFS.  */
+
+static void
+free_mem_refs (struct mem_ref *refs)
+{
+  struct mem_ref *ref, *next;
 
-  bitmap_ior_into (fmrv_data->all_vops, ref->vops);
-  return 1;
+  for (ref = refs; ref; ref = next)
+    {
+      next = ref->next;
+      free_mem_ref (ref);
+    }
 }
 
 /* Try to perform store motion for all memory references modified inside
@@ -1236,10 +1366,8 @@ determine_lsm_loop (struct loop *loop)
 {
   unsigned n_exits;
   edge *exits = get_loop_exit_edges (loop, &n_exits);
-  htab_t mem_refs;
-  struct hmr_data hmr_data;
-  struct fmrv_data fmrv_data;
   bitmap clobbered_vops;
+  struct mem_ref *mem_refs;
 
   if (!loop_suitable_for_sm (loop, exits, n_exits))
     {
@@ -1247,26 +1375,17 @@ determine_lsm_loop (struct loop *loop)
       return;
     }
 
-  mem_refs = htab_create (100, memref_hash, memref_eq, memref_del);
-
   /* Find the memory references in LOOP.  */
   clobbered_vops = BITMAP_ALLOC (NULL);
-  gather_mem_refs (loop, mem_refs, clobbered_vops);
+  mem_refs = gather_mem_refs (loop, clobbered_vops);
 
   /* Find the vops that are used for more than one reference.  */
-  fmrv_data.all_vops = BITMAP_ALLOC (NULL);
-  fmrv_data.clobbered_vops = clobbered_vops;
-  htab_traverse (mem_refs, find_more_ref_vops, &fmrv_data);
-  BITMAP_FREE (fmrv_data.all_vops);
+  find_more_ref_vops (mem_refs, clobbered_vops);
 
   /* Hoist all suitable memory references.  */
-  hmr_data.loop = loop;
-  hmr_data.exits = exits;
-  hmr_data.n_exits = n_exits;
-  hmr_data.clobbered_vops = clobbered_vops;
-  htab_traverse (mem_refs, hoist_memory_reference, &hmr_data);
+  hoist_memory_references (loop, mem_refs, clobbered_vops, exits, n_exits);
 
-  htab_delete (mem_refs);
+  free_mem_refs (mem_refs);
   free (exits);
   BITMAP_FREE (clobbered_vops);
 }