summaryrefslogtreecommitdiff
path: root/gcc/tree-vect-patterns.c
diff options
context:
space:
mode:
authorYuliang Wang <yuliang.wang@arm.com>2019-09-30 16:55:45 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2019-09-30 16:55:45 +0000
commitc0c2f013906a695b8a02226f119649a370d9e083 (patch)
tree6743c5d13bf23522c114e0de5e187c1dade8a1c4 /gcc/tree-vect-patterns.c
parentdcdd0f055731a8c960a15e5de8715d041d9a7876 (diff)
[AArch64][SVE] Utilize ASRD instruction for division and remainder
2019-09-30 Yuliang Wang <yuliang.wang@arm.com> gcc/ * config/aarch64/aarch64-sve.md (sdiv_pow2<mode>3): New pattern for ASRD. * config/aarch64/iterators.md (UNSPEC_ASRD): New unspec. * internal-fn.def (IFN_DIV_POW2): New internal function. * optabs.def (sdiv_pow2_optab): New optab. * tree-vect-patterns.c (vect_recog_divmod_pattern): Modify pattern to support new operation. * doc/md.texi (sdiv_pow2$var{m3}): Documentation for the above. * doc/sourcebuild.texi (vect_sdiv_pow2_si): Document new target selector. gcc/testsuite/ * gcc.dg/vect/vect-sdiv-pow2-1.c: New test. * gcc.target/aarch64/sve/asrdiv_1.c: As above. * lib/target-supports.exp (check_effective_target_vect_sdiv_pow2_si): Return true for AArch64 with SVE. From-SVN: r276343
Diffstat (limited to 'gcc/tree-vect-patterns.c')
-rw-r--r--gcc/tree-vect-patterns.c32
1 files changed, 31 insertions, 1 deletions
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index baa9a4cb8fa..4dfebbefce6 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -2927,6 +2927,37 @@ vect_recog_divmod_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
/* Pattern detected. */
vect_pattern_detected ("vect_recog_divmod_pattern", last_stmt);
+ *type_out = vectype;
+
+ /* Check if the target supports this internal function. */
+ internal_fn ifn = IFN_DIV_POW2;
+ if (direct_internal_fn_supported_p (ifn, vectype, OPTIMIZE_FOR_SPEED))
+ {
+ tree shift = build_int_cst (itype, tree_log2 (oprnd1));
+
+ tree var_div = vect_recog_temp_ssa_var (itype, NULL);
+ gimple *div_stmt = gimple_build_call_internal (ifn, 2, oprnd0, shift);
+ gimple_call_set_lhs (div_stmt, var_div);
+
+ if (rhs_code == TRUNC_MOD_EXPR)
+ {
+ append_pattern_def_seq (stmt_vinfo, div_stmt);
+ def_stmt
+ = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
+ LSHIFT_EXPR, var_div, shift);
+ append_pattern_def_seq (stmt_vinfo, def_stmt);
+ pattern_stmt
+ = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL),
+ MINUS_EXPR, oprnd0,
+ gimple_assign_lhs (def_stmt));
+ }
+ else
+ pattern_stmt = div_stmt;
+ gimple_set_location (pattern_stmt, gimple_location (last_stmt));
+
+ return pattern_stmt;
+ }
+
cond = build2 (LT_EXPR, boolean_type_node, oprnd0,
build_int_cst (itype, 0));
if (rhs_code == TRUNC_DIV_EXPR
@@ -3003,7 +3034,6 @@ vect_recog_divmod_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
signmask);
}
- *type_out = vectype;
return pattern_stmt;
}