poly_int: GET_MODE_NUNITS
[platform/upstream/gcc.git] / gcc / tree-vect-generic.c
index b214208..c0cc656 100644 (file)
@@ -1,5 +1,5 @@
 /* Lower vector operations to scalar operations.
-   Copyright (C) 2004-2017 Free Software Foundation, Inc.
+   Copyright (C) 2004-2018 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -38,10 +38,31 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimplify.h"
 #include "tree-cfg.h"
 #include "tree-vector-builder.h"
+#include "vec-perm-indices.h"
 
 
 static void expand_vector_operations_1 (gimple_stmt_iterator *);
 
+/* Return the number of elements in a vector type TYPE that we have
+   already decided needs to be expanded piecewise.  We don't support
+   this kind of expansion for variable-length vectors, since we should
+   always check for target support before introducing uses of those.  */
+static unsigned int
+nunits_for_known_piecewise_op (const_tree type)
+{
+  return TYPE_VECTOR_SUBPARTS (type);
+}
+
+/* Return true if TYPE1 has more elements than TYPE2, where either
+   type may be a vector or a scalar.  */
+
+static inline bool
+subparts_gt (tree type1, tree type2)
+{
+  poly_uint64 n1 = VECTOR_TYPE_P (type1) ? TYPE_VECTOR_SUBPARTS (type1) : 1;
+  poly_uint64 n2 = VECTOR_TYPE_P (type2) ? TYPE_VECTOR_SUBPARTS (type2) : 1;
+  return known_gt (n1, n2);
+}
 
 /* Build a constant of type TYPE, made of VALUE's bits replicated
    every TYPE_SIZE (INNER_TYPE) bits to fit TYPE's precision.  */
@@ -255,7 +276,7 @@ expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
   vec<constructor_elt, va_gc> *v;
   tree part_width = TYPE_SIZE (inner_type);
   tree index = bitsize_int (0);
-  int nunits = TYPE_VECTOR_SUBPARTS (type);
+  int nunits = nunits_for_known_piecewise_op (type);
   int delta = tree_to_uhwi (part_width)
              / tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type)));
   int i;
@@ -339,7 +360,7 @@ expand_vector_addition (gimple_stmt_iterator *gsi,
 
   if (INTEGRAL_TYPE_P (TREE_TYPE (type))
       && parts_per_word >= 4
-      && TYPE_VECTOR_SUBPARTS (type) >= 4)
+      && nunits_for_known_piecewise_op (type) >= 4)
     return expand_vector_parallel (gsi, f_parallel,
                                   type, a, b, code);
   else
@@ -374,7 +395,7 @@ static tree
 add_rshift (gimple_stmt_iterator *gsi, tree type, tree op0, int *shiftcnts)
 {
   optab op;
-  unsigned int i, nunits = TYPE_VECTOR_SUBPARTS (type);
+  unsigned int i, nunits = nunits_for_known_piecewise_op (type);
   bool scalar_shift = true;
 
   for (i = 1; i < nunits; i++)
@@ -418,7 +439,7 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
   bool has_vector_shift = true;
   int mode = -1, this_mode;
   int pre_shift = -1, post_shift;
-  unsigned int nunits = TYPE_VECTOR_SUBPARTS (type);
+  unsigned int nunits = nunits_for_known_piecewise_op (type);
   int *shifts = XALLOCAVEC (int, nunits * 4);
   int *pre_shifts = shifts + nunits;
   int *post_shifts = pre_shifts + nunits;
@@ -867,7 +888,6 @@ expand_vector_condition (gimple_stmt_iterator *gsi)
   tree index = bitsize_int (0);
   tree comp_width = width;
   tree comp_index = index;
-  int nunits = TYPE_VECTOR_SUBPARTS (type);
   int i;
   location_t loc = gimple_location (gsi_stmt (*gsi));
 
@@ -920,6 +940,7 @@ expand_vector_condition (gimple_stmt_iterator *gsi)
   warning_at (loc, OPT_Wvector_operation_performance,
              "vector condition will be expanded piecewise");
 
+  int nunits = nunits_for_known_piecewise_op (type);
   vec_alloc (v, nunits);
   for (i = 0; i < nunits; i++)
     {
@@ -1139,7 +1160,7 @@ type_for_widest_vector_mode (tree type, optab op)
 {
   machine_mode inner_mode = TYPE_MODE (type);
   machine_mode best_mode = VOIDmode, mode;
-  int best_nunits = 0;
+  poly_int64 best_nunits = 0;
 
   if (SCALAR_FLOAT_MODE_P (inner_mode))
     mode = MIN_MODE_VECTOR_FLOAT;
@@ -1156,7 +1177,7 @@ type_for_widest_vector_mode (tree type, optab op)
 
   FOR_EACH_MODE_FROM (mode, mode)
     if (GET_MODE_INNER (mode) == inner_mode
-        && GET_MODE_NUNITS (mode) > best_nunits
+       && maybe_gt (GET_MODE_NUNITS (mode), best_nunits)
        && optab_handler (op, mode) != CODE_FOR_nothing)
       best_mode = mode, best_nunits = GET_MODE_NUNITS (mode);
 
@@ -1189,7 +1210,7 @@ vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
 
   vect_type = TREE_TYPE (vect);
   vect_elt_type = TREE_TYPE (vect_type);
-  elements = TYPE_VECTOR_SUBPARTS (vect_type);
+  elements = nunits_for_known_piecewise_op (vect_type);
 
   if (TREE_CODE (idx) == INTEGER_CST)
     {
@@ -1298,15 +1319,13 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
        mask = gimple_assign_rhs1 (def_stmt);
     }
 
-  if (TREE_CODE (mask) == VECTOR_CST)
-    {
-      auto_vec_perm_indices sel_int (elements);
-
-      for (i = 0; i < elements; ++i)
-       sel_int.quick_push (TREE_INT_CST_LOW (VECTOR_CST_ELT (mask, i))
-                           & (2 * elements - 1));
+  vec_perm_builder sel_int;
 
-      if (can_vec_perm_p (TYPE_MODE (vect_type), false, &sel_int))
+  if (TREE_CODE (mask) == VECTOR_CST
+      && tree_to_vec_perm_builder (&sel_int, mask))
+    {
+      vec_perm_indices indices (sel_int, 2, elements);
+      if (can_vec_perm_const_p (TYPE_MODE (vect_type), indices))
        {
          gimple_assign_set_rhs3 (stmt, mask);
          update_stmt (stmt);
@@ -1318,18 +1337,24 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
          != CODE_FOR_nothing
          && TREE_CODE (vec1) == VECTOR_CST
          && initializer_zerop (vec1)
-         && sel_int[0]
-         && sel_int[0] < elements)
+         && maybe_ne (indices[0], 0)
+         && known_lt (indices[0], elements))
        {
-         for (i = 1; i < elements; ++i)
+         bool ok_p = indices.series_p (0, 1, indices[0], 1);
+         if (!ok_p)
            {
-             unsigned int expected = i + sel_int[0];
-             /* Indices into the second vector are all equivalent.  */
-             if (MIN (elements, (unsigned) sel_int[i])
-                 != MIN (elements, expected))
-               break;
+             for (i = 1; i < elements; ++i)
+               {
+                 poly_int64 expected = i + indices[0];
+                 /* Indices into the second vector are all equivalent.  */
+                 if (maybe_lt (indices[i], elements)
+                     ? maybe_ne (indices[i], expected)
+                     : maybe_lt (expected, elements))
+                   break;
+               }
+             ok_p = i == elements;
            }
-         if (i == elements)
+         if (ok_p)
            {
              gimple_assign_set_rhs3 (stmt, mask);
              update_stmt (stmt);
@@ -1337,7 +1362,7 @@ lower_vec_perm (gimple_stmt_iterator *gsi)
            }
        }
     }
-  else if (can_vec_perm_p (TYPE_MODE (vect_type), true, NULL))
+  else if (can_vec_perm_var_p (TYPE_MODE (vect_type)))
     return;
   
   warning_at (loc, OPT_Wvector_operation_performance,
@@ -1446,8 +1471,7 @@ get_compute_type (enum tree_code code, optab op, tree type)
       tree vector_compute_type
        = type_for_widest_vector_mode (TREE_TYPE (type), op);
       if (vector_compute_type != NULL_TREE
-         && (TYPE_VECTOR_SUBPARTS (vector_compute_type)
-             < TYPE_VECTOR_SUBPARTS (compute_type))
+         && subparts_gt (compute_type, vector_compute_type)
          && TYPE_VECTOR_SUBPARTS (vector_compute_type) > 1
          && (optab_handler (op, TYPE_MODE (vector_compute_type))
              != CODE_FOR_nothing))
@@ -1476,15 +1500,6 @@ get_compute_type (enum tree_code code, optab op, tree type)
   return compute_type;
 }
 
-/* Helper function of expand_vector_operations_1.  Return number of
-   vector elements for vector types or 1 for other types.  */
-
-static inline int
-count_type_subparts (tree type)
-{
-  return VECTOR_TYPE_P (type) ? TYPE_VECTOR_SUBPARTS (type) : 1;
-}
-
 static tree
 do_cond (gimple_stmt_iterator *gsi, tree inner_type, tree a, tree b,
         tree bitpos, tree bitsize, enum tree_code code,
@@ -1595,7 +1610,8 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
   if (rhs_class == GIMPLE_BINARY_RHS)
     rhs2 = gimple_assign_rhs2 (stmt);
 
-  if (TREE_CODE (type) != VECTOR_TYPE)
+  if (!VECTOR_TYPE_P (type)
+      || !VECTOR_TYPE_P (TREE_TYPE (rhs1)))
     return;
 
   /* If the vector operation is operating on all same vector elements
@@ -1703,8 +1719,7 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
          /* The rtl expander will expand vector/scalar as vector/vector
             if necessary.  Pick one with wider vector type.  */
          tree compute_vtype = get_compute_type (code, opv, type);
-         if (count_type_subparts (compute_vtype)
-             > count_type_subparts (compute_type))
+         if (subparts_gt (compute_vtype, compute_type))
            {
              compute_type = compute_vtype;
              op = opv;
@@ -1734,14 +1749,12 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
              tree compute_rtype = get_compute_type (RSHIFT_EXPR, opr, type);
              /* The rtl expander will expand vector/scalar as vector/vector
                 if necessary.  Pick one with wider vector type.  */
-             if (count_type_subparts (compute_lvtype)
-                 > count_type_subparts (compute_ltype))
+             if (subparts_gt (compute_lvtype, compute_ltype))
                {
                  compute_ltype = compute_lvtype;
                  opl = oplv;
                }
-             if (count_type_subparts (compute_rvtype)
-                 > count_type_subparts (compute_rtype))
+             if (subparts_gt (compute_rvtype, compute_rtype))
                {
                  compute_rtype = compute_rvtype;
                  opr = oprv;
@@ -1749,11 +1762,9 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
              /* Pick the narrowest type from LSHIFT_EXPR, RSHIFT_EXPR and
                 BIT_IOR_EXPR.  */
              compute_type = compute_ltype;
-             if (count_type_subparts (compute_type)
-                 > count_type_subparts (compute_rtype))
+             if (subparts_gt (compute_type, compute_rtype))
                compute_type = compute_rtype;
-             if (count_type_subparts (compute_type)
-                 > count_type_subparts (compute_otype))
+             if (subparts_gt (compute_type, compute_otype))
                compute_type = compute_otype;
              /* Verify all 3 operations can be performed in that type.  */
              if (compute_type != TREE_TYPE (type))