/* 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.
#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. */
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;
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
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++)
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;
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));
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++)
{
{
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;
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);
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)
{
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);
!= 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);
}
}
}
- 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,
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))
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,
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
/* 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;
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;
/* 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))