aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vect-generic.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-vect-generic.c')
-rw-r--r--gcc/tree-vect-generic.c173
1 files changed, 120 insertions, 53 deletions
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index 8b00f32..6d5d651 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -40,10 +40,11 @@ along with GCC; see the file COPYING3. If not see
#include "tree-vector-builder.h"
#include "vec-perm-indices.h"
#include "insn-config.h"
+#include "tree-ssa-dce.h"
#include "recog.h" /* FIXME: for insn_data */
-static void expand_vector_operations_1 (gimple_stmt_iterator *);
+static void expand_vector_operations_1 (gimple_stmt_iterator *, bitmap);
/* Return the number of elements in a vector type TYPE that we have
already decided needs to be expanded piecewise. We don't support
@@ -67,11 +68,10 @@ subparts_gt (tree type1, tree type2)
}
/* Build a constant of type TYPE, made of VALUE's bits replicated
- every TYPE_SIZE (INNER_TYPE) bits to fit TYPE's precision. */
+ every WIDTH bits to fit TYPE's precision. */
static tree
-build_replicated_const (tree type, tree inner_type, HOST_WIDE_INT value)
+build_replicated_const (tree type, unsigned int width, HOST_WIDE_INT value)
{
- int width = tree_to_uhwi (TYPE_SIZE (inner_type));
int n = (TYPE_PRECISION (type) + HOST_BITS_PER_WIDE_INT - 1)
/ HOST_BITS_PER_WIDE_INT;
unsigned HOST_WIDE_INT low, mask;
@@ -214,13 +214,14 @@ do_plus_minus (gimple_stmt_iterator *gsi, tree word_type, tree a, tree b,
tree bitpos ATTRIBUTE_UNUSED, tree bitsize ATTRIBUTE_UNUSED,
enum tree_code code, tree type ATTRIBUTE_UNUSED)
{
+ unsigned int width = vector_element_bits (TREE_TYPE (a));
tree inner_type = TREE_TYPE (TREE_TYPE (a));
unsigned HOST_WIDE_INT max;
tree low_bits, high_bits, a_low, b_low, result_low, signs;
max = GET_MODE_MASK (TYPE_MODE (inner_type));
- low_bits = build_replicated_const (word_type, inner_type, max >> 1);
- high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
+ low_bits = build_replicated_const (word_type, width, max >> 1);
+ high_bits = build_replicated_const (word_type, width, max & ~(max >> 1));
a = tree_vec_extract (gsi, word_type, a, bitsize, bitpos);
b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
@@ -247,13 +248,14 @@ do_negate (gimple_stmt_iterator *gsi, tree word_type, tree b,
enum tree_code code ATTRIBUTE_UNUSED,
tree type ATTRIBUTE_UNUSED)
{
+ unsigned int width = vector_element_bits (TREE_TYPE (b));
tree inner_type = TREE_TYPE (TREE_TYPE (b));
HOST_WIDE_INT max;
tree low_bits, high_bits, b_low, result_low, signs;
max = GET_MODE_MASK (TYPE_MODE (inner_type));
- low_bits = build_replicated_const (word_type, inner_type, max >> 1);
- high_bits = build_replicated_const (word_type, inner_type, max & ~(max >> 1));
+ low_bits = build_replicated_const (word_type, width, max >> 1);
+ high_bits = build_replicated_const (word_type, width, max & ~(max >> 1));
b = tree_vec_extract (gsi, word_type, b, bitsize, bitpos);
@@ -276,8 +278,7 @@ expand_vector_piecewise (gimple_stmt_iterator *gsi, elem_op_func f,
tree part_width = TYPE_SIZE (inner_type);
tree index = bitsize_int (0);
int nunits = nunits_for_known_piecewise_op (type);
- int delta = tree_to_uhwi (part_width)
- / tree_to_uhwi (TYPE_SIZE (TREE_TYPE (type)));
+ int delta = tree_to_uhwi (part_width) / vector_element_bits (type);
int i;
location_t loc = gimple_location (gsi_stmt (*gsi));
@@ -357,8 +358,7 @@ expand_vector_addition (gimple_stmt_iterator *gsi,
elem_op_func f, elem_op_func f_parallel,
tree type, tree a, tree b, enum tree_code code)
{
- int parts_per_word = UNITS_PER_WORD
- / tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
+ int parts_per_word = BITS_PER_WORD / vector_element_bits (type);
if (INTEGRAL_TYPE_P (TREE_TYPE (type))
&& parts_per_word >= 4
@@ -371,17 +371,55 @@ expand_vector_addition (gimple_stmt_iterator *gsi,
a, b, code);
}
+static bool
+expand_vector_condition (gimple_stmt_iterator *gsi, bitmap dce_ssa_names);
+
/* Try to expand vector comparison expression OP0 CODE OP1 by
querying optab if the following expression:
VEC_COND_EXPR< OP0 CODE OP1, {-1,...}, {0,...}>
can be expanded. */
static tree
expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
- tree op1, enum tree_code code)
+ tree op1, enum tree_code code,
+ bitmap dce_ssa_names)
{
+ tree lhs = gimple_assign_lhs (gsi_stmt (*gsi));
+ use_operand_p use_p;
+ imm_use_iterator iterator;
+ bool vec_cond_expr_only = true;
+
+ /* As seen in PR95830, we should not expand comparisons that are only
+ feeding a VEC_COND_EXPR statement. */
+ auto_vec<gimple *> uses;
+ FOR_EACH_IMM_USE_FAST (use_p, iterator, lhs)
+ uses.safe_push (USE_STMT (use_p));
+
+ for (unsigned i = 0; i < uses.length (); i ++)
+ {
+ gassign *use = dyn_cast<gassign *> (uses[i]);
+ if (use != NULL
+ && gimple_assign_rhs_code (use) == VEC_COND_EXPR
+ && gimple_assign_rhs1 (use) == lhs)
+ {
+ gimple_stmt_iterator it = gsi_for_stmt (use);
+ if (!expand_vector_condition (&it, dce_ssa_names))
+ {
+ vec_cond_expr_only = false;
+ break;
+ }
+ }
+ else
+ {
+ vec_cond_expr_only = false;
+ break;
+ }
+ }
+
+ if (!uses.is_empty () && vec_cond_expr_only)
+ return NULL_TREE;
+
tree t;
- if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code)
- && !expand_vec_cond_expr_p (type, TREE_TYPE (op0), code))
+ if (!expand_vec_cmp_expr_p (TREE_TYPE (op0), type, code))
{
if (VECTOR_BOOLEAN_TYPE_P (type)
&& SCALAR_INT_MODE_P (TYPE_MODE (type))
@@ -391,7 +429,7 @@ expand_vector_comparison (gimple_stmt_iterator *gsi, tree type, tree op0,
(TREE_TYPE (type)))))
{
tree inner_type = TREE_TYPE (TREE_TYPE (op0));
- tree part_width = TYPE_SIZE (inner_type);
+ tree part_width = vector_element_bits_tree (TREE_TYPE (op0));
tree index = bitsize_int (0);
int nunits = nunits_for_known_piecewise_op (TREE_TYPE (op0));
int prec = GET_MODE_PRECISION (SCALAR_TYPE_MODE (type));
@@ -695,12 +733,14 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
if (addend == NULL_TREE
&& expand_vec_cond_expr_p (type, type, LT_EXPR))
{
- tree zero, cst, cond, mask_type;
- gimple *stmt;
+ tree zero, cst, mask_type, mask;
+ gimple *stmt, *cond;
mask_type = truth_type_for (type);
zero = build_zero_cst (type);
- cond = build2 (LT_EXPR, mask_type, op0, zero);
+ mask = make_ssa_name (mask_type);
+ cond = gimple_build_assign (mask, LT_EXPR, op0, zero);
+ gsi_insert_before (gsi, cond, GSI_SAME_STMT);
tree_vector_builder vec (type, nunits, 1);
for (i = 0; i < nunits; i++)
vec.quick_push (build_int_cst (TREE_TYPE (type),
@@ -708,8 +748,8 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
<< shifts[i]) - 1));
cst = vec.build ();
addend = make_ssa_name (type);
- stmt = gimple_build_assign (addend, VEC_COND_EXPR, cond,
- cst, zero);
+ stmt
+ = gimple_build_assign (addend, VEC_COND_EXPR, mask, cst, zero);
gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
}
}
@@ -930,8 +970,9 @@ expand_vector_divmod (gimple_stmt_iterator *gsi, tree type, tree op0,
/* Expand a vector condition to scalars, by using many conditions
on the vector's elements. */
-static void
-expand_vector_condition (gimple_stmt_iterator *gsi)
+
+static bool
+expand_vector_condition (gimple_stmt_iterator *gsi, bitmap dce_ssa_names)
{
gassign *stmt = as_a <gassign *> (gsi_stmt (*gsi));
tree type = gimple_expr_type (stmt);
@@ -945,27 +986,36 @@ expand_vector_condition (gimple_stmt_iterator *gsi)
vec<constructor_elt, va_gc> *v;
tree constr;
tree inner_type = TREE_TYPE (type);
+ tree width = vector_element_bits_tree (type);
tree cond_type = TREE_TYPE (TREE_TYPE (a));
tree comp_inner_type = cond_type;
- tree width = TYPE_SIZE (inner_type);
tree index = bitsize_int (0);
tree comp_width = width;
tree comp_index = index;
- int i;
location_t loc = gimple_location (gsi_stmt (*gsi));
+ tree_code code = TREE_CODE (a);
+ gassign *assign = NULL;
- if (!is_gimple_val (a))
+ if (code == SSA_NAME)
{
- gcc_assert (COMPARISON_CLASS_P (a));
- a_is_comparison = true;
- a1 = TREE_OPERAND (a, 0);
- a2 = TREE_OPERAND (a, 1);
- comp_inner_type = TREE_TYPE (TREE_TYPE (a1));
- comp_width = TYPE_SIZE (comp_inner_type);
+ assign = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (a));
+ if (assign != NULL
+ && TREE_CODE_CLASS (gimple_assign_rhs_code (assign)) == tcc_comparison)
+ {
+ a_is_comparison = true;
+ a1 = gimple_assign_rhs1 (assign);
+ a2 = gimple_assign_rhs2 (assign);
+ code = gimple_assign_rhs_code (assign);
+ comp_inner_type = TREE_TYPE (TREE_TYPE (a1));
+ comp_width = vector_element_bits_tree (TREE_TYPE (a1));
+ }
}
- if (expand_vec_cond_expr_p (type, TREE_TYPE (a1), TREE_CODE (a)))
- return;
+ if (expand_vec_cond_expr_p (type, TREE_TYPE (a1), code))
+ {
+ gcc_assert (TREE_CODE (a) == SSA_NAME || TREE_CODE (a) == VECTOR_CST);
+ return true;
+ }
/* Handle vector boolean types with bitmasks. If there is a comparison
and we can expand the comparison into the vector boolean bitmask,
@@ -988,14 +1038,14 @@ expand_vector_condition (gimple_stmt_iterator *gsi)
: expand_vec_cmp_expr_p (TREE_TYPE (a1), type, TREE_CODE (a))))
{
if (a_is_comparison)
- a = gimplify_build2 (gsi, TREE_CODE (a), type, a1, a2);
+ a = gimplify_build2 (gsi, code, type, a1, a2);
a1 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a, b);
a2 = gimplify_build1 (gsi, BIT_NOT_EXPR, type, a);
a2 = gimplify_build2 (gsi, BIT_AND_EXPR, type, a2, c);
a = gimplify_build2 (gsi, BIT_IOR_EXPR, type, a1, a2);
gimple_assign_set_rhs_from_tree (gsi, a);
update_stmt (gsi_stmt (*gsi));
- return;
+ return true;
}
/* TODO: try and find a smaller vector type. */
@@ -1019,7 +1069,7 @@ expand_vector_condition (gimple_stmt_iterator *gsi)
int nunits = nunits_for_known_piecewise_op (type);
vec_alloc (v, nunits);
- for (i = 0; i < nunits; i++)
+ for (int i = 0; i < nunits; i++)
{
tree aa, result;
tree bb = tree_vec_extract (gsi, inner_type, b, width, index);
@@ -1030,7 +1080,7 @@ expand_vector_condition (gimple_stmt_iterator *gsi)
comp_width, comp_index);
tree aa2 = tree_vec_extract (gsi, comp_inner_type, a2,
comp_width, comp_index);
- aa = fold_build2 (TREE_CODE (a), cond_type, aa1, aa2);
+ aa = fold_build2 (code, cond_type, aa1, aa2);
}
else if (a_is_scalar_bitmask)
{
@@ -1055,11 +1105,18 @@ expand_vector_condition (gimple_stmt_iterator *gsi)
constr = build_constructor (type, v);
gimple_assign_set_rhs_from_tree (gsi, constr);
update_stmt (gsi_stmt (*gsi));
+
+ if (a_is_comparison)
+ bitmap_set_bit (dce_ssa_names,
+ SSA_NAME_VERSION (gimple_assign_lhs (assign)));
+
+ return false;
}
static tree
expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
- gassign *assign, enum tree_code code)
+ gassign *assign, enum tree_code code,
+ bitmap dce_ssa_names)
{
machine_mode compute_mode = TYPE_MODE (compute_type);
@@ -1113,7 +1170,8 @@ expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type
tree rhs1 = gimple_assign_rhs1 (assign);
tree rhs2 = gimple_assign_rhs2 (assign);
- return expand_vector_comparison (gsi, type, rhs1, rhs2, code);
+ return expand_vector_comparison (gsi, type, rhs1, rhs2, code,
+ dce_ssa_names);
}
case TRUNC_DIV_EXPR:
@@ -1334,7 +1392,7 @@ vector_element (gimple_stmt_iterator *gsi, tree vect, tree idx, tree *ptmpvec)
}
else
{
- tree size = TYPE_SIZE (vect_elt_type);
+ tree size = vector_element_bits_tree (vect_type);
tree pos = fold_build2 (MULT_EXPR, bitsizetype, bitsize_int (index),
size);
return fold_build3 (BIT_FIELD_REF, vect_elt_type, vect, size, pos);
@@ -1717,6 +1775,12 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
gimple *stmt = gsi_stmt (*gsi);
gimple *g;
tree lhs = gimple_call_lhs (stmt);
+ if (lhs == NULL_TREE)
+ {
+ g = gimple_build_nop ();
+ gsi_replace (gsi, g, false);
+ return;
+ }
tree arg = gimple_call_arg (stmt, 0);
tree ret_type = TREE_TYPE (lhs);
tree arg_type = TREE_TYPE (arg);
@@ -1727,19 +1791,17 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
optab optab1 = unknown_optab;
gcc_checking_assert (VECTOR_TYPE_P (ret_type) && VECTOR_TYPE_P (arg_type));
- gcc_checking_assert (tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (ret_type))));
- gcc_checking_assert (tree_fits_uhwi_p (TYPE_SIZE (TREE_TYPE (arg_type))));
if (INTEGRAL_TYPE_P (TREE_TYPE (ret_type))
&& SCALAR_FLOAT_TYPE_P (TREE_TYPE (arg_type)))
code = FIX_TRUNC_EXPR;
else if (INTEGRAL_TYPE_P (TREE_TYPE (arg_type))
&& SCALAR_FLOAT_TYPE_P (TREE_TYPE (ret_type)))
code = FLOAT_EXPR;
- if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (ret_type)))
- < tree_to_uhwi (TYPE_SIZE (TREE_TYPE (arg_type))))
+ unsigned int ret_elt_bits = vector_element_bits (ret_type);
+ unsigned int arg_elt_bits = vector_element_bits (arg_type);
+ if (ret_elt_bits < arg_elt_bits)
modifier = NARROW;
- else if (tree_to_uhwi (TYPE_SIZE (TREE_TYPE (ret_type)))
- > tree_to_uhwi (TYPE_SIZE (TREE_TYPE (arg_type))))
+ else if (ret_elt_bits > arg_elt_bits)
modifier = WIDEN;
if (modifier == NONE && (code == FIX_TRUNC_EXPR || code == FLOAT_EXPR))
@@ -1902,8 +1964,7 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
tree part_width = TYPE_SIZE (compute_type);
tree index = bitsize_int (0);
int nunits = nunits_for_known_piecewise_op (arg_type);
- int delta = tree_to_uhwi (part_width)
- / tree_to_uhwi (TYPE_SIZE (TREE_TYPE (arg_type)));
+ int delta = tree_to_uhwi (part_width) / arg_elt_bits;
int i;
location_t loc = gimple_location (gsi_stmt (*gsi));
@@ -1950,7 +2011,8 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
/* Process one statement. If we identify a vector operation, expand it. */
static void
-expand_vector_operations_1 (gimple_stmt_iterator *gsi)
+expand_vector_operations_1 (gimple_stmt_iterator *gsi,
+ bitmap dce_ssa_names)
{
tree lhs, rhs1, rhs2 = NULL, type, compute_type = NULL_TREE;
enum tree_code code;
@@ -1979,7 +2041,7 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
if (code == VEC_COND_EXPR)
{
- expand_vector_condition (gsi);
+ expand_vector_condition (gsi, dce_ssa_names);
return;
}
@@ -2200,7 +2262,8 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
if (compute_type == type)
return;
- new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code);
+ new_rhs = expand_vector_operation (gsi, type, compute_type, stmt, code,
+ dce_ssa_names);
/* Leave expression untouched for later expansion. */
if (new_rhs == NULL_TREE)
@@ -2227,11 +2290,13 @@ expand_vector_operations (void)
basic_block bb;
bool cfg_changed = false;
+ auto_bitmap dce_ssa_names;
+
FOR_EACH_BB_FN (bb, cfun)
{
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
- expand_vector_operations_1 (&gsi);
+ expand_vector_operations_1 (&gsi, dce_ssa_names);
/* ??? If we do not cleanup EH then we will ICE in
verification. But in reality we have created wrong-code
as we did not properly transition EH info and edges to
@@ -2242,6 +2307,8 @@ expand_vector_operations (void)
}
}
+ simple_dce_from_worklist (dce_ssa_names);
+
return cfg_changed ? TODO_cleanup_cfg : 0;
}