OSDN Git Service

2010-04-08 Manuel López-Ibáñez <manu@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / tree-vect-stmts.c
index c280e81..a70ebfe 100644 (file)
@@ -29,6 +29,8 @@ along with GCC; see the file COPYING3.  If not see
 #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 @@ 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;
@@ -1223,7 +1225,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;
@@ -1252,8 +1254,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
@@ -1264,38 +1269,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)
@@ -1546,13 +1572,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;
 
@@ -1578,21 +1603,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)
@@ -1602,16 +1645,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
@@ -1626,24 +1659,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))
@@ -1653,7 +1679,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;
@@ -1687,7 +1712,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.  */
@@ -1719,8 +1745,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,
@@ -1918,7 +1942,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;
@@ -1932,7 +1956,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;
@@ -1944,21 +1968,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;
 
@@ -1972,14 +1981,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
@@ -1996,13 +1997,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)
     {
@@ -2016,6 +2042,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.  */
@@ -2423,16 +2464,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;
@@ -2446,28 +2513,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;
@@ -2516,7 +2566,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);
@@ -2693,16 +2743,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;
@@ -2717,21 +2793,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)
     {
@@ -2745,7 +2806,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;
@@ -2754,8 +2815,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;
@@ -2817,7 +2876,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);
@@ -3029,12 +3088,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
@@ -3103,7 +3167,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);
             }
@@ -3863,7 +3927,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)
@@ -3943,7 +4008,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))
@@ -4001,7 +4065,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:  ");
@@ -4047,7 +4111,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
       {
@@ -4199,8 +4263,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;
 
@@ -4326,6 +4389,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;
@@ -4454,6 +4518,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:
@@ -4587,12 +4662,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
@@ -4612,7 +4730,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,
@@ -4625,8 +4744,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
@@ -4725,8 +4844,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
     {
@@ -4808,7 +4927,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
@@ -4825,15 +4945,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;
@@ -4859,7 +4979,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);