On Mon, 15 Jun 2026, [email protected] wrote:
> From: Kyrylo Tkachov <[email protected]>
>
> vect_slp_analyze_data_ref_dependence conservatively reports a dependence
> whenever the classical (affine) data-dependence test returns chrec_dont_know,
> e.g. when one of the accesses has a non-affine or runtime array subscript.
> In the BB SLP region check this is overly pessimistic: the unanalyzable
> subscript says nothing about whether the two references can actually alias,
> and the alias oracle can frequently still prove they cannot (distinct restrict
> parameters, distinct non-escaping objects, TBAA-incompatible types, and so
> on).
> When that happens a perfectly good SLP group can be torn down.
>
> Consult the alias oracle (refs_may_alias_p) before assuming a dependence on
> chrec_dont_know: if the two references cannot alias they are independent
> regardless of the unanalyzable subscript, and BB SLP may proceed.
>
> On the new gcc.dg/vect/bb-slp-dep-oracle.c the 8-lane reciprocal group is torn
> down and emitted scalar without the patch
>
> fmov d23, 1.0e+0
> fdiv d8, d23, d8
> fdiv d9, d23, d9
> fdiv d10, d23, d10
> fdiv d11, d23, d11
> fdiv d12, d23, d12
> fdiv d13, d23, d13
> fdiv d14, d23, d14
> fdiv d15, d23, d15
>
> and vectorizes with it:
>
> fmov v27.2d, 1.0e+0
> fdiv v28.2d, v27.2d, v28.2d
> fdiv v29.2d, v27.2d, v29.2d
> fdiv v30.2d, v27.2d, v30.2d
> fdiv v31.2d, v27.2d, v31.2d
>
> Bootstrapped and tested on aarch64-none-linux-gnu.
> Ok for trunk?
Hmm, but we already do
/* If we couldn't record a (single) data reference for this
stmt we have to resort to the alias oracle. */
stmt_vec_info stmt_info = vinfo->lookup_stmt (stmt);
data_reference *dr_b = STMT_VINFO_DATA_REF (stmt_info);
if (!dr_b)
{
/* We are moving a store - this means
we cannot use TBAA for disambiguation. */
if (!ref_initialized_p)
ao_ref_init (&ref, DR_REF (dr_a));
if (stmt_may_clobber_ref_p_1 (stmt, &ref, false)
|| ref_maybe_used_by_stmt_p (stmt, &ref, false))
return false;
continue;
on one path, so maybe refactor this so this is also done when
chrec_dont_know
(have vect_slp_analyze_data_ref_dependence return
chrec_known instead of false and then DDR_ARE_DEPENDENT so
we can distinguish the three cases)?
Also because a generic refs_may_alias_p is too strong for
the store vs. store case, so I'd like to see the fallback
duplicated to all three places.
> Thanks,
> Kyrill
>
> Signed-off-by: Kyrylo Tkachov <[email protected]>
>
> gcc/ChangeLog:
>
> * tree-vect-data-refs.cc (vect_slp_analyze_data_ref_dependence): On an
> unknown (chrec_dont_know) dependence, consult the alias oracle on the
> references and treat them as independent when they provably cannot
> alias.
>
> gcc/testsuite/ChangeLog:
>
> * gcc.dg/vect/bb-slp-dep-oracle.c: New test.
> ---
> gcc/testsuite/gcc.dg/vect/bb-slp-dep-oracle.c | 40 +++++++++++++++++++
> gcc/tree-vect-data-refs.cc | 8 ++++
> 2 files changed, 48 insertions(+)
> create mode 100644 gcc/testsuite/gcc.dg/vect/bb-slp-dep-oracle.c
>
> diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-dep-oracle.c
> b/gcc/testsuite/gcc.dg/vect/bb-slp-dep-oracle.c
> new file mode 100644
> index 00000000000..b2551ef644c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.dg/vect/bb-slp-dep-oracle.c
> @@ -0,0 +1,40 @@
> +/* BB SLP must not abandon a vectorizable group when the classical (affine)
> + data-dependence test cannot analyze a runtime array subscript but the
> alias
> + oracle can still prove the two references do not alias.
> +
> + The per-lane reciprocals are discovered as an SLP group, then the group is
> + torn down by vect_slp_analyze_data_ref_dependence reporting "can't
> determine
> + dependence" between the restrict output store and a runtime-indexed input
> + load, even though the distinct restrict objects provably do not alias. */
> +
> +/* { dg-do compile } */
> +/* { dg-require-effective-target vect_double } */
> +/* { dg-additional-options "-O3 -ffast-math -fno-trapping-math" } */
> +
> +struct VA { double data[8]; };
> +struct Tensor { struct VA comp[4]; };
> +
> +/* Opaque: the returned index is a runtime value the affine subscript test
> + cannot analyze. */
> +unsigned __attribute__((noipa)) pick (unsigned k) { return k & 3; }
> +
> +void f (const struct Tensor *in, double *__restrict out,
> + unsigned nq, unsigned base)
> +{
> + for (unsigned q = 0; q < nq; q++)
> + {
> + const struct VA *rho = &in[q].comp[0]; /* divisor: contiguous
> .data[i] */
> + double inv[8];
> + for (unsigned i = 0; i < 8; i++)
> + inv[i] = 1.0 / rho->data[i]; /* reciprocal group, reused
> below */
> + for (unsigned d = 0; d < 3; d++)
> + {
> + const struct VA *mom = &in[q].comp[pick (base + d)]; /*
> runtime-indexed numerator */
> + for (unsigned i = 0; i < 8; i++)
> + out[(q * 3 + d) * 8 + i] = mom->data[i] * inv[i];
> + }
> + }
> +}
> +
> +/* The reciprocal group must survive the dependence check and vectorize. */
> +/* { dg-final { scan-tree-dump "basic block part vectorized" "slp1" } } */
> diff --git a/gcc/tree-vect-data-refs.cc b/gcc/tree-vect-data-refs.cc
> index 0e57e1068d6..07d0d860d44 100644
> --- a/gcc/tree-vect-data-refs.cc
> +++ b/gcc/tree-vect-data-refs.cc
> @@ -1011,6 +1011,14 @@ vect_slp_analyze_data_ref_dependence (vec_info *vinfo,
> /* Unknown data dependence. */
> if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
> {
> + /* The classical (affine) dependence test gave up, e.g. a non-affine
> + or runtime array subscript. Before conservatively assuming a
> + dependence (which prevents SLP), consult the alias oracle on the
> + actual references: if they provably cannot alias (e.g. based on
> + distinct restrict / non-escaping objects) they are independent
> + regardless of the unanalyzable subscript. */
> + if (!refs_may_alias_p (DR_REF (dra), DR_REF (drb)))
> + return false;
> if (dump_enabled_p ())
> dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
> "can't determine dependence between %T and %T\n",
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)