On Tue, 13 Oct 2026, Richard Sandiford wrote:

> Rohith Kapelli <[email protected]> writes:
> > Hi Richard,
> >
> > Thanks for the review.  I looked into where the missed dependences
> > come from, and it is wider than the structure case.
> >
> > 1. It also happens with plain arrays and the same base.  PR120254 is
> >    wrong at -O3 on trunk (92a7b1230e6): for A[k+1][i][i] against
> >    A[k][i][i] in an (i, j, k) nest the only distance vector is (0 0 1),
> >    but (0 1 -1) is a real distance, and interchange swaps j and k.
> >
> > 2. The cause is in build_classic_dist_vector.  Call a loop of the nest
> >    free when none of the compared access functions evolves in it.
> >    A free loop gets component 0 in every distance vector.  Only when
> >    it lies outside every constrained loop are vectors added with 1 in
> >    its component (add_outer_distances, add_other_self_distances,
> >    add_distance_for_zero_overlaps).  So the vectors cover all
> >    distances only when there is no free loop, or exactly one that
> >    lies outside all the constrained loops.
> >
> > 3. In the structure case, full_seq = struct_seq drops the base
> >    subscript, so the loop in which the objects move becomes a free
> >    loop.  That is PR115869 and PR105771.
> >
> > 4. Unroll-and-jam already guards against this using DR_ACCESS_FNS, but
> >    the structure path defeats that check because it looks at the
> >    reference's access functions rather than the compared ones.  Loop
> >    distribution has its own guard.  Interchange has none.  I found no
> >    vectorizer miscompile.
> >
> > 5. On x[k].v vs x[k + d].v: giving it the same dependences as x[k] vs
> >    x[k + d] would be right, but not enough on its own, since as in 1
> >    plain arrays miss distances too in deeper nests.  For x[k].v[j],
> >    j invariant or in an outer loop behaves like x[k].v; with j in an
> >    inner loop the vectors are conservative in a two-deep nest, but a
> >    three-deep nest with the objects moving in the middle loop
> >    miscompiles at -O3 -fno-loop-unroll-and-jam.
> >
> > I have tried a fix in both places:
> >
> >  a) In the consumers: unroll-and-jam's existing guard uses the
> >     compared access functions, and interchange refuses only a loop
> >     pair whose swap a missing distance could reverse.  57 changed
> >     lines.
> >
> >  b) In tree-data-ref.cc: give up on a relation whose vectors miss a
> >     free loop.  This also has to release the distance vectors
> >     (unroll-and-jam reads them even on chrec_dont_know) and count a
> >     loop as free only if it contains both references.  61 changed
> >     lines.
> 
> When doing the original review, I was thinking along the lines of (b).
> But it looked like it might be cumbersome to calculate.  Is there an
> off-the-self way of asking "does this value vary only in subloops and
> superloops?"?

no_evolution_in_loop_p can possibly be used?

> So I was hoping there might be a simpler way.  However, the same-base
> examples above suggest that (b) really is the right thing after all.
> 
> Isn't it a bug that unroll-and-jam's adjust_unroll_factor doesn't check
> whether DDR_ARE_DEPENDENT (ddr) is chrec_dont_know?  The dump functions
> in tree-data-ref.cc suggest that the distance vectors shouldn't be read
> in that case.  And there is an existing early-out in
> add_other_self_distances:
> 
>             if (DDR_NUM_SUBSCRIPTS (ddr) != 1)
>               {
>                 DDR_ARE_DEPENDENT (ddr) = chrec_dont_know;
>                 return;
>               }
> 
> where (AIUI) the code is explicitly dropping a case that would matter
> to consumers of the distance vectors.
> 
> > Both fix every miscompile of this kind I have found, including
> > PR120254 and the PR109184 testcase.  Compiling the C, C++ and Fortran
> > testsuites at -O3, and again with -fprefetch-loop-arrays, (a) changes
> > no vectorizer, distribution or prefetch decision.  (b) changes no
> > issued prefetch either, but changes prefetch reuse-distance estimates
> > in 23 files and refuses more valid transforms.  Either way, a few
> > interchanges that are only valid because the update commutes are
> > refused.
> 
> Do you have examples of the refused prefetch and interchange transforms?
> Are they being refused for the "right" reasons, or are we being too
> conservative?

IIRC Michael Matz analyzed a latent data dependence issue that boils
down to the bad representation of distance/direction vectors which
do not encode the do-not-know (either direction) case leading to
downstream wrong answers exactly in the case where there are
loops without an evolution.  Maybe he remembers and also the
associated PR.

Richard.

> Thanks,
> Richard
> 
> > Testing so far, on aarch64-linux: both were built and run through the
> > same targeted tests (the new tests, vect.exp, the interchange,
> > unroll-and-jam and prefetch tests) and the testsuite comparison above.
> > (a) has also passed a three-stage bootstrap and full regression
> > testing against an unpatched baseline; (b) has not had a bootstrap or
> > a full regression run.
> >
> > The v1 patch does not fix PR120254 and should be considered
> > superseded.
> >
> > Which direction would you prefer?  I will post (a) once the release
> > branch testing finishes, unless you would rather have (b), in which
> > case I will give it the same full testing first.
> >
> > Thanks,
> > Rohith
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri; (HRB 36809, AG Nuernberg)

Reply via email to