OSDN Git Service

* de.po, zh_CN.po: Update.
[pf3gnuchains/gcc-fork.git] / gcc / tree-vect-analyze.c
index 5caf832..7529eff 100644 (file)
@@ -1,4 +1,4 @@
-/* Anlaysis Utilities for Loop Vectorization.
+/* Analysis Utilities for Loop Vectorization.
    Copyright (C) 2003,2004,2005 Free Software Foundation, Inc.
    Contributed by Dorit Naishlos <dorit@il.ibm.com>
 
@@ -50,10 +50,11 @@ static bool vect_analyze_data_refs_alignment (loop_vec_info);
 static bool vect_compute_data_refs_alignment (loop_vec_info);
 static void vect_enhance_data_refs_alignment (loop_vec_info);
 static bool vect_analyze_operations (loop_vec_info);
+static bool vect_determine_vectorization_factor (loop_vec_info);
 
 /* Utility functions for the analyses.  */
 static bool exist_non_indexing_operands_for_use_p (tree, tree);
-static void vect_mark_relevant (varray_type *, tree);
+static void vect_mark_relevant (VEC(tree,heap) **, tree);
 static bool vect_stmt_relevant_p (tree, loop_vec_info);
 static tree vect_get_loop_niters (struct loop *, tree *);
 static bool vect_analyze_data_ref_dependence
@@ -70,7 +71,8 @@ static bool vect_base_addr_differ_p (struct data_reference *,
                                     struct data_reference *drb, bool *);
 static tree vect_object_analysis (tree, tree, bool, tree, 
                                  struct data_reference **, tree *, tree *, 
-                                 tree *, bool *, tree *);
+                                 tree *, bool *, tree *, struct ptr_info_def **,
+                                 subvar_t *);
 static tree vect_address_analysis (tree, tree, bool, tree, 
                                   struct data_reference *, tree *, tree *, 
                                   tree *, bool *);
@@ -285,6 +287,150 @@ vect_analyze_offset_expr (tree expr,
 }
 
 
+/* Function vect_determine_vectorization_factor
+
+   Determine the vectorization factor (VF). VF is the number of data elements
+   that are operated upon in parallel in a single iteration of the vectorized
+   loop. For example, when vectorizing a loop that operates on 4byte elements,
+   on a target with vector size (VS) 16byte, the VF is set to 4, since 4
+   elements can fit in a single vector register.
+
+   We currently support vectorization of loops in which all types operated upon
+   are of the same size. Therefore this function currently sets VF according to
+   the size of the types operated upon, and fails if there are multiple sizes
+   in the loop.
+
+   VF is also the factor by which the loop iterations are strip-mined, e.g.:
+   original loop:
+        for (i=0; i<N; i++){
+          a[i] = b[i] + c[i];
+        }
+
+   vectorized loop:
+        for (i=0; i<N; i+=VF){
+          a[i:VF] = b[i:VF] + c[i:VF];
+        }
+*/
+
+static bool
+vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
+{
+  struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+  basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
+  int nbbs = loop->num_nodes;
+  block_stmt_iterator si;
+  unsigned int vectorization_factor = 0;
+  int i;
+  tree scalar_type;
+
+  if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
+    fprintf (vect_dump, "=== vect_determine_vectorization_factor ===");
+
+  for (i = 0; i < nbbs; i++)
+    {
+      basic_block bb = bbs[i];
+
+      for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
+        {
+          tree stmt = bsi_stmt (si);
+          unsigned int nunits;
+          stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+          tree vectype;
+
+          if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
+            {
+              fprintf (vect_dump, "==> examining statement: ");
+              print_generic_expr (vect_dump, stmt, TDF_SLIM);
+            }
+
+          gcc_assert (stmt_info);
+          /* skip stmts which do not need to be vectorized.  */
+          if (!STMT_VINFO_RELEVANT_P (stmt_info))
+            continue;
+
+          if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (stmt))))
+            {
+              if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
+                                        LOOP_LOC (loop_vinfo)))
+                {
+                  fprintf (vect_dump, "not vectorized: vector stmt in loop:");
+                  print_generic_expr (vect_dump, stmt, TDF_SLIM);
+                }
+              return false;
+            }
+
+          if (STMT_VINFO_DATA_REF (stmt_info))
+            scalar_type = TREE_TYPE (DR_REF (STMT_VINFO_DATA_REF (stmt_info)));
+          else if (TREE_CODE (stmt) == MODIFY_EXPR)
+            scalar_type = TREE_TYPE (TREE_OPERAND (stmt, 0));
+          else
+            scalar_type = TREE_TYPE (stmt);
+
+          if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
+            {
+              fprintf (vect_dump, "get vectype for scalar type:  ");
+              print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
+            }
+
+          vectype = get_vectype_for_scalar_type (scalar_type);
+          if (!vectype)
+            {
+              if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
+                                        LOOP_LOC (loop_vinfo)))
+                {
+                  fprintf (vect_dump, "not vectorized: unsupported data-type ");
+                  print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
+                }
+              return false;
+            }
+          if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
+            {
+              fprintf (vect_dump, "vectype: ");
+              print_generic_expr (vect_dump, vectype, TDF_SLIM);
+            }
+          STMT_VINFO_VECTYPE (stmt_info) = vectype;
+
+          nunits = TYPE_VECTOR_SUBPARTS (vectype);
+          if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
+            fprintf (vect_dump, "nunits = %d", nunits);
+
+          if (vectorization_factor)
+            {
+              /* FORNOW: don't allow mixed units. 
+                 This restriction will be relaxed in the future.  */
+              if (nunits != vectorization_factor) 
+                {
+                  if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
+                                            LOOP_LOC (loop_vinfo)))
+                    fprintf (vect_dump, "not vectorized: mixed data-types");
+                  return false;
+                }
+            }
+          else
+            vectorization_factor = nunits;
+
+#ifdef ENABLE_CHECKING
+          gcc_assert (GET_MODE_SIZE (TYPE_MODE (scalar_type))
+                        * vectorization_factor == UNITS_PER_SIMD_WORD);
+#endif
+        }
+    }
+
+  /* TODO: Analyze cost. Decide if worth while to vectorize.  */
+
+  if (vectorization_factor <= 1)
+    {
+      if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
+                                LOOP_LOC (loop_vinfo)))
+        fprintf (vect_dump, "not vectorized: unsupported data-type");
+      return false;
+    }
+  LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor;
+
+  return true;
+}
+
+
 /* Function vect_analyze_operations.
 
    Scan the loop stmts and make sure they are all vectorizable.  */
@@ -299,11 +445,13 @@ vect_analyze_operations (loop_vec_info loop_vinfo)
   unsigned int vectorization_factor = 0;
   int i;
   bool ok;
-  tree scalar_type;
 
   if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
     fprintf (vect_dump, "=== vect_analyze_operations ===");
 
+  gcc_assert (LOOP_VINFO_VECT_FACTOR (loop_vinfo));
+  vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+
   for (i = 0; i < nbbs; i++)
     {
       basic_block bb = bbs[i];
@@ -311,9 +459,7 @@ vect_analyze_operations (loop_vec_info loop_vinfo)
       for (si = bsi_start (bb); !bsi_end_p (si); bsi_next (&si))
        {
          tree stmt = bsi_stmt (si);
-         unsigned int nunits;
          stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
-         tree vectype;
 
          if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
            {
@@ -337,54 +483,19 @@ vect_analyze_operations (loop_vec_info loop_vinfo)
              continue;
            }
 
-         if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (stmt))))
-           {
-             if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
-                                         LOOP_LOC (loop_vinfo)))
-               {
-                  fprintf (vect_dump, "not vectorized: vector stmt in loop:");
-                 print_generic_expr (vect_dump, stmt, TDF_SLIM);
-               }
-             return false;
-           }
-
-          if (STMT_VINFO_DATA_REF (stmt_info))
-            scalar_type = TREE_TYPE (DR_REF (STMT_VINFO_DATA_REF (stmt_info)));    
-          else if (TREE_CODE (stmt) == MODIFY_EXPR)
-           scalar_type = TREE_TYPE (TREE_OPERAND (stmt, 0));
-         else
-           scalar_type = TREE_TYPE (stmt);
-
-         if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
-           {
-             fprintf (vect_dump, "get vectype for scalar type:  ");
-             print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
-           }
-
-         vectype = get_vectype_for_scalar_type (scalar_type);
-         if (!vectype)
-           {
-             if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
-                                         LOOP_LOC (loop_vinfo)))
-               {
-                  fprintf (vect_dump,
-                           "not vectorized: unsupported data-type ");
-                 print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
-               }
-             return false;
-           }
-
-         if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
-           {
-             fprintf (vect_dump, "vectype: ");
-             print_generic_expr (vect_dump, vectype, TDF_SLIM);
-           }
-         STMT_VINFO_VECTYPE (stmt_info) = vectype;
+#ifdef ENABLE_CHECKING
+          if (STMT_VINFO_RELEVANT_P (stmt_info))
+            {
+              gcc_assert (!VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (stmt))));
+              gcc_assert (STMT_VINFO_VECTYPE (stmt_info));
+            }
+#endif
 
          ok = (vectorizable_operation (stmt, NULL, NULL)
                || vectorizable_assignment (stmt, NULL, NULL)
                || vectorizable_load (stmt, NULL, NULL)
-               || vectorizable_store (stmt, NULL, NULL));
+               || vectorizable_store (stmt, NULL, NULL)
+               || vectorizable_condition (stmt, NULL, NULL));
 
          if (!ok)
            {
@@ -396,44 +507,11 @@ vect_analyze_operations (loop_vec_info loop_vinfo)
                }
              return false;
            }
-
-         nunits = GET_MODE_NUNITS (TYPE_MODE (vectype));
-         if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
-           fprintf (vect_dump, "nunits = %d", nunits);
-
-         if (vectorization_factor)
-           {
-             /* FORNOW: don't allow mixed units.
-                This restriction will be relaxed in the future.  */
-             if (nunits != vectorization_factor)
-               {
-                 if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
-                                             LOOP_LOC (loop_vinfo)))
-                   fprintf (vect_dump, "not vectorized: mixed data-types");
-                 return false;
-               }
-           }
-         else
-           vectorization_factor = nunits;
-
-#ifdef ENABLE_CHECKING
-         gcc_assert (GET_MODE_SIZE (TYPE_MODE (scalar_type))
-                       * vectorization_factor == UNITS_PER_SIMD_WORD);
-#endif
        }
     }
 
   /* TODO: Analyze cost. Decide if worth while to vectorize.  */
 
-  if (vectorization_factor <= 1)
-    {
-      if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
-                                 LOOP_LOC (loop_vinfo)))
-        fprintf (vect_dump, "not vectorized: unsupported data-type");
-      return false;
-    }
-  LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor;
-
   if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
       && vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
     fprintf (vect_dump,
@@ -462,7 +540,7 @@ vect_analyze_operations (loop_vec_info loop_vinfo)
                      "not vectorized: can't create epilog loop 1.");
           return false;
         }
-      if (!slpeel_can_duplicate_loop_p (loop, loop->exit_edges[0]))
+      if (!slpeel_can_duplicate_loop_p (loop, loop->single_exit))
         {
           if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
                                      LOOP_LOC (loop_vinfo)))
@@ -697,6 +775,12 @@ vect_analyze_data_ref_dependence (struct data_reference *dra,
 {
   bool differ_p; 
   struct data_dependence_relation *ddr;
+  struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+  int vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+  int dist = 0;
+  unsigned int loop_depth = 0;
+  struct loop *loop_nest = loop;  
+
   
   if (!vect_base_addr_differ_p (dra, drb, &differ_p))
     {
@@ -720,7 +804,65 @@ vect_analyze_data_ref_dependence (struct data_reference *dra,
 
   if (DDR_ARE_DEPENDENT (ddr) == chrec_known)
     return false;
-  
+
+  if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
+    {
+      if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
+                                LOOP_LOC (loop_vinfo)))
+        {
+          fprintf (vect_dump, 
+                   "not vectorized: can't determine dependence between "); 
+          print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
+          fprintf (vect_dump, " and ");
+          print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
+        }
+      return true;
+    }
+
+  /* Find loop depth.  */
+  while (loop_nest)
+    {
+      if (loop_nest->outer && loop_nest->outer->outer)
+       {
+         loop_nest = loop_nest->outer;
+         loop_depth++;
+       }
+      else
+       break;
+    }
+
+  /* Compute distance vector.  */
+  compute_subscript_distance (ddr);
+  build_classic_dist_vector (ddr, vect_loops_num, loop_nest->depth);
+
+  if (!DDR_DIST_VECT (ddr))
+    {
+      if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
+                               LOOP_LOC (loop_vinfo)))
+       {
+         fprintf (vect_dump, "not vectorized: bad dist vector for ");
+         print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
+         fprintf (vect_dump, " and ");
+         print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
+       }      
+      return true;
+    }
+
+  dist = DDR_DIST_VECT (ddr)[loop_depth];
+
+  /* Same loop iteration.  */
+  if (dist == 0)
+    {
+      if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
+       fprintf (vect_dump, "dependence distance 0.");
+      return false;
+    }
+
+  if (dist >= vectorization_factor)
+    /* Dependence distance does not create dependence, as far as vectorization
+       is concerned, in this case.  */
+    return false;
+    
   if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
                            LOOP_LOC (loop_vinfo)))
     {
@@ -738,10 +880,7 @@ vect_analyze_data_ref_dependence (struct data_reference *dra,
 /* Function vect_analyze_data_ref_dependences.
 
    Examine all the data references in the loop, and make sure there do not
-   exist any data dependences between them.
-
-   TODO: dependences which distance is greater than the vectorization factor
-         can be ignored.  */
+   exist any data dependences between them.  */
 
 static bool
 vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo)
@@ -933,7 +1072,9 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
 {
   varray_type loop_read_datarefs = LOOP_VINFO_DATAREF_READS (loop_vinfo);
   varray_type loop_write_datarefs = LOOP_VINFO_DATAREF_WRITES (loop_vinfo);
-  unsigned int i;
+  varray_type datarefs;
+  struct data_reference *dr0 = NULL;
+  unsigned int i, j;
 
   /*
      This pass will require a cost model to guide it whether to apply peeling 
@@ -1036,25 +1177,14 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
 
   for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_write_datarefs); i++)
     {
-      struct data_reference *dr = VARRAY_GENERIC_PTR (loop_write_datarefs, i);
-      if (!aligned_access_p (dr))
-        {
-          LOOP_VINFO_UNALIGNED_DR (loop_vinfo) = dr;
-          LOOP_DO_PEELING_FOR_ALIGNMENT (loop_vinfo) = true;
+      dr0 = VARRAY_GENERIC_PTR (loop_write_datarefs, i);
+      if (!aligned_access_p (dr0))
+       {
+         LOOP_VINFO_UNALIGNED_DR (loop_vinfo) = dr0;
+         LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo) = DR_MISALIGNMENT (dr0);
          break;
-        }
-    }
-
-  if (!LOOP_VINFO_UNALIGNED_DR (loop_vinfo))
-    {
-      if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
-       fprintf (vect_dump, "Peeling for alignment will not be applied.");
-      return;
+       }
     }
-  else
-    if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
-      fprintf (vect_dump, "Peeling for alignment will be applied.");
-
 
   /* (1.2) Update the alignment info according to the peeling factor.
           If the misalignment of the DR we peel for is M, then the
@@ -1063,37 +1193,52 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
           If the misalignment of the DR we peel for is unknown, then the 
           misalignment of each access DR_i in the loop is also unknown.
 
-          FORNOW: set the misalignment of the accesses to unknown even
-                  if the peeling factor is known at compile time.
+           TODO: - consider accesses that are known to have the same
+                   alignment, even if that alignment is unknown.  */
 
-          TODO: - if the peeling factor is known at compile time, use that
-                  when updating the misalignment info of the loop DRs.
-                - consider accesses that are known to have the same 
-                  alignment, even if that alignment is unknown.  */
-   
-  for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_write_datarefs); i++)
+  if (LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo))
     {
-      struct data_reference *dr = VARRAY_GENERIC_PTR (loop_write_datarefs, i);
-      if (dr == LOOP_VINFO_UNALIGNED_DR (loop_vinfo))
+      int mis;
+      int npeel = 0;
+
+      if (known_alignment_for_access_p (dr0))
        {
-         DR_MISALIGNMENT (dr) = 0;
-         if (vect_print_dump_info (REPORT_ALIGNMENT, LOOP_LOC (loop_vinfo)))
-           fprintf (vect_dump, "Alignment of access forced using peeling.");
+         /* Since it's known at compile time, compute the number of iterations
+            in the peeled loop (the peeling factor) for use in updating
+            DR_MISALIGNMENT values.  The peeling factor is the vectorization
+            factor minus the misalignment as an element count.  */
+         mis = DR_MISALIGNMENT (dr0);
+         mis /= GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (dr0))));
+         npeel = LOOP_VINFO_VECT_FACTOR (loop_vinfo) - mis;
        }
-      else
-       DR_MISALIGNMENT (dr) = -1;
-    }
-  for (i = 0; i < VARRAY_ACTIVE_SIZE (loop_read_datarefs); i++)
-    {
-      struct data_reference *dr = VARRAY_GENERIC_PTR (loop_read_datarefs, i);
-      if (dr == LOOP_VINFO_UNALIGNED_DR (loop_vinfo))
+
+      datarefs = loop_write_datarefs;
+      for (j = 0; j < 2; j++)
        {
-         DR_MISALIGNMENT (dr) = 0;
-         if (vect_print_dump_info (REPORT_ALIGNMENT, LOOP_LOC (loop_vinfo)))
-           fprintf (vect_dump, "Alignment of access forced using peeling.");
+         for (i = 0; i < VARRAY_ACTIVE_SIZE (datarefs); i++)
+           {
+             struct data_reference *dr = VARRAY_GENERIC_PTR (datarefs, i);
+
+             if (dr == dr0)
+               continue;
+             if (known_alignment_for_access_p (dr)
+                 && DR_MISALIGNMENT (dr) == DR_MISALIGNMENT (dr0))
+               DR_MISALIGNMENT (dr) = 0;
+             else if (known_alignment_for_access_p (dr)
+                      && known_alignment_for_access_p (dr0))
+               {
+                 int drsize = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (DR_REF (dr))));
+
+                 DR_MISALIGNMENT (dr) += npeel * drsize;
+                 DR_MISALIGNMENT (dr) %= UNITS_PER_SIMD_WORD;
+               }
+             else
+               DR_MISALIGNMENT (dr) = -1;
+           }
+         datarefs = loop_read_datarefs;
        }
-      else
-       DR_MISALIGNMENT (dr) = -1;
+
+      DR_MISALIGNMENT (dr0) = 0;
     }
 }
 
@@ -1169,6 +1314,9 @@ vect_analyze_data_refs_alignment (loop_vec_info loop_vinfo)
          && (vect_print_dump_info (REPORT_ALIGNMENT, LOOP_LOC (loop_vinfo))))
        fprintf (vect_dump, "Vectorizing an unaligned access.");
     }
+  if (LOOP_VINFO_UNALIGNED_DR (loop_vinfo)
+      && vect_print_dump_info (REPORT_ALIGNMENT, LOOP_LOC (loop_vinfo)))
+    fprintf (vect_dump, "Alignment of access forced using peeling.");
 
   return true;
 }
@@ -1310,8 +1458,7 @@ vect_analyze_pointer_ref_access (tree memref, tree stmt, bool is_read,
       return NULL;
     }
 
-  reftype = TREE_TYPE (init);
-  if (!POINTER_TYPE_P (reftype)) 
+  if (!POINTER_TYPE_P (TREE_TYPE (init))) 
     {
       if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
                                LOOP_LOC (loop_vinfo))) 
@@ -1321,6 +1468,14 @@ vect_analyze_pointer_ref_access (tree memref, tree stmt, bool is_read,
 
   *ptr_step = fold_convert (ssizetype, step);
   innertype = TREE_TYPE (reftype);
+  if (!COMPLETE_TYPE_P (innertype))
+    {
+      if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
+                              LOOP_LOC (loop_vinfo)))
+      fprintf (vect_dump, "not vectorized: pointer to incomplete type.");
+      return NULL;
+    }
+   
   /* Check that STEP is a multiple of type size.  */
   if (!integer_zerop (size_binop (TRUNC_MOD_EXPR, *ptr_step, 
                        fold_convert (ssizetype, TYPE_SIZE_UNIT (innertype)))))
@@ -1377,6 +1532,8 @@ vect_address_analysis (tree expr, tree stmt, bool is_read, tree vectype,
   tree oprnd0, oprnd1, base_address, offset_expr, base_addr0, base_addr1;
   tree address_offset = ssize_int (0), address_misalign = ssize_int (0);
   tree dummy;
+  struct ptr_info_def *dummy1;
+  subvar_t dummy2;
 
   switch (TREE_CODE (expr))
     {
@@ -1426,9 +1583,10 @@ vect_address_analysis (tree expr, tree stmt, bool is_read, tree vectype,
       return base_addr0 ? base_addr0 : base_addr1;
 
     case ADDR_EXPR:
-      base_address = vect_object_analysis (TREE_OPERAND (expr, 0), stmt, is_read, 
-                                  vectype, &dr, offset, misalign, step, 
-                                  base_aligned, &dummy);
+      base_address = vect_object_analysis (TREE_OPERAND (expr, 0), stmt,
+                                          is_read, vectype, &dr, offset, 
+                                          misalign, step, base_aligned, 
+                                          &dummy, &dummy1, &dummy2);
       return base_address;
 
     case SSA_NAME:
@@ -1507,6 +1665,8 @@ vect_address_analysis (tree expr, tree stmt, bool is_read, tree vectype,
    STEP - evolution of the DR_REF in the loop
    BASE_ALIGNED - indicates if BASE is aligned
    MEMTAG - memory tag for aliasing purposes
+   PTR_INFO - NULL or points-to aliasing info from a pointer SSA_NAME
+   SUBVAR - Sub-variables of the variable
  
    If something unexpected is encountered (an unsupported form of data-ref),
    then NULL_TREE is returned.  */
@@ -1515,7 +1675,8 @@ static tree
 vect_object_analysis (tree memref, tree stmt, bool is_read,
                      tree vectype, struct data_reference **dr,
                      tree *offset, tree *misalign, tree *step,
-                     bool *base_aligned, tree *memtag)
+                     bool *base_aligned, tree *memtag,
+                     struct ptr_info_def **ptr_info, subvar_t *subvars)
 {
   tree base = NULL_TREE, base_address = NULL_TREE;
   tree object_offset = ssize_int (0), object_misalign = ssize_int (0);
@@ -1532,6 +1693,8 @@ vect_object_analysis (tree memref, tree stmt, bool is_read,
   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
   struct data_reference *ptr_dr = NULL;
   tree access_fn, evolution_part, address_to_analyze;
+
+  *ptr_info = NULL;
    
   /* Part 1: */
   /* Case 1. handled_component_p refs.  */
@@ -1611,15 +1774,21 @@ vect_object_analysis (tree memref, tree stmt, bool is_read,
           us to object.  */
        DR_BASE_NAME ((*dr)) = memref;
 
+      if (SSA_VAR_P (memref) && var_can_have_subvars (memref)) 
+       *subvars = get_subvars_for_var (memref);
       base_address = build_fold_addr_expr (memref);
       *memtag = memref;
     }
 
   /* Part 1:  Case 3. INDIRECT_REFs.  */
   else if (TREE_CODE (memref) == INDIRECT_REF)
-    {      
+    {
+      tree ptr_ref = TREE_OPERAND (memref, 0);
+      if (TREE_CODE (ptr_ref) == SSA_NAME)
+        *ptr_info = SSA_NAME_PTR_INFO (ptr_ref);
+
       /* 3.1 get the access function.  */
-      access_fn = analyze_scalar_evolution (loop, TREE_OPERAND (memref, 0));
+      access_fn = analyze_scalar_evolution (loop, ptr_ref);
       if (!access_fn)
        {
          if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
@@ -1654,10 +1823,11 @@ vect_object_analysis (tree memref, tree stmt, bool is_read,
                fprintf (vect_dump, "not vectorized: ptr is loop invariant.");  
              return NULL_TREE;
            }
-         /* Since there exists DR for MEMREF, we are analyzing the base of
-            handled component, which not necessary has evolution in the 
+         /* Since there exists DR for MEMREF, we are analyzing the init of 
+            the access function, which not necessary has evolution in the 
             loop.  */
-         address_to_analyze = TREE_OPERAND (base, 0);
+         address_to_analyze = initial_condition_in_loop_num (access_fn,
+                                                              loop->num);
        }
       
       /* 3.3 set data-reference structure for MEMREF.  */
@@ -1697,8 +1867,11 @@ vect_object_analysis (tree memref, tree stmt, bool is_read,
     /* MEMREF cannot be analyzed.  */
     return NULL_TREE;
 
+  if (SSA_VAR_P (*memtag) && var_can_have_subvars (*memtag))
+    *subvars = get_subvars_for_var (*memtag);
+
   /* Part 2: Combine the results of object and address analysis to calculate 
-     INITIAL_OFFSET, STEP and misalignment info. */
+     INITIAL_OFFSET, STEP and misalignment info.  */
   *offset = size_binop (PLUS_EXPR, object_offset, address_offset);
   if (object_misalign && address_misalign)
     *misalign = size_binop (PLUS_EXPR, object_misalign, address_misalign);
@@ -1740,7 +1913,7 @@ vect_object_analysis (tree memref, tree stmt, bool is_read,
            Call get_inner_reference for refs handled in this function.
            Call vect_addr_analysis(addr) to analyze pointer type expressions.
       Set ref_stmt.base, ref_stmt.initial_offset, ref_stmt.alignment,  
-      ref_stmt.memtag and ref_stmt.step accordingly. 
+      ref_stmt.memtag, ref_stmt.ptr_info and ref_stmt.step accordingly. 
    2- vect_analyze_dependences(): apply dependence testing using ref_stmt.DR
    3- vect_analyze_drs_alignment(): check that ref_stmt.alignment is ok.
    4- vect_analyze_drs_access(): check that ref_stmt.step is ok.
@@ -1770,27 +1943,25 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
          bool is_read = false;
          tree stmt = bsi_stmt (si);
          stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
-         v_may_def_optype v_may_defs = STMT_V_MAY_DEF_OPS (stmt);
-         v_must_def_optype v_must_defs = STMT_V_MUST_DEF_OPS (stmt);
-         vuse_optype vuses = STMT_VUSE_OPS (stmt);
          varray_type *datarefs = NULL;
-         int nvuses, nv_may_defs, nv_must_defs;
          tree memref = NULL;
          tree scalar_type, vectype;      
          tree base, offset, misalign, step, tag;
+         struct ptr_info_def *ptr_info;
          bool base_aligned;
+         subvar_t subvars = NULL;
+         bool no_vuse, no_vmaymust;
 
          /* Assumption: there exists a data-ref in stmt, if and only if 
              it has vuses/vdefs.  */
 
-         if (!vuses && !v_may_defs && !v_must_defs)
+         no_vuse = ZERO_SSA_OPERANDS (stmt, SSA_OP_VUSE);
+         no_vmaymust = ZERO_SSA_OPERANDS (stmt,
+                                          SSA_OP_VMAYDEF | SSA_OP_VMUSTDEF);
+         if (no_vuse && no_vmaymust)
            continue;
 
-         nvuses = NUM_VUSES (vuses);
-         nv_may_defs = NUM_V_MAY_DEFS (v_may_defs);
-         nv_must_defs = NUM_V_MUST_DEFS (v_must_defs);
-
-         if (nvuses && (nv_may_defs || nv_must_defs))
+         if (!no_vuse && !no_vmaymust)
            {
              if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
                {
@@ -1810,7 +1981,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
              return false;
            }
 
-         if (vuses)
+         if (!no_vuse)
            {
              memref = TREE_OPERAND (stmt, 1);
              datarefs = &(LOOP_VINFO_DATAREF_READS (loop_vinfo));
@@ -1842,7 +2013,8 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
          dr = NULL; 
          base = vect_object_analysis (memref, stmt, is_read, vectype, &dr, 
                                       &offset, &misalign, &step, 
-                                      &base_aligned, &tag);
+                                      &base_aligned, &tag, &ptr_info,
+                                      &subvars);
          if (!base)
            {
              if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
@@ -1859,6 +2031,8 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
          STMT_VINFO_VECT_MISALIGNMENT (stmt_info) = misalign;
          STMT_VINFO_VECT_BASE_ALIGNED_P (stmt_info) = base_aligned;
          STMT_VINFO_MEMTAG (stmt_info) = tag;
+         STMT_VINFO_PTR_INFO (stmt_info) = ptr_info;
+         STMT_VINFO_SUBVARS (stmt_info) = subvars;
          STMT_VINFO_VECTYPE (stmt_info) = vectype;
          VARRAY_PUSH_GENERIC_PTR (*datarefs, dr);
          STMT_VINFO_DATA_REF (stmt_info) = dr;
@@ -1876,7 +2050,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
    Mark STMT as "relevant for vectorization" and add it to WORKLIST.  */
 
 static void
-vect_mark_relevant (varray_type *worklist, tree stmt)
+vect_mark_relevant (VEC(tree,heap) **worklist, tree stmt)
 {
   stmt_vec_info stmt_info;
 
@@ -1885,7 +2059,7 @@ vect_mark_relevant (varray_type *worklist, tree stmt)
 
   if (TREE_CODE (stmt) == PHI_NODE)
     {
-      VARRAY_PUSH_TREE (*worklist, stmt);
+      VEC_safe_push (tree, heap, *worklist, stmt);
       return;
     }
 
@@ -1909,7 +2083,7 @@ vect_mark_relevant (varray_type *worklist, tree stmt)
     }
 
   STMT_VINFO_RELEVANT_P (stmt_info) = 1;
-  VARRAY_PUSH_TREE (*worklist, stmt);
+  VEC_safe_push (tree, heap, *worklist, stmt);
 }
 
 
@@ -1928,12 +2102,11 @@ vect_mark_relevant (varray_type *worklist, tree stmt)
 static bool
 vect_stmt_relevant_p (tree stmt, loop_vec_info loop_vinfo)
 {
-  v_may_def_optype v_may_defs;
-  v_must_def_optype v_must_defs;
   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
-  int i;
-  dataflow_t df;
-  int num_uses;
+  ssa_op_iter op_iter;
+  imm_use_iterator imm_iter;
+  use_operand_p use_p;
+  def_operand_p def_p;
 
   /* cond stmt other than loop exit cond.  */
   if (is_ctrl_stmt (stmt) && (stmt != LOOP_VINFO_EXIT_COND (loop_vinfo)))
@@ -1941,29 +2114,25 @@ vect_stmt_relevant_p (tree stmt, loop_vec_info loop_vinfo)
 
   /* changing memory.  */
   if (TREE_CODE (stmt) != PHI_NODE)
-    {
-      v_may_defs = STMT_V_MAY_DEF_OPS (stmt);
-      v_must_defs = STMT_V_MUST_DEF_OPS (stmt);
-      if (v_may_defs || v_must_defs)
-       {
-         if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
-           fprintf (vect_dump, "vec_stmt_relevant_p: stmt has vdefs.");
-         return true;
-       }
-    }
+    if (!ZERO_SSA_OPERANDS (stmt, SSA_OP_VIRTUAL_DEFS))
+      {
+       if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
+         fprintf (vect_dump, "vec_stmt_relevant_p: stmt has vdefs.");
+       return true;
+      }
 
   /* uses outside the loop.  */
-  df = get_immediate_uses (stmt);
-  num_uses = num_immediate_uses (df);
-  for (i = 0; i < num_uses; i++)
+  FOR_EACH_PHI_OR_STMT_DEF (def_p, stmt, op_iter, SSA_OP_DEF)
     {
-      tree use = immediate_use (df, i);
-      basic_block bb = bb_for_stmt (use);
-      if (!flow_bb_inside_loop_p (loop, bb))
+      FOR_EACH_IMM_USE_FAST (use_p, imm_iter, DEF_FROM_PTR (def_p))
        {
-         if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
-           fprintf (vect_dump, "vec_stmt_relevant_p: used out of loop.");
-         return true;
+         basic_block bb = bb_for_stmt (USE_STMT (use_p));
+         if (!flow_bb_inside_loop_p (loop, bb))
+           {
+             if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
+               fprintf (vect_dump, "vec_stmt_relevant_p: used out of loop.");
+             return true;
+           }
        }
     }
 
@@ -1990,16 +2159,15 @@ vect_stmt_relevant_p (tree stmt, loop_vec_info loop_vinfo)
 static bool
 vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
 {
-  varray_type worklist;
+  VEC(tree,heap) *worklist;
   struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
   basic_block *bbs = LOOP_VINFO_BBS (loop_vinfo);
   unsigned int nbbs = loop->num_nodes;
   block_stmt_iterator si;
-  tree stmt;
-  stmt_ann_t ann;
+  tree stmt, use;
+  ssa_op_iter iter;
   unsigned int i;
   int j;
-  use_optype use_ops;
   stmt_vec_info stmt_info;
   basic_block bb;
   tree phi;
@@ -2025,7 +2193,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
        }
     }
 
-  VARRAY_TREE_INIT (worklist, 64, "work list");
+  worklist = VEC_alloc (tree, heap, 64);
 
   /* 1. Init worklist.  */
 
@@ -2053,10 +2221,9 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
 
   /* 2. Process_worklist */
 
-  while (VARRAY_ACTIVE_SIZE (worklist) > 0)
+  while (VEC_length (tree, worklist) > 0)
     {
-      stmt = VARRAY_TOP_TREE (worklist);
-      VARRAY_POP (worklist);
+      stmt = VEC_pop (tree, worklist);
 
       if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC))
        {
@@ -2081,7 +2248,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
                  if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
                                            LOOP_LOC (loop_vinfo)))
                    fprintf (vect_dump, "not vectorized: unsupported use in stmt.");
-                 varray_clear (worklist);
+                 VEC_free (tree, heap, worklist);
                  return false;
                }
              if (!def_stmt)
@@ -2099,12 +2266,8 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
            }
        } 
 
-      ann = stmt_ann (stmt);
-      use_ops = USE_OPS (ann);
-
-      for (i = 0; i < NUM_USES (use_ops); i++)
+      FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE)
        {
-         tree use = USE_OP (use_ops, i);
 
          /* We are only interested in uses that need to be vectorized. Uses 
             that are used for address computation are not considered relevant.
@@ -2118,7 +2281,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
                   if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS,
                                            LOOP_LOC (loop_vinfo)))
                     fprintf (vect_dump, "not vectorized: unsupported use in stmt.");
-                  varray_clear (worklist);
+                 VEC_free (tree, heap, worklist);
                   return false;
                 }
 
@@ -2138,7 +2301,7 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
        }
     }                          /* while worklist */
 
-  varray_clear (worklist);
+  VEC_free (tree, heap, worklist);
   return true;
 }
 
@@ -2265,7 +2428,6 @@ vect_analyze_loop_form (struct loop *loop)
   loop_vec_info loop_vinfo;
   tree loop_cond;
   tree number_of_iterations = NULL;
-  bool rescan = false;
   LOC loop_loc;
 
   loop_loc = find_loop_location (loop);
@@ -2282,8 +2444,7 @@ vect_analyze_loop_form (struct loop *loop)
   
   if (!loop->single_exit 
       || loop->num_nodes != 2
-      || EDGE_COUNT (loop->header->preds) != 2
-      || loop->num_entries != 1)
+      || EDGE_COUNT (loop->header->preds) != 2)
     {
       if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS, loop_loc))
         {
@@ -2293,8 +2454,6 @@ vect_analyze_loop_form (struct loop *loop)
             fprintf (vect_dump, "not vectorized: too many BBs in loop.");
           else if (EDGE_COUNT (loop->header->preds) != 2)
             fprintf (vect_dump, "not vectorized: too many incoming edges.");
-          else if (loop->num_entries != 1)
-            fprintf (vect_dump, "not vectorized: too many entries.");
         }
 
       return NULL;
@@ -2311,25 +2470,22 @@ vect_analyze_loop_form (struct loop *loop)
       return NULL;
     }
 
-  /* Make sure we have a preheader basic block.  */
-  if (!loop->pre_header)
-    {
-      rescan = true;
-      loop_split_edge_with (loop_preheader_edge (loop), NULL);
-    }
-    
   /* Make sure there exists a single-predecessor exit bb:  */
-  if (EDGE_COUNT (loop->exit_edges[0]->dest->preds) != 1)
-    {
-      rescan = true;
-      loop_split_edge_with (loop->exit_edges[0], NULL);
-    }
-    
-  if (rescan)
+  if (!single_pred_p (loop->single_exit->dest))
     {
-      flow_loop_scan (loop, LOOP_ALL);
-      /* Flow loop scan does not update loop->single_exit field.  */
-      loop->single_exit = loop->exit_edges[0];
+      edge e = loop->single_exit;
+      if (!(e->flags & EDGE_ABNORMAL))
+       {
+         split_loop_exit_edge (e);
+         if (vect_print_dump_info (REPORT_DETAILS, loop_loc))
+           fprintf (vect_dump, "split exit edge.");
+       }
+      else
+       {
+         if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS, loop_loc))
+           fprintf (vect_dump, "not vectorized: abnormal loop exit edge.");
+         return NULL;
+       }
     }
 
   if (empty_block_p (loop->header))
@@ -2450,6 +2606,15 @@ vect_analyze_loop (struct loop *loop)
       return NULL;
     }
 
+  ok = vect_determine_vectorization_factor (loop_vinfo);
+  if (!ok)
+    {
+      if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo)))
+        fprintf (vect_dump, "can't determine vectorization factor.");
+      destroy_loop_vec_info (loop_vinfo);
+      return NULL;
+    }
+
   /* Analyze data dependences between the data-refs in the loop. 
      FORNOW: fail at the first data dependence that we encounter.  */