diff gcc/tree-vect-stmts.c @ 63:b7f97abdc517 gcc-4.6-20100522

update gcc from gcc-4.5.0 to gcc-4.6
author ryoma <e075725@ie.u-ryukyu.ac.jp>
date Mon, 24 May 2010 12:47:05 +0900
parents 77e2b8dfacca
children f6334be47118
line wrap: on
line diff
--- a/gcc/tree-vect-stmts.c	Fri Feb 12 23:41:23 2010 +0900
+++ b/gcc/tree-vect-stmts.c	Mon May 24 12:47:05 2010 +0900
@@ -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>
 
@@ -29,6 +29,8 @@
 #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"
@@ -1134,7 +1136,7 @@
 		   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 +1191,6 @@
 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 +1202,7 @@
       || !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 +1225,7 @@
   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 +1254,11 @@
   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 +1269,59 @@
 
   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 (!vect_is_simple_use (op, loop_vinfo, NULL, &def_stmt, &def, &dt[i]))
+      if (!rhs_type)
+	rhs_type = TREE_TYPE (op);
+
+      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;
 	}
+
+      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;
+	}
     }
-
-  vectype_in = get_vectype_for_scalar_type (rhs_type);
+  /* 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);
-
-  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);
+    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);
+        }
+
+      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 +1572,12 @@
   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 +1603,39 @@
     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);
-
-  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);
+    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);
+        }
+
+      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 +1645,6 @@
   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 +1659,17 @@
      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 +1679,6 @@
 
   if (modifier != NONE)
     {
-      STMT_VINFO_VECTYPE (stmt_info) = vectype_in;
       /* FORNOW: SLP not supported.  */
       if (STMT_SLP_TYPE (stmt_info))
 	return false;
@@ -1689,7 +1712,8 @@
 	    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 +1745,6 @@
 	  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,
@@ -1920,7 +1942,7 @@
   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 +1956,7 @@
   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 +1968,6 @@
   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 +1981,6 @@
   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 +1997,38 @@
       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 +2042,21 @@
 	}
     }
 
+  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.  */
@@ -2425,16 +2464,42 @@
   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 (! ((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;
+  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)
-    return false;
+    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);
+        }
+
+      return false;
+    }
+
   nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
-
-  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_in >= nunits_out)
     return false;
@@ -2448,28 +2513,11 @@
     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))))
+  /* Supportable by target?  */
+  if (!supportable_narrowing_operation (code, vectype_out, vectype_in,
+					&code1, &multi_step_cvt, &interm_types))
     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))
-    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 +2566,7 @@
     {
       /* 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 +2743,42 @@
       && 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 (! ((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;
+  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)
-    return false;
+    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);
+        }
+
+      return false;
+    }
+
   nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
-
-  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_in <= nunits_out)
     return false;
@@ -2719,21 +2793,6 @@
 
   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 +2806,7 @@
     }
 
   /* 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 +2815,6 @@
      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 +2876,7 @@
       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);
@@ -3031,12 +3088,17 @@
 	}
 
       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
@@ -3105,7 +3167,7 @@
           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);
             }
@@ -3865,7 +3927,8 @@
 
   /* 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 +4008,6 @@
   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 +4065,7 @@
     {
       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 +4111,7 @@
             || 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 +4263,7 @@
       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 +4389,7 @@
   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;
@@ -4405,13 +4467,26 @@
 get_vectype_for_scalar_type (tree scalar_type)
 {
   enum machine_mode inner_mode = TYPE_MODE (scalar_type);
-  int nbytes = GET_MODE_SIZE (inner_mode);
+  unsigned int nbytes = GET_MODE_SIZE (inner_mode);
   int nunits;
   tree vectype;
 
   if (nbytes == 0 || nbytes >= UNITS_PER_SIMD_WORD (inner_mode))
     return NULL_TREE;
 
+  /* We can't build a vector type of elements with alignment bigger than
+     their size.  */
+  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;
@@ -4443,6 +4518,17 @@
   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:
@@ -4576,12 +4662,55 @@
   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
@@ -4601,7 +4730,8 @@
    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,
@@ -4614,8 +4744,8 @@
   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
@@ -4714,8 +4844,8 @@
   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
     {
@@ -4797,7 +4927,8 @@
 
    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
@@ -4814,15 +4945,15 @@
 
 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;
@@ -4848,7 +4979,7 @@
 
   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);