aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vect-patterns.c
diff options
context:
space:
mode:
authorPrathamesh Kulkarni <prathamesh.kulkarni@linaro.org>2019-12-09 09:59:42 +0000
committerPrathamesh Kulkarni <prathamesh3492@gcc.gnu.org>2019-12-09 09:59:42 +0000
commit8e03b21e84e4b6a3c806bb48bb5eceac1f7ed273 (patch)
treeea260ab621a5fe224c76b87e0f643c1e89502449 /gcc/tree-vect-patterns.c
parent1d214c3f83521bcf0793f6460ace2bee89f670b8 (diff)
downloadgcc-8e03b21e84e4b6a3c806bb48bb5eceac1f7ed273.zip
gcc-8e03b21e84e4b6a3c806bb48bb5eceac1f7ed273.tar.gz
gcc-8e03b21e84e4b6a3c806bb48bb5eceac1f7ed273.tar.bz2
re PR tree-optimization/89007 ([SVE] Implement generic vector average expansion)
2019-12-09 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org> PR tree-optimization/89007 * tree-vect-patterns.c (vect_recog_average_pattern): If there is no target support available, generate code to distribute rshift over plus and add a carry. testsuite/ * gcc.target/aarch64/sve/pr89007-1.c: New test. * gcc.target/aarch64/sve/pr89007-2.c: Likewise. From-SVN: r279112
Diffstat (limited to 'gcc/tree-vect-patterns.c')
-rw-r--r--gcc/tree-vect-patterns.c66
1 files changed, 61 insertions, 5 deletions
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index 2e02128..c9ad9e0 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -1928,7 +1928,10 @@ vect_recog_mulhs_pattern (stmt_vec_info last_stmt_info, tree *type_out)
TYPE avg = (TYPE) avg';
where NTYPE is no wider than half of TYPE. Since only the bottom half
- of avg is used, all or part of the cast of avg' should become redundant. */
+ of avg is used, all or part of the cast of avg' should become redundant.
+
+ If there is no target support available, generate code to distribute rshift
+ over plus and add a carry. */
static gimple *
vect_recog_average_pattern (stmt_vec_info last_stmt_info, tree *type_out)
@@ -2032,9 +2035,20 @@ vect_recog_average_pattern (stmt_vec_info last_stmt_info, tree *type_out)
/* Check for target support. */
tree new_vectype = get_vectype_for_scalar_type (vinfo, new_type);
- if (!new_vectype
- || !direct_internal_fn_supported_p (ifn, new_vectype,
- OPTIMIZE_FOR_SPEED))
+ if (!new_vectype)
+ return NULL;
+
+ bool fallback_p = false;
+
+ if (direct_internal_fn_supported_p (ifn, new_vectype, OPTIMIZE_FOR_SPEED))
+ ;
+ else if (TYPE_UNSIGNED (new_type)
+ && optab_for_tree_code (RSHIFT_EXPR, new_vectype, optab_scalar)
+ && optab_for_tree_code (PLUS_EXPR, new_vectype, optab_default)
+ && optab_for_tree_code (BIT_IOR_EXPR, new_vectype, optab_default)
+ && optab_for_tree_code (BIT_AND_EXPR, new_vectype, optab_default))
+ fallback_p = true;
+ else
return NULL;
/* The IR requires a valid vector type for the cast result, even though
@@ -2043,11 +2057,53 @@ vect_recog_average_pattern (stmt_vec_info last_stmt_info, tree *type_out)
if (!*type_out)
return NULL;
- /* Generate the IFN_AVG* call. */
tree new_var = vect_recog_temp_ssa_var (new_type, NULL);
tree new_ops[2];
vect_convert_inputs (last_stmt_info, 2, new_ops, new_type,
unprom, new_vectype);
+
+ if (fallback_p)
+ {
+ /* As a fallback, generate code for following sequence:
+
+ shifted_op0 = new_ops[0] >> 1;
+ shifted_op1 = new_ops[1] >> 1;
+ sum_of_shifted = shifted_op0 + shifted_op1;
+ unmasked_carry = new_ops[0] and/or new_ops[1];
+ carry = unmasked_carry & 1;
+ new_var = sum_of_shifted + carry;
+ */
+
+ tree one_cst = build_one_cst (new_type);
+ gassign *g;
+
+ tree shifted_op0 = vect_recog_temp_ssa_var (new_type, NULL);
+ g = gimple_build_assign (shifted_op0, RSHIFT_EXPR, new_ops[0], one_cst);
+ append_pattern_def_seq (last_stmt_info, g, new_vectype);
+
+ tree shifted_op1 = vect_recog_temp_ssa_var (new_type, NULL);
+ g = gimple_build_assign (shifted_op1, RSHIFT_EXPR, new_ops[1], one_cst);
+ append_pattern_def_seq (last_stmt_info, g, new_vectype);
+
+ tree sum_of_shifted = vect_recog_temp_ssa_var (new_type, NULL);
+ g = gimple_build_assign (sum_of_shifted, PLUS_EXPR,
+ shifted_op0, shifted_op1);
+ append_pattern_def_seq (last_stmt_info, g, new_vectype);
+
+ tree unmasked_carry = vect_recog_temp_ssa_var (new_type, NULL);
+ tree_code c = (ifn == IFN_AVG_CEIL) ? BIT_IOR_EXPR : BIT_AND_EXPR;
+ g = gimple_build_assign (unmasked_carry, c, new_ops[0], new_ops[1]);
+ append_pattern_def_seq (last_stmt_info, g, new_vectype);
+
+ tree carry = vect_recog_temp_ssa_var (new_type, NULL);
+ g = gimple_build_assign (carry, BIT_AND_EXPR, unmasked_carry, one_cst);
+ append_pattern_def_seq (last_stmt_info, g, new_vectype);
+
+ g = gimple_build_assign (new_var, PLUS_EXPR, sum_of_shifted, carry);
+ return vect_convert_output (last_stmt_info, type, g, new_vectype);
+ }
+
+ /* Generate the IFN_AVG* call. */
gcall *average_stmt = gimple_build_call_internal (ifn, 2, new_ops[0],
new_ops[1]);
gimple_call_set_lhs (average_stmt, new_var);