aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vect-patterns.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-vect-patterns.cc')
-rw-r--r--gcc/tree-vect-patterns.cc73
1 files changed, 56 insertions, 17 deletions
diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
index 4f0a7ea..0f6d6b7 100644
--- a/gcc/tree-vect-patterns.cc
+++ b/gcc/tree-vect-patterns.cc
@@ -1095,9 +1095,10 @@ vect_recog_cond_expr_convert_pattern (vec_info *vinfo,
stmt_vec_info stmt_vinfo, tree *type_out)
{
gassign *last_stmt = dyn_cast <gassign *> (stmt_vinfo->stmt);
- tree lhs, match[4], temp, type, new_lhs, op2;
+ tree lhs, match[4], temp, type, new_lhs, op2, op1;
gimple *cond_stmt;
gimple *pattern_stmt;
+ enum tree_code code = NOP_EXPR;
if (!last_stmt)
return NULL;
@@ -1109,25 +1110,51 @@ vect_recog_cond_expr_convert_pattern (vec_info *vinfo,
if (!gimple_cond_expr_convert_p (lhs, &match[0], NULL))
return NULL;
- vect_pattern_detected ("vect_recog_cond_expr_convert_pattern", last_stmt);
+ if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (lhs)))
+ code = INTEGRAL_TYPE_P (TREE_TYPE (match[1])) ? FLOAT_EXPR : CONVERT_EXPR;
+ else if (SCALAR_FLOAT_TYPE_P (TREE_TYPE (match[1])))
+ code = FIX_TRUNC_EXPR;
+ op1 = match[1];
op2 = match[2];
- type = TREE_TYPE (match[1]);
- if (TYPE_SIGN (type) != TYPE_SIGN (TREE_TYPE (match[2])))
+ type = TREE_TYPE (op1);
+ /* When op1/op2 is REAL_CST, the conversion must be CONVERT_EXPR from
+ SCALAR_FLOAT_TYPE_P which is restricted in gimple_cond_expr_convert_p.
+ Otherwise, the conversion could be FLOAT_EXPR, FIX_TRUNC_EXPR
+ or CONVERT_EXPR. */
+ if (TREE_CODE (op1) == REAL_CST)
+ {
+ op1 = const_unop (CONVERT_EXPR, TREE_TYPE (op2), op1);
+ type = TREE_TYPE (op2);
+ if (op1 == NULL_TREE)
+ return NULL;
+ }
+ else if (TREE_CODE (op2) == REAL_CST)
{
- op2 = vect_recog_temp_ssa_var (type, NULL);
- gimple* nop_stmt = gimple_build_assign (op2, NOP_EXPR, match[2]);
- append_pattern_def_seq (vinfo, stmt_vinfo, nop_stmt,
- get_vectype_for_scalar_type (vinfo, type));
+ op2 = const_unop (FLOAT_EXPR, TREE_TYPE (op1), op2);
+ if (op2 == NULL_TREE)
+ return NULL;
}
+ else if (code == NOP_EXPR)
+ {
+ if (TYPE_SIGN (type) != TYPE_SIGN (TREE_TYPE (match[2])))
+ {
+ op2 = vect_recog_temp_ssa_var (type, NULL);
+ gimple* nop_stmt = gimple_build_assign (op2, NOP_EXPR, match[2]);
+ append_pattern_def_seq (vinfo, stmt_vinfo, nop_stmt,
+ get_vectype_for_scalar_type (vinfo, type));
+ }
+ }
+
+ vect_pattern_detected ("vect_recog_cond_expr_convert_pattern", last_stmt);
temp = vect_recog_temp_ssa_var (type, NULL);
cond_stmt = gimple_build_assign (temp, build3 (COND_EXPR, type, match[3],
- match[1], op2));
+ op1, op2));
append_pattern_def_seq (vinfo, stmt_vinfo, cond_stmt,
get_vectype_for_scalar_type (vinfo, type));
new_lhs = vect_recog_temp_ssa_var (TREE_TYPE (lhs), NULL);
- pattern_stmt = gimple_build_assign (new_lhs, NOP_EXPR, temp);
+ pattern_stmt = gimple_build_assign (new_lhs, code, temp);
*type_out = STMT_VINFO_VECTYPE (stmt_vinfo);
if (dump_enabled_p ())
@@ -6544,10 +6571,22 @@ vect_determine_precisions_from_users (stmt_vec_info stmt_info, gassign *stmt)
case RSHIFT_EXPR:
{
tree shift = gimple_assign_rhs2 (stmt);
- if (TREE_CODE (shift) != INTEGER_CST
- || !wi::ltu_p (wi::to_widest (shift), precision))
+ unsigned int min_const_shift, max_const_shift;
+ wide_int min_shift, max_shift;
+ if (TREE_CODE (shift) == SSA_NAME
+ && vect_get_range_info (shift, &min_shift, &max_shift)
+ && wi::ge_p (min_shift, 0, TYPE_SIGN (TREE_TYPE (shift)))
+ && wi::lt_p (max_shift, TYPE_PRECISION (type),
+ TYPE_SIGN (TREE_TYPE (shift))))
+ {
+ min_const_shift = min_shift.to_uhwi ();
+ max_const_shift = max_shift.to_uhwi ();
+ }
+ else if (TREE_CODE (shift) == INTEGER_CST
+ && wi::ltu_p (wi::to_widest (shift), precision))
+ min_const_shift = max_const_shift = TREE_INT_CST_LOW (shift);
+ else
return;
- unsigned int const_shift = TREE_INT_CST_LOW (shift);
if (code == LSHIFT_EXPR)
{
/* Avoid creating an undefined shift.
@@ -6559,16 +6598,16 @@ vect_determine_precisions_from_users (stmt_vec_info stmt_info, gassign *stmt)
of vectorization. This sort of thing should really be
handled before vectorization. */
operation_precision = MAX (stmt_info->min_output_precision,
- const_shift + 1);
+ max_const_shift + 1);
/* We need CONST_SHIFT fewer bits of the input. */
- min_input_precision = (MAX (operation_precision, const_shift)
- - const_shift);
+ min_input_precision = (MAX (operation_precision, max_const_shift)
+ - min_const_shift);
}
else
{
/* We need CONST_SHIFT extra bits to do the operation. */
operation_precision = (stmt_info->min_output_precision
- + const_shift);
+ + max_const_shift);
min_input_precision = operation_precision;
}
break;