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?"?

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?

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

Reply via email to