Optimise WAR and WAW alias checks
authorRichard Sandiford <richard.sandiford@arm.com>
Mon, 18 Nov 2019 15:26:55 +0000 (15:26 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Mon, 18 Nov 2019 15:26:55 +0000 (15:26 +0000)
commit8489e1f45b50600c01eb8ed8c5d0ca914ded281c
tree1e519a352bc06542b1ef8703ad437a501fadac9f
parent1aeffdce2dfe718e1337d75eb4f22c3c300df9bb
Optimise WAR and WAW alias checks

For:

  void
  f1 (int *x, int *y)
  {
    for (int i = 0; i < 32; ++i)
      x[i] += y[i];
  }

we checked at runtime whether one vector at x would overlap one vector
at y.  But in cases like this, the vector code would handle x <= y just
fine, since any write to address A still happens after any read from
address A.  The only problem is if x is ahead of y by less than a
vector.

The same is true for two writes:

  void
  f2 (int *x, int *y)
  {
    for (int i = 0; i < 32; ++i)
      {
        x[i] = i;
        y[i] = 2;
      }
  }

if y <= x then a vector write at y after a vector write at x would
have the same net effect as the original scalar writes.

This patch optimises the alias checks for these two cases.  E.g.,
before the patch, f1 used:

        add     x2, x0, 15
        sub     x2, x2, x1
        cmp     x2, 30
        bls     .L2

whereas after the patch it uses:

        add     x2, x1, 4
        sub     x2, x0, x2
        cmp     x2, 8
        bls     .L2

Read-after-write cases like:

  int
  f3 (int *x, int *y)
  {
    int res = 0;
    for (int i = 0; i < 32; ++i)
      {
        x[i] = i;
        res += y[i];
      }
    return res;
  }

can cope with x == y, but otherwise don't allow overlap in either
direction.  Since checking for x == y at runtime would require extra
code, we're probably better off sticking with the current overlap test.

An overlap test is also needed if the scalar or vector accesses covered
by the alias check are mixed together, rather than all statements for
the second access following all statements for the first access.

The new code for gcc.target/aarch64/sve/var_strict_[135].c is slightly
better than before.

2019-11-18  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
* tree-data-ref.c (create_intersect_range_checks_index): If the
alias pair describes simple WAW and WAR dependencies, just check
whether the first B access overlaps later A accesses.
(create_waw_or_war_checks): New function that performs the same
optimization on addresses.
(create_intersect_range_checks): Call it.

gcc/testsuite/
* gcc.dg/vect/vect-alias-check-8.c: Expect WAR/WAW checks to be used.
* gcc.dg/vect/vect-alias-check-14.c: Likewise.
* gcc.dg/vect/vect-alias-check-15.c: Likewise.
* gcc.dg/vect/vect-alias-check-18.c: Likewise.
* gcc.dg/vect/vect-alias-check-19.c: Likewise.
* gcc.target/aarch64/sve/var_stride_1.c: Update expected sequence.
* gcc.target/aarch64/sve/var_stride_2.c: Likewise.
* gcc.target/aarch64/sve/var_stride_3.c: Likewise.
* gcc.target/aarch64/sve/var_stride_5.c: Likewise.

From-SVN: r278409
12 files changed:
gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/vect-alias-check-14.c
gcc/testsuite/gcc.dg/vect/vect-alias-check-15.c
gcc/testsuite/gcc.dg/vect/vect-alias-check-18.c
gcc/testsuite/gcc.dg/vect/vect-alias-check-19.c
gcc/testsuite/gcc.dg/vect/vect-alias-check-8.c
gcc/testsuite/gcc.target/aarch64/sve/var_stride_1.c
gcc/testsuite/gcc.target/aarch64/sve/var_stride_2.c
gcc/testsuite/gcc.target/aarch64/sve/var_stride_3.c
gcc/testsuite/gcc.target/aarch64/sve/var_stride_5.c
gcc/tree-data-ref.c