OSDN Git Service

2010-07-24 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / tree-vect-stmts.c
index ce604b3..e0ae559 100644 (file)
@@ -1,6 +1,6 @@
 /* Statement Analysis and Transformation for Vectorization
-   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software
-   Foundation, Inc.
+   Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   Free Software Foundation, Inc.
    Contributed by Dorit Naishlos <dorit@il.ibm.com>
    and Ira Rosen <irar@il.ibm.com>
 
@@ -28,7 +28,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree.h"
 #include "target.h"
 #include "basic-block.h"
-#include "diagnostic.h"
+#include "tree-pretty-print.h"
+#include "gimple-pretty-print.h"
 #include "tree-flow.h"
 #include "tree-dump.h"
 #include "cfgloop.h"
@@ -36,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "expr.h"
 #include "recog.h"
 #include "optabs.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 #include "tree-vectorizer.h"
 #include "langhooks.h"
@@ -544,6 +546,18 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo)
 }
 
 
+/* Get cost by calling cost target builtin.  */
+
+static inline
+int vect_get_stmt_cost (enum vect_cost_for_stmt type_of_cost)
+{
+  tree dummy_type = NULL;
+  int dummy = 0;
+
+  return targetm.vectorize.builtin_vectorization_cost (type_of_cost,
+                                                       dummy_type, dummy);
+}
+
 int
 cost_for_stmt (gimple stmt)
 {
@@ -552,9 +566,9 @@ cost_for_stmt (gimple stmt)
   switch (STMT_VINFO_TYPE (stmt_info))
   {
   case load_vec_info_type:
-    return TARG_SCALAR_LOAD_COST;
+    return vect_get_stmt_cost (scalar_load);
   case store_vec_info_type:
-    return TARG_SCALAR_STORE_COST;
+    return vect_get_stmt_cost (scalar_store);
   case op_vec_info_type:
   case condition_vec_info_type:
   case assignment_vec_info_type:
@@ -564,7 +578,7 @@ cost_for_stmt (gimple stmt)
   case type_demotion_vec_info_type:
   case type_conversion_vec_info_type:
   case call_vec_info_type:
-    return TARG_SCALAR_STMT_COST;
+    return vect_get_stmt_cost (scalar_stmt);
   case undef_vec_info_type:
   default:
     gcc_unreachable ();
@@ -588,13 +602,13 @@ vect_model_simple_cost (stmt_vec_info stmt_info, int ncopies,
   if (PURE_SLP_STMT (stmt_info))
     return;
 
-  inside_cost = ncopies * TARG_VEC_STMT_COST;
+  inside_cost = ncopies * vect_get_stmt_cost (vector_stmt); 
 
   /* FORNOW: Assuming maximum 2 args per stmts.  */
   for (i = 0; i < 2; i++)
     {
       if (dt[i] == vect_constant_def || dt[i] == vect_external_def)
-       outside_cost += TARG_SCALAR_TO_VEC_COST;
+       outside_cost += vect_get_stmt_cost (vector_stmt); 
     }
 
   if (vect_print_dump_info (REPORT_COST))
@@ -635,21 +649,39 @@ vect_model_store_cost (stmt_vec_info stmt_info, int ncopies,
                       enum vect_def_type dt, slp_tree slp_node)
 {
   int group_size;
-  int inside_cost = 0, outside_cost = 0;
+  unsigned int inside_cost = 0, outside_cost = 0;
+  struct data_reference *first_dr;
+  gimple first_stmt;
 
   /* The SLP costs were already calculated during SLP tree build.  */
   if (PURE_SLP_STMT (stmt_info))
     return;
 
   if (dt == vect_constant_def || dt == vect_external_def)
-    outside_cost = TARG_SCALAR_TO_VEC_COST;
+    outside_cost = vect_get_stmt_cost (scalar_to_vec); 
 
   /* Strided access?  */
-  if (DR_GROUP_FIRST_DR (stmt_info) && !slp_node)
-    group_size = vect_cost_strided_group_size (stmt_info);
+  if (DR_GROUP_FIRST_DR (stmt_info))
+    {
+      if (slp_node)
+        {
+          first_stmt = VEC_index (gimple, SLP_TREE_SCALAR_STMTS (slp_node), 0);
+          group_size = 1;
+        }
+      else
+        {
+          first_stmt = DR_GROUP_FIRST_DR (stmt_info);
+          group_size = vect_cost_strided_group_size (stmt_info);
+        }
+
+      first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
+    }
   /* Not a strided access.  */
   else
-    group_size = 1;
+    {
+      group_size = 1;
+      first_dr = STMT_VINFO_DATA_REF (stmt_info);
+    }
 
   /* Is this an access in a group of stores, which provide strided access?
      If so, add in the cost of the permutes.  */
@@ -657,7 +689,7 @@ vect_model_store_cost (stmt_vec_info stmt_info, int ncopies,
     {
       /* Uses a high and low interleave operation for each needed permute.  */
       inside_cost = ncopies * exact_log2(group_size) * group_size
-             * TARG_VEC_STMT_COST;
+        * vect_get_stmt_cost (vector_stmt);
 
       if (vect_print_dump_info (REPORT_COST))
         fprintf (vect_dump, "vect_model_store_cost: strided group_size = %d .",
@@ -666,7 +698,7 @@ vect_model_store_cost (stmt_vec_info stmt_info, int ncopies,
     }
 
   /* Costs of the stores.  */
-  inside_cost += ncopies * TARG_VEC_STORE_COST;
+  vect_get_store_cost (first_dr, ncopies, &inside_cost);
 
   if (vect_print_dump_info (REPORT_COST))
     fprintf (vect_dump, "vect_model_store_cost: inside_cost = %d, "
@@ -678,6 +710,49 @@ vect_model_store_cost (stmt_vec_info stmt_info, int ncopies,
 }
 
 
+/* Calculate cost of DR's memory access.  */
+void
+vect_get_store_cost (struct data_reference *dr, int ncopies,
+                     unsigned int *inside_cost)
+{
+  int alignment_support_scheme = vect_supportable_dr_alignment (dr, false);
+
+  switch (alignment_support_scheme)
+    {
+    case dr_aligned:
+      {
+        *inside_cost += ncopies * vect_get_stmt_cost (vector_store);
+
+        if (vect_print_dump_info (REPORT_COST))
+          fprintf (vect_dump, "vect_model_store_cost: aligned.");
+
+        break;
+      }
+
+    case dr_unaligned_supported:
+      {
+        gimple stmt = DR_STMT (dr);
+        stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+        tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+
+        /* Here, we assign an additional cost for the unaligned store.  */
+        *inside_cost += ncopies
+          * targetm.vectorize.builtin_vectorization_cost (unaligned_store,
+                                 vectype, DR_MISALIGNMENT (dr));
+
+        if (vect_print_dump_info (REPORT_COST))
+          fprintf (vect_dump, "vect_model_store_cost: unaligned supported by "
+                   "hardware.");
+
+        break;
+      }
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
+
 /* Function vect_model_load_cost
 
    Models cost for loads.  In the case of strided accesses, the last access
@@ -690,10 +765,9 @@ vect_model_load_cost (stmt_vec_info stmt_info, int ncopies, slp_tree slp_node)
 
 {
   int group_size;
-  int alignment_support_cheme;
   gimple first_stmt;
   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr;
-  int inside_cost = 0, outside_cost = 0;
+  unsigned int inside_cost = 0, outside_cost = 0;
 
   /* The SLP costs were already calculated during SLP tree build.  */
   if (PURE_SLP_STMT (stmt_info))
@@ -713,28 +787,47 @@ vect_model_load_cost (stmt_vec_info stmt_info, int ncopies, slp_tree slp_node)
       first_dr = dr;
     }
 
-  alignment_support_cheme = vect_supportable_dr_alignment (first_dr);
-
   /* Is this an access in a group of loads providing strided access?
      If so, add in the cost of the permutes.  */
   if (group_size > 1)
     {
       /* Uses an even and odd extract operations for each needed permute.  */
       inside_cost = ncopies * exact_log2(group_size) * group_size
-       * TARG_VEC_STMT_COST;
+       * vect_get_stmt_cost (vector_stmt);
 
       if (vect_print_dump_info (REPORT_COST))
         fprintf (vect_dump, "vect_model_load_cost: strided group_size = %d .",
                  group_size);
-
     }
 
   /* The loads themselves.  */
-  switch (alignment_support_cheme)
+  vect_get_load_cost (first_dr, ncopies,
+         ((!DR_GROUP_FIRST_DR (stmt_info)) || group_size > 1 || slp_node),
+         &inside_cost, &outside_cost);
+
+  if (vect_print_dump_info (REPORT_COST))
+    fprintf (vect_dump, "vect_model_load_cost: inside_cost = %d, "
+             "outside_cost = %d .", inside_cost, outside_cost);
+
+  /* Set the costs either in STMT_INFO or SLP_NODE (if exists).  */
+  stmt_vinfo_set_inside_of_loop_cost (stmt_info, slp_node, inside_cost);
+  stmt_vinfo_set_outside_of_loop_cost (stmt_info, slp_node, outside_cost);
+}
+
+
+/* Calculate cost of DR's memory access.  */
+void
+vect_get_load_cost (struct data_reference *dr, int ncopies,
+                    bool add_realign_cost, unsigned int *inside_cost,
+                    unsigned int *outside_cost)
+{
+  int alignment_support_scheme = vect_supportable_dr_alignment (dr, false);
+
+  switch (alignment_support_scheme)
     {
     case dr_aligned:
       {
-        inside_cost += ncopies * TARG_VEC_LOAD_COST;
+        *inside_cost += ncopies * vect_get_stmt_cost (vector_load); 
 
         if (vect_print_dump_info (REPORT_COST))
           fprintf (vect_dump, "vect_model_load_cost: aligned.");
@@ -743,9 +836,14 @@ vect_model_load_cost (stmt_vec_info stmt_info, int ncopies, slp_tree slp_node)
       }
     case dr_unaligned_supported:
       {
-        /* Here, we assign an additional cost for the unaligned load.  */
-        inside_cost += ncopies * TARG_VEC_UNALIGNED_LOAD_COST;
+        gimple stmt = DR_STMT (dr);
+        stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+        tree vectype = STMT_VINFO_VECTYPE (stmt_info);
 
+        /* Here, we assign an additional cost for the unaligned load.  */
+        *inside_cost += ncopies
+          * targetm.vectorize.builtin_vectorization_cost (unaligned_load,
+                                           vectype, DR_MISALIGNMENT (dr));
         if (vect_print_dump_info (REPORT_COST))
           fprintf (vect_dump, "vect_model_load_cost: unaligned supported by "
                    "hardware.");
@@ -754,13 +852,14 @@ vect_model_load_cost (stmt_vec_info stmt_info, int ncopies, slp_tree slp_node)
       }
     case dr_explicit_realign:
       {
-        inside_cost += ncopies * (2*TARG_VEC_LOAD_COST + TARG_VEC_STMT_COST);
+        *inside_cost += ncopies * (2 * vect_get_stmt_cost (vector_load)
+           + vect_get_stmt_cost (vector_stmt));
 
         /* FIXME: If the misalignment remains fixed across the iterations of
            the containing loop, the following cost should be added to the
            outside costs.  */
         if (targetm.vectorize.builtin_mask_for_load)
-          inside_cost += TARG_VEC_STMT_COST;
+          *inside_cost += vect_get_stmt_cost (vector_stmt);
 
         break;
       }
@@ -777,29 +876,21 @@ vect_model_load_cost (stmt_vec_info stmt_info, int ncopies, slp_tree slp_node)
            access in the group. Inside the loop, there is a load op
            and a realignment op.  */
 
-        if ((!DR_GROUP_FIRST_DR (stmt_info)) || group_size > 1 || slp_node)
+        if (add_realign_cost)
           {
-            outside_cost = 2*TARG_VEC_STMT_COST;
+            *outside_cost = 2 * vect_get_stmt_cost (vector_stmt);
             if (targetm.vectorize.builtin_mask_for_load)
-              outside_cost += TARG_VEC_STMT_COST;
+              *outside_cost += vect_get_stmt_cost (vector_stmt);
           }
 
-        inside_cost += ncopies * (TARG_VEC_LOAD_COST + TARG_VEC_STMT_COST);
-
+        *inside_cost += ncopies * (vect_get_stmt_cost (vector_load)
+          + vect_get_stmt_cost (vector_stmt));
         break;
       }
 
     default:
       gcc_unreachable ();
     }
-
-  if (vect_print_dump_info (REPORT_COST))
-    fprintf (vect_dump, "vect_model_load_cost: inside_cost = %d, "
-             "outside_cost = %d .", inside_cost, outside_cost);
-
-  /* Set the costs either in STMT_INFO or SLP_NODE (if exists).  */
-  stmt_vinfo_set_inside_of_loop_cost (stmt_info, slp_node, inside_cost);
-  stmt_vinfo_set_outside_of_loop_cost (stmt_info, slp_node, outside_cost);
 }
 
 
@@ -1134,7 +1225,7 @@ vect_get_vec_defs (tree op0, tree op1, gimple stmt,
                   slp_tree slp_node)
 {
   if (slp_node)
-    vect_get_slp_defs (slp_node, vec_oprnds0, vec_oprnds1);
+    vect_get_slp_defs (slp_node, vec_oprnds0, vec_oprnds1, -1);
   else
     {
       tree vec_oprnd;
@@ -1189,7 +1280,6 @@ tree
 vectorizable_function (gimple call, tree vectype_out, tree vectype_in)
 {
   tree fndecl = gimple_call_fndecl (call);
-  enum built_in_function code;
 
   /* We only handle functions that do not read or clobber memory -- i.e.
      const or novops ones.  */
@@ -1201,8 +1291,7 @@ vectorizable_function (gimple call, tree vectype_out, tree vectype_in)
       || !DECL_BUILT_IN (fndecl))
     return NULL_TREE;
 
-  code = DECL_FUNCTION_CODE (fndecl);
-  return targetm.vectorize.builtin_vectorized_function (code, vectype_out,
+  return targetm.vectorize.builtin_vectorized_function (fndecl, vectype_out,
                                                        vectype_in);
 }
 
@@ -1225,7 +1314,7 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt)
   int nunits_in;
   int nunits_out;
   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
-  tree fndecl, new_temp, def, rhs_type, lhs_type;
+  tree fndecl, new_temp, def, rhs_type;
   gimple def_stmt;
   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
   gimple new_stmt = NULL;
@@ -1254,8 +1343,11 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt)
   if (TREE_CODE (gimple_call_lhs (stmt)) != SSA_NAME)
     return false;
 
+  vectype_out = STMT_VINFO_VECTYPE (stmt_info);
+
   /* Process function arguments.  */
   rhs_type = NULL_TREE;
+  vectype_in = NULL_TREE;
   nargs = gimple_call_num_args (stmt);
 
   /* Bail out if the function has more than two arguments, we
@@ -1266,38 +1358,59 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt)
 
   for (i = 0; i < nargs; i++)
     {
+      tree opvectype;
+
       op = gimple_call_arg (stmt, i);
 
       /* We can only handle calls with arguments of the same type.  */
       if (rhs_type
-         && rhs_type != TREE_TYPE (op))
+         && !types_compatible_p (rhs_type, TREE_TYPE (op)))
        {
          if (vect_print_dump_info (REPORT_DETAILS))
            fprintf (vect_dump, "argument types differ.");
          return false;
        }
-      rhs_type = TREE_TYPE (op);
+      if (!rhs_type)
+       rhs_type = TREE_TYPE (op);
 
-      if (!vect_is_simple_use (op, loop_vinfo, NULL, &def_stmt, &def, &dt[i]))
+      if (!vect_is_simple_use_1 (op, loop_vinfo, NULL,
+                                &def_stmt, &def, &dt[i], &opvectype))
        {
          if (vect_print_dump_info (REPORT_DETAILS))
            fprintf (vect_dump, "use not simple.");
          return false;
        }
-    }
 
-  vectype_in = get_vectype_for_scalar_type (rhs_type);
+      if (!vectype_in)
+       vectype_in = opvectype;
+      else if (opvectype
+              && opvectype != vectype_in)
+       {
+         if (vect_print_dump_info (REPORT_DETAILS))
+           fprintf (vect_dump, "argument vector types differ.");
+         return false;
+       }
+    }
+  /* If all arguments are external or constant defs use a vector type with
+     the same size as the output vector type.  */
   if (!vectype_in)
-    return false;
-  nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
+    vectype_in = get_same_sized_vectype (rhs_type, vectype_out);
+  if (vec_stmt)
+    gcc_assert (vectype_in);
+  if (!vectype_in)
+    {
+      if (vect_print_dump_info (REPORT_DETAILS))
+        {
+          fprintf (vect_dump, "no vectype for scalar type ");
+          print_generic_expr (vect_dump, rhs_type, TDF_SLIM);
+        }
 
-  lhs_type = TREE_TYPE (gimple_call_lhs (stmt));
-  vectype_out = get_vectype_for_scalar_type (lhs_type);
-  if (!vectype_out)
-    return false;
-  nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
+      return false;
+    }
 
   /* FORNOW */
+  nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
+  nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
   if (nunits_in == nunits_out / 2)
     modifier = NARROW;
   else if (nunits_out == nunits_in)
@@ -1548,13 +1661,12 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
   int nunits_out;
   tree vectype_out, vectype_in;
   int ncopies, j;
-  tree rhs_type, lhs_type;
+  tree rhs_type;
   tree builtin_decl;
   enum { NARROW, NONE, WIDEN } modifier;
   int i;
   VEC(tree,heap) *vec_oprnds0 = NULL;
   tree vop0;
-  tree integral_type;
   VEC(tree,heap) *dummy = NULL;
   int dummy_int;
 
@@ -1580,21 +1692,39 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
     return false;
 
   /* Check types of lhs and rhs.  */
+  scalar_dest = gimple_assign_lhs (stmt);
+  vectype_out = STMT_VINFO_VECTYPE (stmt_info);
+
   op0 = gimple_assign_rhs1 (stmt);
   rhs_type = TREE_TYPE (op0);
-  vectype_in = get_vectype_for_scalar_type (rhs_type);
+  /* Check the operands of the operation.  */
+  if (!vect_is_simple_use_1 (op0, loop_vinfo, NULL,
+                            &def_stmt, &def, &dt[0], &vectype_in))
+    {
+      if (vect_print_dump_info (REPORT_DETAILS))
+       fprintf (vect_dump, "use not simple.");
+      return false;
+    }
+  /* If op0 is an external or constant defs use a vector type of
+     the same size as the output vector type.  */
   if (!vectype_in)
-    return false;
-  nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
+    vectype_in = get_same_sized_vectype (rhs_type, vectype_out);
+  if (vec_stmt)
+    gcc_assert (vectype_in);
+  if (!vectype_in)
+    {
+      if (vect_print_dump_info (REPORT_DETAILS))
+        {
+          fprintf (vect_dump, "no vectype for scalar type ");
+          print_generic_expr (vect_dump, rhs_type, TDF_SLIM);
+        }
 
-  scalar_dest = gimple_assign_lhs (stmt);
-  lhs_type = TREE_TYPE (scalar_dest);
-  vectype_out = get_vectype_for_scalar_type (lhs_type);
-  if (!vectype_out)
-    return false;
-  nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
+      return false;
+    }
 
   /* FORNOW */
+  nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
+  nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
   if (nunits_in == nunits_out / 2)
     modifier = NARROW;
   else if (nunits_out == nunits_in)
@@ -1604,16 +1734,6 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
   else
     return false;
 
-  if (modifier == NONE)
-    gcc_assert (STMT_VINFO_VECTYPE (stmt_info) == vectype_out);
-
-  /* Bail out if the types are both integral or non-integral.  */
-  if ((INTEGRAL_TYPE_P (rhs_type) && INTEGRAL_TYPE_P (lhs_type))
-      || (!INTEGRAL_TYPE_P (rhs_type) && !INTEGRAL_TYPE_P (lhs_type)))
-    return false;
-
-  integral_type = INTEGRAL_TYPE_P (rhs_type) ? vectype_in : vectype_out;
-
   if (modifier == NARROW)
     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_out;
   else
@@ -1628,24 +1748,17 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
      needs to be generated.  */
   gcc_assert (ncopies >= 1);
 
-  /* Check the operands of the operation.  */
-  if (!vect_is_simple_use (op0, loop_vinfo, NULL, &def_stmt, &def, &dt[0]))
-    {
-      if (vect_print_dump_info (REPORT_DETAILS))
-       fprintf (vect_dump, "use not simple.");
-      return false;
-    }
-
   /* Supportable by target?  */
   if ((modifier == NONE
-       && !targetm.vectorize.builtin_conversion (code, integral_type))
+       && !targetm.vectorize.builtin_conversion (code, vectype_out, vectype_in))
       || (modifier == WIDEN
-         && !supportable_widening_operation (code, stmt, vectype_in,
+         && !supportable_widening_operation (code, stmt,
+                                             vectype_out, vectype_in,
                                              &decl1, &decl2,
                                              &code1, &code2,
                                               &dummy_int, &dummy))
       || (modifier == NARROW
-         && !supportable_narrowing_operation (code, stmt, vectype_in,
+         && !supportable_narrowing_operation (code, vectype_out, vectype_in,
                                               &code1, &dummy_int, &dummy)))
     {
       if (vect_print_dump_info (REPORT_DETAILS))
@@ -1655,7 +1768,6 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
 
   if (modifier != NONE)
     {
-      STMT_VINFO_VECTYPE (stmt_info) = vectype_in;
       /* FORNOW: SLP not supported.  */
       if (STMT_SLP_TYPE (stmt_info))
        return false;
@@ -1689,7 +1801,8 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
            vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds0, NULL);
 
          builtin_decl =
-           targetm.vectorize.builtin_conversion (code, integral_type);
+           targetm.vectorize.builtin_conversion (code,
+                                                 vectype_out, vectype_in);
          for (i = 0; VEC_iterate (tree, vec_oprnds0, i, vop0); i++)
            {
              /* Arguments are ready. create the new vector stmt.  */
@@ -1721,8 +1834,6 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
          else
            vec_oprnd0 = vect_get_vec_def_for_stmt_copy (dt[0], vec_oprnd0);
 
-         STMT_VINFO_VECTYPE (stmt_info) = vectype_in;
-
          /* Generate first half of the widened result:  */
          new_stmt
            = vect_gen_widened_results_half (code1, decl1,
@@ -1807,7 +1918,7 @@ vectorizable_assignment (gimple stmt, gimple_stmt_iterator *gsi,
   tree def;
   gimple def_stmt;
   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
-  int nunits = TYPE_VECTOR_SUBPARTS (vectype);
+  unsigned int nunits = TYPE_VECTOR_SUBPARTS (vectype);
   int ncopies;
   int i, j;
   VEC(tree,heap) *vec_oprnds = NULL;
@@ -1815,6 +1926,8 @@ vectorizable_assignment (gimple stmt, gimple_stmt_iterator *gsi,
   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
   gimple new_stmt = NULL;
   stmt_vec_info prev_stmt_info = NULL;
+  enum tree_code code;
+  tree vectype_in;
 
   /* Multiple types in SLP are handled by creating the appropriate number of
      vectorized stmts for each SLP node. Hence, NCOPIES is always 1 in
@@ -1840,19 +1953,31 @@ vectorizable_assignment (gimple stmt, gimple_stmt_iterator *gsi,
   if (TREE_CODE (scalar_dest) != SSA_NAME)
     return false;
 
+  code = gimple_assign_rhs_code (stmt);
   if (gimple_assign_single_p (stmt)
-      || gimple_assign_rhs_code (stmt) == PAREN_EXPR)
+      || code == PAREN_EXPR
+      || CONVERT_EXPR_CODE_P (code))
     op = gimple_assign_rhs1 (stmt);
   else
     return false;
 
-  if (!vect_is_simple_use (op, loop_vinfo, bb_vinfo, &def_stmt, &def, &dt[0]))
+  if (!vect_is_simple_use_1 (op, loop_vinfo, bb_vinfo,
+                            &def_stmt, &def, &dt[0], &vectype_in))
     {
       if (vect_print_dump_info (REPORT_DETAILS))
         fprintf (vect_dump, "use not simple.");
       return false;
     }
 
+  /* We can handle NOP_EXPR conversions that do not change the number
+     of elements or the vector size.  */
+  if (CONVERT_EXPR_CODE_P (code)
+      && (!vectype_in
+         || TYPE_VECTOR_SUBPARTS (vectype_in) != nunits
+         || (GET_MODE_SIZE (TYPE_MODE (vectype))
+             != GET_MODE_SIZE (TYPE_MODE (vectype_in)))))
+    return false;
+
   if (!vec_stmt) /* transformation not required.  */
     {
       STMT_VINFO_TYPE (stmt_info) = assignment_vec_info_type;
@@ -1881,6 +2006,8 @@ vectorizable_assignment (gimple stmt, gimple_stmt_iterator *gsi,
       /* Arguments are ready. create the new vector stmt.  */
       for (i = 0; VEC_iterate (tree, vec_oprnds, i, vop); i++)
        {
+        if (CONVERT_EXPR_CODE_P (code))
+          vop = build1 (VIEW_CONVERT_EXPR, vectype, vop);
          new_stmt = gimple_build_assign (vec_dest, vop);
          new_temp = make_ssa_name (vec_dest, new_stmt);
          gimple_assign_set_lhs (new_stmt, new_temp);
@@ -1920,7 +2047,7 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
   tree op0, op1 = NULL;
   tree vec_oprnd1 = NULL_TREE;
   stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
-  tree vectype = STMT_VINFO_VECTYPE (stmt_info);
+  tree vectype;
   loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
   enum tree_code code;
   enum machine_mode vec_mode;
@@ -1934,7 +2061,7 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
   enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
   gimple new_stmt = NULL;
   stmt_vec_info prev_stmt_info;
-  int nunits_in = TYPE_VECTOR_SUBPARTS (vectype);
+  int nunits_in;
   int nunits_out;
   tree vectype_out;
   int ncopies;
@@ -1946,21 +2073,6 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
   int vf;
 
-  if (loop_vinfo)
-    vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
-  else
-    vf = 1;
-
-  /* Multiple types in SLP are handled by creating the appropriate number of
-     vectorized stmts for each SLP node. Hence, NCOPIES is always 1 in
-     case of SLP.  */
-  if (slp_node)
-    ncopies = 1;
-  else
-    ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
-
-  gcc_assert (ncopies >= 1);
-
   if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
     return false;
 
@@ -1974,14 +2086,6 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
   if (TREE_CODE (gimple_assign_lhs (stmt)) != SSA_NAME)
     return false;
 
-  scalar_dest = gimple_assign_lhs (stmt);
-  vectype_out = get_vectype_for_scalar_type (TREE_TYPE (scalar_dest));
-  if (!vectype_out)
-    return false;
-  nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
-  if (nunits_out != nunits_in)
-    return false;
-
   code = gimple_assign_rhs_code (stmt);
 
   /* For pointer addition, we should use the normal plus for
@@ -1998,13 +2102,38 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
       return false;
     }
 
+  scalar_dest = gimple_assign_lhs (stmt);
+  vectype_out = STMT_VINFO_VECTYPE (stmt_info);
+
   op0 = gimple_assign_rhs1 (stmt);
-  if (!vect_is_simple_use (op0, loop_vinfo, bb_vinfo, &def_stmt, &def, &dt[0]))
+  if (!vect_is_simple_use_1 (op0, loop_vinfo, bb_vinfo,
+                            &def_stmt, &def, &dt[0], &vectype))
     {
       if (vect_print_dump_info (REPORT_DETAILS))
         fprintf (vect_dump, "use not simple.");
       return false;
     }
+  /* If op0 is an external or constant def use a vector type with
+     the same size as the output vector type.  */
+  if (!vectype)
+    vectype = get_same_sized_vectype (TREE_TYPE (op0), vectype_out);
+  if (vec_stmt)
+    gcc_assert (vectype);
+  if (!vectype)
+    {
+      if (vect_print_dump_info (REPORT_DETAILS))
+        {
+          fprintf (vect_dump, "no vectype for scalar type ");
+          print_generic_expr (vect_dump, TREE_TYPE (op0), TDF_SLIM);
+        }
+
+      return false;
+    }
+
+  nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
+  nunits_in = TYPE_VECTOR_SUBPARTS (vectype);
+  if (nunits_out != nunits_in)
+    return false;
 
   if (op_type == binary_op)
     {
@@ -2018,6 +2147,21 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
        }
     }
 
+  if (loop_vinfo)
+    vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+  else
+    vf = 1;
+
+  /* Multiple types in SLP are handled by creating the appropriate number of
+     vectorized stmts for each SLP node. Hence, NCOPIES is always 1 in
+     case of SLP.  */
+  if (slp_node)
+    ncopies = 1;
+  else
+    ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_in;
+
+  gcc_assert (ncopies >= 1);
+
   /* If this is a shift/rotate, determine whether the shift amount is a vector,
      or scalar.  If the shift/rotate amount is a vector, use the vector/vector
      shift optabs.  */
@@ -2038,8 +2182,7 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
        {
          optab = optab_for_tree_code (code, vectype, optab_scalar);
          if (optab
-             && (optab_handler (optab, TYPE_MODE (vectype))->insn_code
-                 != CODE_FOR_nothing))
+             && optab_handler (optab, TYPE_MODE (vectype)) != CODE_FOR_nothing)
            {
              scalar_shift_arg = true;
              if (vect_print_dump_info (REPORT_DETAILS))
@@ -2049,7 +2192,7 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
            {
              optab = optab_for_tree_code (code, vectype, optab_vector);
              if (optab
-                 && (optab_handler (optab, TYPE_MODE (vectype))->insn_code
+                 && (optab_handler (optab, TYPE_MODE (vectype))
                      != CODE_FOR_nothing))
                {
                  if (vect_print_dump_info (REPORT_DETAILS))
@@ -2083,7 +2226,7 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
       return false;
     }
   vec_mode = TYPE_MODE (vectype);
-  icode = (int) optab_handler (optab, vec_mode)->insn_code;
+  icode = (int) optab_handler (optab, vec_mode);
   if (icode == CODE_FOR_nothing)
     {
       if (vect_print_dump_info (REPORT_DETAILS))
@@ -2425,16 +2568,42 @@ vectorizable_type_demotion (gimple stmt, gimple_stmt_iterator *gsi,
   if (!CONVERT_EXPR_CODE_P (code))
     return false;
 
+  scalar_dest = gimple_assign_lhs (stmt);
+  vectype_out = STMT_VINFO_VECTYPE (stmt_info);
+
+  /* Check the operands of the operation.  */
   op0 = gimple_assign_rhs1 (stmt);
-  vectype_in = get_vectype_for_scalar_type (TREE_TYPE (op0));
-  if (!vectype_in)
+  if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
+         && INTEGRAL_TYPE_P (TREE_TYPE (op0)))
+        || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (scalar_dest))
+            && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0))
+            && CONVERT_EXPR_CODE_P (code))))
     return false;
-  nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
+  if (!vect_is_simple_use_1 (op0, loop_vinfo, NULL,
+                            &def_stmt, &def, &dt[0], &vectype_in))
+    {
+      if (vect_print_dump_info (REPORT_DETAILS))
+        fprintf (vect_dump, "use not simple.");
+      return false;
+    }
+  /* If op0 is an external def use a vector type with the
+     same size as the output vector type if possible.  */
+  if (!vectype_in)
+    vectype_in = get_same_sized_vectype (TREE_TYPE (op0), vectype_out);
+  if (vec_stmt)
+    gcc_assert (vectype_in);
+  if (!vectype_in)
+    {
+      if (vect_print_dump_info (REPORT_DETAILS))
+        {
+          fprintf (vect_dump, "no vectype for scalar type ");
+          print_generic_expr (vect_dump, TREE_TYPE (op0), TDF_SLIM);
+        }
 
-  scalar_dest = gimple_assign_lhs (stmt);
-  vectype_out = get_vectype_for_scalar_type (TREE_TYPE (scalar_dest));
-  if (!vectype_out)
-    return false;
+      return false;
+    }
+
+  nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
   if (nunits_in >= nunits_out)
     return false;
@@ -2448,28 +2617,11 @@ vectorizable_type_demotion (gimple stmt, gimple_stmt_iterator *gsi,
     ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_out;
   gcc_assert (ncopies >= 1);
 
-  if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
-         && INTEGRAL_TYPE_P (TREE_TYPE (op0)))
-        || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (scalar_dest))
-            && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0))
-            && CONVERT_EXPR_CODE_P (code))))
-    return false;
-
-  /* Check the operands of the operation.  */
-  if (!vect_is_simple_use (op0, loop_vinfo, NULL, &def_stmt, &def, &dt[0]))
-    {
-      if (vect_print_dump_info (REPORT_DETAILS))
-        fprintf (vect_dump, "use not simple.");
-      return false;
-    }
-
   /* Supportable by target?  */
-  if (!supportable_narrowing_operation (code, stmt, vectype_in, &code1,
-                                        &multi_step_cvt, &interm_types))
+  if (!supportable_narrowing_operation (code, vectype_out, vectype_in,
+                                       &code1, &multi_step_cvt, &interm_types))
     return false;
 
-  STMT_VINFO_VECTYPE (stmt_info) = vectype_in;
-
   if (!vec_stmt) /* transformation not required.  */
     {
       STMT_VINFO_TYPE (stmt_info) = type_demotion_vec_info_type;
@@ -2518,7 +2670,7 @@ vectorizable_type_demotion (gimple stmt, gimple_stmt_iterator *gsi,
     {
       /* Handle uses.  */
       if (slp_node)
-        vect_get_slp_defs (slp_node, &vec_oprnds0, NULL);
+        vect_get_slp_defs (slp_node, &vec_oprnds0, NULL, -1);
       else
         {
           VEC_free (tree, heap, vec_oprnds0);
@@ -2695,16 +2847,42 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
       && code != WIDEN_MULT_EXPR)
     return false;
 
+  scalar_dest = gimple_assign_lhs (stmt);
+  vectype_out = STMT_VINFO_VECTYPE (stmt_info);
+
+  /* Check the operands of the operation.  */
   op0 = gimple_assign_rhs1 (stmt);
-  vectype_in = get_vectype_for_scalar_type (TREE_TYPE (op0));
-  if (!vectype_in)
+  if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
+         && INTEGRAL_TYPE_P (TREE_TYPE (op0)))
+        || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (scalar_dest))
+            && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0))
+            && CONVERT_EXPR_CODE_P (code))))
     return false;
-  nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
+  if (!vect_is_simple_use_1 (op0, loop_vinfo, NULL,
+                            &def_stmt, &def, &dt[0], &vectype_in))
+    {
+      if (vect_print_dump_info (REPORT_DETAILS))
+       fprintf (vect_dump, "use not simple.");
+      return false;
+    }
+  /* If op0 is an external or constant def use a vector type with
+     the same size as the output vector type.  */
+  if (!vectype_in)
+    vectype_in = get_same_sized_vectype (TREE_TYPE (op0), vectype_out);
+  if (vec_stmt)
+    gcc_assert (vectype_in);
+  if (!vectype_in)
+    {
+      if (vect_print_dump_info (REPORT_DETAILS))
+        {
+          fprintf (vect_dump, "no vectype for scalar type ");
+          print_generic_expr (vect_dump, TREE_TYPE (op0), TDF_SLIM);
+        }
 
-  scalar_dest = gimple_assign_lhs (stmt);
-  vectype_out = get_vectype_for_scalar_type (TREE_TYPE (scalar_dest));
-  if (!vectype_out)
-    return false;
+      return false;
+    }
+
+  nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
   nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
   if (nunits_in <= nunits_out)
     return false;
@@ -2719,21 +2897,6 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
 
   gcc_assert (ncopies >= 1);
 
-  if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
-         && INTEGRAL_TYPE_P (TREE_TYPE (op0)))
-        || (SCALAR_FLOAT_TYPE_P (TREE_TYPE (scalar_dest))
-            && SCALAR_FLOAT_TYPE_P (TREE_TYPE (op0))
-            && CONVERT_EXPR_CODE_P (code))))
-    return false;
-
-  /* Check the operands of the operation.  */
-  if (!vect_is_simple_use (op0, loop_vinfo, NULL, &def_stmt, &def, &dt[0]))
-    {
-      if (vect_print_dump_info (REPORT_DETAILS))
-       fprintf (vect_dump, "use not simple.");
-      return false;
-    }
-
   op_type = TREE_CODE_LENGTH (code);
   if (op_type == binary_op)
     {
@@ -2747,7 +2910,7 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
     }
 
   /* Supportable by target?  */
-  if (!supportable_widening_operation (code, stmt, vectype_in,
+  if (!supportable_widening_operation (code, stmt, vectype_out, vectype_in,
                                       &decl1, &decl2, &code1, &code2,
                                        &multi_step_cvt, &interm_types))
     return false;
@@ -2756,8 +2919,6 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
      architecture.  */
   gcc_assert (!(multi_step_cvt && op_type == binary_op));
 
-  STMT_VINFO_VECTYPE (stmt_info) = vectype_in;
-
   if (!vec_stmt) /* transformation not required.  */
     {
       STMT_VINFO_TYPE (stmt_info) = type_promotion_vec_info_type;
@@ -2819,7 +2980,7 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
       if (j == 0)
         {
           if (slp_node)
-              vect_get_slp_defs (slp_node, &vec_oprnds0, &vec_oprnds1);
+              vect_get_slp_defs (slp_node, &vec_oprnds0, &vec_oprnds1, -1);
           else
             {
               vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL);
@@ -2942,7 +3103,8 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
       && TREE_CODE (scalar_dest) != INDIRECT_REF
       && TREE_CODE (scalar_dest) != COMPONENT_REF
       && TREE_CODE (scalar_dest) != IMAGPART_EXPR
-      && TREE_CODE (scalar_dest) != REALPART_EXPR)
+      && TREE_CODE (scalar_dest) != REALPART_EXPR
+      && TREE_CODE (scalar_dest) != MEM_REF)
     return false;
 
   gcc_assert (gimple_assign_single_p (stmt));
@@ -2966,7 +3128,7 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
   vec_mode = TYPE_MODE (vectype);
   /* FORNOW. In some cases can vectorize even if data-type not supported
      (e.g. - array initialization with 0).  */
-  if (optab_handler (mov_optab, (int)vec_mode)->insn_code == CODE_FOR_nothing)
+  if (optab_handler (mov_optab, vec_mode) == CODE_FOR_nothing)
     return false;
 
   if (!STMT_VINFO_DATA_REF (stmt_info))
@@ -3031,12 +3193,17 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
        }
 
       if (slp)
-       strided_store = false;
-
-      /* VEC_NUM is the number of vect stmts to be created for this group.  */
-      if (slp)
-       vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
+        {
+          strided_store = false;
+          /* VEC_NUM is the number of vect stmts to be created for this 
+             group.  */
+          vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
+          first_stmt = VEC_index (gimple, SLP_TREE_SCALAR_STMTS (slp_node), 0); 
+          first_dr = STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt));
+        } 
       else
+        /* VEC_NUM is the number of vect stmts to be created for this 
+           group.  */
        vec_num = group_size;
     }
   else
@@ -3052,7 +3219,7 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
   dr_chain = VEC_alloc (tree, heap, group_size);
   oprnds = VEC_alloc (tree, heap, group_size);
 
-  alignment_support_scheme = vect_supportable_dr_alignment (first_dr);
+  alignment_support_scheme = vect_supportable_dr_alignment (first_dr, false);
   gcc_assert (alignment_support_scheme);
 
   /* In case the vectorization factor (VF) is bigger than the number
@@ -3105,7 +3272,7 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
           if (slp)
             {
              /* Get vectorized arguments for SLP_NODE.  */
-              vect_get_slp_defs (slp_node, &vec_oprnds, NULL);
+              vect_get_slp_defs (slp_node, &vec_oprnds, NULL, -1);
 
               vec_oprnd = VEC_index (tree, vec_oprnds, 0);
             }
@@ -3193,7 +3360,10 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
            vec_oprnd = VEC_index (tree, result_chain, i);
 
           if (aligned_access_p (first_dr))
-            data_ref = build_fold_indirect_ref (dataref_ptr);
+           data_ref
+             = build2 (MEM_REF, TREE_TYPE (vec_oprnd), dataref_ptr,
+                       build_int_cst (reference_alias_ptr_type
+                                        (DR_REF (first_dr)), 0));
           else
           {
             int mis = DR_MISALIGNMENT (first_dr);
@@ -3202,11 +3372,6 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
             data_ref = build2 (MISALIGNED_INDIRECT_REF, vectype, dataref_ptr, tmis);
            }
 
-         /* If accesses through a pointer to vectype do not alias the original
-            memory reference we have a problem.  This should never happen.  */
-         gcc_assert (alias_sets_conflict_p (get_alias_set (data_ref),
-                     get_alias_set (gimple_assign_lhs (stmt))));
-
          /* Arguments are ready. Create the new vector stmt.  */
          new_stmt = gimple_build_assign (data_ref, vec_oprnd);
          vect_finish_stmt_generation (stmt, new_stmt, gsi);
@@ -3259,7 +3424,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
   struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr;
   tree vectype = STMT_VINFO_VECTYPE (stmt_info);
   tree new_temp;
-  int mode;
+  enum machine_mode mode;
   gimple new_stmt = NULL;
   tree dummy;
   enum dr_alignment_support alignment_support_scheme;
@@ -3332,18 +3497,19 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
       && code != INDIRECT_REF
       && code != COMPONENT_REF
       && code != IMAGPART_EXPR
-      && code != REALPART_EXPR)
+      && code != REALPART_EXPR
+      && code != MEM_REF)
     return false;
 
   if (!STMT_VINFO_DATA_REF (stmt_info))
     return false;
 
   scalar_type = TREE_TYPE (DR_REF (dr));
-  mode = (int) TYPE_MODE (vectype);
+  mode = TYPE_MODE (vectype);
 
   /* FORNOW. In some cases can vectorize even if data-type not supported
     (e.g. - data copies).  */
-  if (optab_handler (mov_optab, mode)->insn_code == CODE_FOR_nothing)
+  if (optab_handler (mov_optab, mode) == CODE_FOR_nothing)
     {
       if (vect_print_dump_info (REPORT_DETAILS))
        fprintf (vect_dump, "Aligned load, but unsupported type.");
@@ -3416,7 +3582,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
       group_size = vec_num = 1;
     }
 
-  alignment_support_scheme = vect_supportable_dr_alignment (first_dr);
+  alignment_support_scheme = vect_supportable_dr_alignment (first_dr, false);
   gcc_assert (alignment_support_scheme);
 
   /* In case the vectorization factor (VF) is bigger than the number
@@ -3570,7 +3736,10 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
            {
            case dr_aligned:
              gcc_assert (aligned_access_p (first_dr));
-             data_ref = build_fold_indirect_ref (dataref_ptr);
+             data_ref
+               = build2 (MEM_REF, vectype, dataref_ptr,
+                         build_int_cst (reference_alias_ptr_type
+                                          (DR_REF (first_dr)), 0));
              break;
            case dr_unaligned_supported:
              {
@@ -3593,7 +3762,18 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
                                                dr_explicit_realign,
                                                dataref_ptr, NULL);
 
-               data_ref = build1 (ALIGN_INDIRECT_REF, vectype, dataref_ptr);
+               new_stmt = gimple_build_assign_with_ops
+                            (BIT_AND_EXPR, NULL_TREE, dataref_ptr,
+                             build_int_cst
+                               (TREE_TYPE (dataref_ptr),
+                                -(HOST_WIDE_INT)TYPE_ALIGN_UNIT (vectype)));
+               ptr = make_ssa_name (SSA_NAME_VAR (dataref_ptr), new_stmt);
+               gimple_assign_set_lhs (new_stmt, ptr);
+               vect_finish_stmt_generation (stmt, new_stmt, gsi);
+               data_ref
+                 = build2 (MEM_REF, vectype, ptr,
+                           build_int_cst (reference_alias_ptr_type
+                                            (DR_REF (first_dr)), 0));
                vec_dest = vect_create_destination_var (scalar_dest, vectype);
                new_stmt = gimple_build_assign (vec_dest, data_ref);
                new_temp = make_ssa_name (vec_dest, new_stmt);
@@ -3606,19 +3786,37 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
                bump = size_binop (MULT_EXPR, vs_minus_1,
                                   TYPE_SIZE_UNIT (scalar_type));
                ptr = bump_vector_ptr (dataref_ptr, NULL, gsi, stmt, bump);
-               data_ref = build1 (ALIGN_INDIRECT_REF, vectype, ptr);
+               new_stmt = gimple_build_assign_with_ops
+                            (BIT_AND_EXPR, NULL_TREE, ptr,
+                             build_int_cst
+                               (TREE_TYPE (ptr),
+                                -(HOST_WIDE_INT)TYPE_ALIGN_UNIT (vectype)));
+               ptr = make_ssa_name (SSA_NAME_VAR (dataref_ptr), new_stmt);
+               gimple_assign_set_lhs (new_stmt, ptr);
+               vect_finish_stmt_generation (stmt, new_stmt, gsi);
+               data_ref
+                 = build2 (MEM_REF, vectype, ptr,
+                           build_int_cst (reference_alias_ptr_type
+                                            (DR_REF (first_dr)), 0));
                break;
              }
            case dr_explicit_realign_optimized:
-             data_ref = build1 (ALIGN_INDIRECT_REF, vectype, dataref_ptr);
+             new_stmt = gimple_build_assign_with_ops
+                          (BIT_AND_EXPR, NULL_TREE, dataref_ptr,
+                           build_int_cst
+                             (TREE_TYPE (dataref_ptr),
+                              -(HOST_WIDE_INT)TYPE_ALIGN_UNIT (vectype)));
+             new_temp = make_ssa_name (SSA_NAME_VAR (dataref_ptr), new_stmt);
+             gimple_assign_set_lhs (new_stmt, new_temp);
+             vect_finish_stmt_generation (stmt, new_stmt, gsi);
+             data_ref
+               = build2 (MEM_REF, vectype, new_temp,
+                         build_int_cst (reference_alias_ptr_type
+                                          (DR_REF (first_dr)), 0));
              break;
            default:
              gcc_unreachable ();
            }
-         /* If accesses through a pointer to vectype do not alias the original
-            memory reference we have a problem.  This should never happen. */
-         gcc_assert (alias_sets_conflict_p (get_alias_set (data_ref),
-                     get_alias_set (gimple_assign_rhs1 (stmt))));
          vec_dest = vect_create_destination_var (scalar_dest, vectype);
          new_stmt = gimple_build_assign (vec_dest, data_ref);
          new_temp = make_ssa_name (vec_dest, new_stmt);
@@ -3865,7 +4063,8 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
 
   /* We do not handle two different vector types for the condition
      and the values.  */
-  if (TREE_TYPE (TREE_OPERAND (cond_expr, 0)) != TREE_TYPE (vectype))
+  if (!types_compatible_p (TREE_TYPE (TREE_OPERAND (cond_expr, 0)),
+                          TREE_TYPE (vectype)))
     return false;
 
   if (TREE_CODE (then_clause) == SSA_NAME)
@@ -3945,7 +4144,6 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node)
   bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
   enum vect_relevant relevance = STMT_VINFO_RELEVANT (stmt_info);
   bool ok;
-  HOST_WIDE_INT dummy;
   tree scalar_type, vectype;
 
   if (vect_print_dump_info (REPORT_DETAILS))
@@ -4003,7 +4201,7 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node)
     {
       gcc_assert (PURE_SLP_STMT (stmt_info));
 
-      scalar_type = vect_get_smallest_scalar_type (stmt, &dummy, &dummy);
+      scalar_type = TREE_TYPE (gimple_get_lhs (stmt));
       if (vect_print_dump_info (REPORT_DETAILS))
         {
           fprintf (vect_dump, "get vectype for scalar type:  ");
@@ -4049,7 +4247,7 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node)
             || vectorizable_load (stmt, NULL, NULL, NULL, NULL)
             || vectorizable_call (stmt, NULL, NULL)
             || vectorizable_store (stmt, NULL, NULL, NULL)
-            || vectorizable_reduction (stmt, NULL, NULL)
+            || vectorizable_reduction (stmt, NULL, NULL, NULL)
             || vectorizable_condition (stmt, NULL, NULL, NULL, 0));
     else
       {
@@ -4201,8 +4399,7 @@ vect_transform_stmt (gimple stmt, gimple_stmt_iterator *gsi,
       break;
 
     case reduc_vec_info_type:
-      gcc_assert (!slp_node);
-      done = vectorizable_reduction (stmt, gsi, &vec_stmt);
+      done = vectorizable_reduction (stmt, gsi, &vec_stmt, slp_node);
       gcc_assert (done);
       break;
 
@@ -4328,6 +4525,7 @@ new_stmt_vec_info (gimple stmt, loop_vec_info loop_vinfo,
   STMT_VINFO_LIVE_P (res) = false;
   STMT_VINFO_VECTYPE (res) = NULL;
   STMT_VINFO_VEC_STMT (res) = NULL;
+  STMT_VINFO_VECTORIZABLE (res) = true;
   STMT_VINFO_IN_PATTERN_P (res) = false;
   STMT_VINFO_RELATED_STMT (res) = NULL;
   STMT_VINFO_DATA_REF (res) = NULL;
@@ -4417,6 +4615,14 @@ get_vectype_for_scalar_type (tree scalar_type)
   if (nbytes < TYPE_ALIGN_UNIT (scalar_type))
     return NULL_TREE;
 
+  /* If we'd build a vector type of elements whose mode precision doesn't
+     match their types precision we'll get mismatched types on vector
+     extracts via BIT_FIELD_REFs.  This effectively means we disable
+     vectorization of bool and/or enum types in some languages.  */
+  if (INTEGRAL_TYPE_P (scalar_type)
+      && GET_MODE_BITSIZE (inner_mode) != TYPE_PRECISION (scalar_type))
+    return NULL_TREE;
+
   /* FORNOW: Only a single vector size per mode (UNITS_PER_SIMD_WORD)
      is expected.  */
   nunits = UNITS_PER_SIMD_WORD (inner_mode) / nbytes;
@@ -4448,6 +4654,17 @@ get_vectype_for_scalar_type (tree scalar_type)
   return vectype;
 }
 
+/* Function get_same_sized_vectype
+
+   Returns a vector type corresponding to SCALAR_TYPE of size
+   VECTOR_TYPE if supported by the target.  */
+
+tree
+get_same_sized_vectype (tree scalar_type, tree vector_type ATTRIBUTE_UNUSED)
+{
+  return get_vectype_for_scalar_type (scalar_type);
+}
+
 /* Function vect_is_simple_use.
 
    Input:
@@ -4581,12 +4798,55 @@ vect_is_simple_use (tree operand, loop_vec_info loop_vinfo,
   return true;
 }
 
+/* Function vect_is_simple_use_1.
+
+   Same as vect_is_simple_use_1 but also determines the vector operand
+   type of OPERAND and stores it to *VECTYPE.  If the definition of
+   OPERAND is vect_uninitialized_def, vect_constant_def or
+   vect_external_def *VECTYPE will be set to NULL_TREE and the caller
+   is responsible to compute the best suited vector type for the
+   scalar operand.  */
+
+bool
+vect_is_simple_use_1 (tree operand, loop_vec_info loop_vinfo,
+                     bb_vec_info bb_vinfo, gimple *def_stmt,
+                     tree *def, enum vect_def_type *dt, tree *vectype)
+{
+  if (!vect_is_simple_use (operand, loop_vinfo, bb_vinfo, def_stmt, def, dt))
+    return false;
+
+  /* Now get a vector type if the def is internal, otherwise supply
+     NULL_TREE and leave it up to the caller to figure out a proper
+     type for the use stmt.  */
+  if (*dt == vect_internal_def
+      || *dt == vect_induction_def
+      || *dt == vect_reduction_def
+      || *dt == vect_double_reduction_def
+      || *dt == vect_nested_cycle)
+    {
+      stmt_vec_info stmt_info = vinfo_for_stmt (*def_stmt);
+      if (STMT_VINFO_IN_PATTERN_P (stmt_info))
+       stmt_info = vinfo_for_stmt (STMT_VINFO_RELATED_STMT (stmt_info));
+      *vectype = STMT_VINFO_VECTYPE (stmt_info);
+      gcc_assert (*vectype != NULL_TREE);
+    }
+  else if (*dt == vect_uninitialized_def
+          || *dt == vect_constant_def
+          || *dt == vect_external_def)
+    *vectype = NULL_TREE;
+  else
+    gcc_unreachable ();
+
+  return true;
+}
+
 
 /* Function supportable_widening_operation
 
    Check whether an operation represented by the code CODE is a
    widening operation that is supported by the target platform in
-   vector form (i.e., when operating on arguments of type VECTYPE).
+   vector form (i.e., when operating on arguments of type VECTYPE_IN
+   producing a result of type VECTYPE_OUT).
 
    Widening operations we currently support are NOP (CONVERT), FLOAT
    and WIDEN_MULT.  This function checks if these operations are supported
@@ -4606,7 +4866,8 @@ vect_is_simple_use (tree operand, loop_vec_info loop_vinfo,
    widening operation (short in the above example).  */
 
 bool
-supportable_widening_operation (enum tree_code code, gimple stmt, tree vectype,
+supportable_widening_operation (enum tree_code code, gimple stmt,
+                               tree vectype_out, tree vectype_in,
                                 tree *decl1, tree *decl2,
                                 enum tree_code *code1, enum tree_code *code2,
                                 int *multi_step_cvt,
@@ -4619,8 +4880,8 @@ supportable_widening_operation (enum tree_code code, gimple stmt, tree vectype,
   enum machine_mode vec_mode;
   enum insn_code icode1, icode2;
   optab optab1, optab2;
-  tree type = gimple_expr_type (stmt);
-  tree wide_vectype = get_vectype_for_scalar_type (type);
+  tree vectype = vectype_in;
+  tree wide_vectype = vectype_out;
   enum tree_code c1, c2;
 
   /* The result of a vectorized widening operation usually requires two vectors
@@ -4719,8 +4980,8 @@ supportable_widening_operation (enum tree_code code, gimple stmt, tree vectype,
   if (code == FIX_TRUNC_EXPR)
     {
       /* The signedness is determined from output operand.  */
-      optab1 = optab_for_tree_code (c1, type, optab_default);
-      optab2 = optab_for_tree_code (c2, type, optab_default);
+      optab1 = optab_for_tree_code (c1, vectype_out, optab_default);
+      optab2 = optab_for_tree_code (c2, vectype_out, optab_default);
     }
   else
     {
@@ -4732,9 +4993,8 @@ supportable_widening_operation (enum tree_code code, gimple stmt, tree vectype,
     return false;
 
   vec_mode = TYPE_MODE (vectype);
-  if ((icode1 = optab_handler (optab1, vec_mode)->insn_code) == CODE_FOR_nothing
-       || (icode2 = optab_handler (optab2, vec_mode)->insn_code)
-                                                       == CODE_FOR_nothing)
+  if ((icode1 = optab_handler (optab1, vec_mode)) == CODE_FOR_nothing
+       || (icode2 = optab_handler (optab2, vec_mode)) == CODE_FOR_nothing)
     return false;
 
   /* Check if it's a multi-step conversion that can be done using intermediate
@@ -4766,16 +5026,16 @@ supportable_widening_operation (enum tree_code code, gimple stmt, tree vectype,
           optab4 = optab_for_tree_code (c2, intermediate_type, optab_default);
 
           if (!optab3 || !optab4
-              || (icode1 = optab1->handlers[(int) prev_mode].insn_code)
-                                                        == CODE_FOR_nothing
+              || ((icode1 = optab_handler (optab1, prev_mode))
+                 == CODE_FOR_nothing)
               || insn_data[icode1].operand[0].mode != intermediate_mode
-              || (icode2 = optab2->handlers[(int) prev_mode].insn_code)
-                                                        == CODE_FOR_nothing
+              || ((icode2 = optab_handler (optab2, prev_mode))
+                 == CODE_FOR_nothing)
               || insn_data[icode2].operand[0].mode != intermediate_mode
-              || (icode1 = optab3->handlers[(int) intermediate_mode].insn_code)
-                                                        == CODE_FOR_nothing
-              || (icode2 = optab4->handlers[(int) intermediate_mode].insn_code)
-                                                        == CODE_FOR_nothing)
+              || ((icode1 = optab_handler (optab3, intermediate_mode))
+                 == CODE_FOR_nothing)
+              || ((icode2 = optab_handler (optab4, intermediate_mode))
+                 == CODE_FOR_nothing))
             return false;
 
           VEC_quick_push (tree, *interm_types, intermediate_type);
@@ -4802,7 +5062,8 @@ supportable_widening_operation (enum tree_code code, gimple stmt, tree vectype,
 
    Check whether an operation represented by the code CODE is a
    narrowing operation that is supported by the target platform in
-   vector form (i.e., when operating on arguments of type VECTYPE).
+   vector form (i.e., when operating on arguments of type VECTYPE_IN
+   and producing a result of type VECTYPE_OUT).
 
    Narrowing operations we currently support are NOP (CONVERT) and
    FIX_TRUNC. This function checks if these operations are supported by
@@ -4819,15 +5080,15 @@ supportable_widening_operation (enum tree_code code, gimple stmt, tree vectype,
 
 bool
 supportable_narrowing_operation (enum tree_code code,
-                                const_gimple stmt, tree vectype,
+                                tree vectype_out, tree vectype_in,
                                 enum tree_code *code1, int *multi_step_cvt,
                                  VEC (tree, heap) **interm_types)
 {
   enum machine_mode vec_mode;
   enum insn_code icode1;
   optab optab1, interm_optab;
-  tree type = gimple_expr_type (stmt);
-  tree narrow_vectype = get_vectype_for_scalar_type (type);
+  tree vectype = vectype_in;
+  tree narrow_vectype = vectype_out;
   enum tree_code c1;
   tree intermediate_type, prev_type;
   int i;
@@ -4853,7 +5114,7 @@ supportable_narrowing_operation (enum tree_code code,
 
   if (code == FIX_TRUNC_EXPR)
     /* The signedness is determined from output operand.  */
-    optab1 = optab_for_tree_code (c1, type, optab_default);
+    optab1 = optab_for_tree_code (c1, vectype_out, optab_default);
   else
     optab1 = optab_for_tree_code (c1, vectype, optab_default);
 
@@ -4861,8 +5122,7 @@ supportable_narrowing_operation (enum tree_code code,
     return false;
 
   vec_mode = TYPE_MODE (vectype);
-  if ((icode1 = optab_handler (optab1, vec_mode)->insn_code)
-       == CODE_FOR_nothing)
+  if ((icode1 = optab_handler (optab1, vec_mode)) == CODE_FOR_nothing)
     return false;
 
   /* Check if it's a multi-step conversion that can be done using intermediate
@@ -4885,12 +5145,11 @@ supportable_narrowing_operation (enum tree_code code,
           interm_optab = optab_for_tree_code (c1, intermediate_type,
                                               optab_default);
           if (!interm_optab
-              || (icode1 = optab1->handlers[(int) prev_mode].insn_code)
-                                                        == CODE_FOR_nothing
+              || ((icode1 = optab_handler (optab1, prev_mode))
+                 == CODE_FOR_nothing)
               || insn_data[icode1].operand[0].mode != intermediate_mode
-              || (icode1
-                  = interm_optab->handlers[(int) intermediate_mode].insn_code)
-                 == CODE_FOR_nothing)
+              || ((icode1 = optab_handler (interm_optab, intermediate_mode))
+                 == CODE_FOR_nothing))
             return false;
 
           VEC_quick_push (tree, *interm_types, intermediate_type);