diff options
author | Richard Sandiford <richard.sandiford@arm.com> | 2021-11-30 09:52:29 +0000 |
---|---|---|
committer | Richard Sandiford <richard.sandiford@arm.com> | 2021-11-30 09:52:29 +0000 |
commit | 10833849b55401a52f2334eb032a70beb688e9fc (patch) | |
tree | a2556da822f071f9f927e85f9f4ecb668bac4d07 /gcc/tree-vect-data-refs.c | |
parent | 6f798618c070e2ca505e39c3fcc0c3ca478ac81b (diff) | |
download | gcc-10833849b55401a52f2334eb032a70beb688e9fc.zip gcc-10833849b55401a52f2334eb032a70beb688e9fc.tar.gz gcc-10833849b55401a52f2334eb032a70beb688e9fc.tar.bz2 |
vect: Support gather loads with SLP
This patch adds SLP support for IFN_GATHER_LOAD. Like the SLP
support for IFN_MASK_LOAD, it works by treating only some of the
arguments as child nodes. Unlike IFN_MASK_LOAD, it requires the
other arguments (base, scale, and extension type) to be the same
for all calls in the group. It does not require/expect the loads
to be in a group (which probably wouldn't make sense for gathers).
I was worried about the possible alias effect of moving gathers
around to be part of the same SLP group. The patch therefore
makes vect_analyze_data_ref_dependence treat gathers and scatters
as a top-level concern, punting if the accesses aren't completely
independent and if the user hasn't told us that a particular
VF is safe. I think in practice we already punted in the same
circumstances; the idea is just to make it more explicit.
gcc/
PR tree-optimization/102467
* doc/sourcebuild.texi (vect_gather_load_ifn): Document.
* tree-vect-data-refs.c (vect_analyze_data_ref_dependence):
Commonize safelen handling. Punt for anything involving
gathers and scatters unless safelen says otherwise.
* tree-vect-slp.c (arg1_map): New variable.
(vect_get_operand_map): Handle IFN_GATHER_LOAD.
(vect_build_slp_tree_1): Likewise.
(vect_build_slp_tree_2): Likewise.
(compatible_calls_p): If vect_get_operand_map returns nonnull,
check that any skipped arguments are equal.
(vect_slp_analyze_node_operations_1): Tighten reduction check.
* tree-vect-stmts.c (check_load_store_for_partial_vectors): Take
an ncopies argument.
(vect_get_gather_scatter_ops): Take slp_node and ncopies arguments.
Handle SLP nodes.
(vectorizable_store, vectorizable_load): Adjust accordingly.
gcc/testsuite/
* lib/target-supports.exp
(check_effective_target_vect_gather_load_ifn): New target test.
* gcc.dg/vect/vect-gather-1.c: New test.
* gcc.dg/vect/vect-gather-2.c: Likewise.
* gcc.target/aarch64/sve/gather_load_11.c: Likewise.
Diffstat (limited to 'gcc/tree-vect-data-refs.c')
-rw-r--r-- | gcc/tree-vect-data-refs.c | 64 |
1 files changed, 30 insertions, 34 deletions
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c index 888ad72..12a82cd 100644 --- a/gcc/tree-vect-data-refs.c +++ b/gcc/tree-vect-data-refs.c @@ -359,6 +359,20 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, lambda_vector dist_v; unsigned int loop_depth; + /* If user asserted safelen consecutive iterations can be + executed concurrently, assume independence. */ + auto apply_safelen = [&]() + { + if (loop->safelen >= 2) + { + if ((unsigned int) loop->safelen < *max_vf) + *max_vf = loop->safelen; + LOOP_VINFO_NO_DATA_DEPENDENCIES (loop_vinfo) = false; + return true; + } + return false; + }; + /* In loop analysis all data references should be vectorizable. */ if (!STMT_VINFO_VECTORIZABLE (stmtinfo_a) || !STMT_VINFO_VECTORIZABLE (stmtinfo_b)) @@ -393,26 +407,23 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, get_alias_set (DR_REF (drb)))) return opt_result::success (); + if (STMT_VINFO_GATHER_SCATTER_P (stmtinfo_a) + || STMT_VINFO_GATHER_SCATTER_P (stmtinfo_b)) + { + if (apply_safelen ()) + return opt_result::success (); + + return opt_result::failure_at + (stmtinfo_a->stmt, + "possible alias involving gather/scatter between %T and %T\n", + DR_REF (dra), DR_REF (drb)); + } + /* Unknown data dependence. */ if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know) { - /* If user asserted safelen consecutive iterations can be - executed concurrently, assume independence. */ - if (loop->safelen >= 2) - { - if ((unsigned int) loop->safelen < *max_vf) - *max_vf = loop->safelen; - LOOP_VINFO_NO_DATA_DEPENDENCIES (loop_vinfo) = false; - return opt_result::success (); - } - - if (STMT_VINFO_GATHER_SCATTER_P (stmtinfo_a) - || STMT_VINFO_GATHER_SCATTER_P (stmtinfo_b)) - return opt_result::failure_at - (stmtinfo_a->stmt, - "versioning for alias not supported for: " - "can't determine dependence between %T and %T\n", - DR_REF (dra), DR_REF (drb)); + if (apply_safelen ()) + return opt_result::success (); if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, stmtinfo_a->stmt, @@ -427,23 +438,8 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, /* Known data dependence. */ if (DDR_NUM_DIST_VECTS (ddr) == 0) { - /* If user asserted safelen consecutive iterations can be - executed concurrently, assume independence. */ - if (loop->safelen >= 2) - { - if ((unsigned int) loop->safelen < *max_vf) - *max_vf = loop->safelen; - LOOP_VINFO_NO_DATA_DEPENDENCIES (loop_vinfo) = false; - return opt_result::success (); - } - - if (STMT_VINFO_GATHER_SCATTER_P (stmtinfo_a) - || STMT_VINFO_GATHER_SCATTER_P (stmtinfo_b)) - return opt_result::failure_at - (stmtinfo_a->stmt, - "versioning for alias not supported for: " - "bad dist vector for %T and %T\n", - DR_REF (dra), DR_REF (drb)); + if (apply_safelen ()) + return opt_result::success (); if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, stmtinfo_a->stmt, |