diff options
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/pr87288-1.c | 49 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/pr87288-2.c | 64 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/pr87288-3.c | 64 | ||||
-rw-r--r-- | gcc/tree-vect-loop.c | 14 |
6 files changed, 201 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index af5fddf1..f400284 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,11 @@ 2018-09-20 Richard Sandiford <richard.sandiford@arm.com> + PR tree-optimization/87288 + * tree-vect-loop.c (vect_analyze_loop_2): Take PEELING_FOR_GAPS + into account when determining PEELING_FOR_NITERS. + +2018-09-20 Richard Sandiford <richard.sandiford@arm.com> + PR tree-optimization/86877 * tree-vect-loop.c (vect_analyze_loop_2): Call vect_verify_datarefs_alignment. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ade95db..c7c8e90 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,12 @@ 2018-09-20 Richard Sandiford <richard.sandiford@arm.com> + PR tree-optimization/87288 + * gcc.dg/vect/pr87288-1.c: New test. + * gcc.dg/vect/pr87288-2.c: Likewise, + * gcc.dg/vect/pr87288-3.c: Likewise. + +2018-09-20 Richard Sandiford <richard.sandiford@arm.com> + PR tree-optimization/86877 * gfortran.dg/vect/vect-8-epilogue.F90: New test. diff --git a/gcc/testsuite/gcc.dg/vect/pr87288-1.c b/gcc/testsuite/gcc.dg/vect/pr87288-1.c new file mode 100644 index 0000000..0d0a70d --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr87288-1.c @@ -0,0 +1,49 @@ +#include "tree-vect.h" + +#define N (VECTOR_BITS / 32) +#define MAX_COUNT 4 + +void __attribute__ ((noipa)) +run (int *restrict a, int *restrict b, int count) +{ + for (int i = 0; i < count * N; ++i) + { + a[i * 2] = b[i * 2] + count; + a[i * 2 + 1] = count; + } +} + +void __attribute__ ((noipa)) +check (int *restrict a, int count) +{ + for (int i = 0; i < count * N; ++i) + if (a[i * 2] != i * 41 + count || a[i * 2 + 1] != count) + __builtin_abort (); + if (a[count * 2 * N] != 999) + __builtin_abort (); +} + +int a[N * MAX_COUNT * 2 + 1], b[N * MAX_COUNT * 2]; + +int +main (void) +{ + check_vect (); + + for (int i = 0; i < N * MAX_COUNT; ++i) + { + b[i * 2] = i * 41; + asm volatile ("" ::: "memory"); + } + + for (int i = 0; i <= MAX_COUNT; ++i) + { + a[i * 2 * N] = 999; + run (a, b, i); + check (a, i); + } + + return 0; +} + +/* { dg-final { scan-tree-dump-times {LOOP VECTORIZED} 1 "vect" { target { { vect_int && vect_perm } && vect_element_align } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr87288-2.c b/gcc/testsuite/gcc.dg/vect/pr87288-2.c new file mode 100644 index 0000000..e9ff9a0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr87288-2.c @@ -0,0 +1,64 @@ +#include "tree-vect.h" + +#define N (VECTOR_BITS / 32) +#define MAX_COUNT 4 + +#define RUN_COUNT(COUNT) \ + void __attribute__ ((noipa)) \ + run_##COUNT (int *restrict a, int *restrict b) \ + { \ + for (int i = 0; i < N * COUNT; ++i) \ + { \ + a[i * 2] = b[i * 2] + COUNT; \ + a[i * 2 + 1] = COUNT; \ + } \ + } + +RUN_COUNT (1) +RUN_COUNT (2) +RUN_COUNT (3) +RUN_COUNT (4) + +void __attribute__ ((noipa)) +check (int *restrict a, int count) +{ + for (int i = 0; i < count * N; ++i) + if (a[i * 2] != i * 41 + count || a[i * 2 + 1] != count) + __builtin_abort (); + if (a[count * 2 * N] != 999) + __builtin_abort (); +} + +int a[N * MAX_COUNT * 2 + 1], b[N * MAX_COUNT * 2]; + +int +main (void) +{ + check_vect (); + + for (int i = 0; i < N * MAX_COUNT; ++i) + { + b[i * 2] = i * 41; + asm volatile ("" ::: "memory"); + } + + a[N * 2] = 999; + run_1 (a, b); + check (a, 1); + + a[N * 4] = 999; + run_2 (a, b); + check (a, 2); + + a[N * 6] = 999; + run_3 (a, b); + check (a, 3); + + a[N * 8] = 999; + run_4 (a, b); + check (a, 4); + + return 0; +} + +/* { dg-final { scan-tree-dump {LOOP VECTORIZED} "vect" { target { { vect_int && vect_perm } && vect_element_align } } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr87288-3.c b/gcc/testsuite/gcc.dg/vect/pr87288-3.c new file mode 100644 index 0000000..23f574c --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/pr87288-3.c @@ -0,0 +1,64 @@ +#include "tree-vect.h" + +#define N (VECTOR_BITS / 32) +#define MAX_COUNT 4 + +#define RUN_COUNT(COUNT) \ + void __attribute__ ((noipa)) \ + run_##COUNT (int *restrict a, int *restrict b) \ + { \ + for (int i = 0; i < N * COUNT + 1; ++i) \ + { \ + a[i * 2] = b[i * 2] + COUNT; \ + a[i * 2 + 1] = COUNT; \ + } \ + } + +RUN_COUNT (1) +RUN_COUNT (2) +RUN_COUNT (3) +RUN_COUNT (4) + +void __attribute__ ((noipa)) +check (int *restrict a, int count) +{ + for (int i = 0; i < count * N + 1; ++i) + if (a[i * 2] != i * 41 + count || a[i * 2 + 1] != count) + __builtin_abort (); + if (a[count * 2 * N + 2] != 999) + __builtin_abort (); +} + +int a[N * MAX_COUNT * 2 + 3], b[N * MAX_COUNT * 2 + 2]; + +int +main (void) +{ + check_vect (); + + for (int i = 0; i < N * MAX_COUNT + 1; ++i) + { + b[i * 2] = i * 41; + asm volatile ("" ::: "memory"); + } + + a[N * 2 + 2] = 999; + run_1 (a, b); + check (a, 1); + + a[N * 4 + 2] = 999; + run_2 (a, b); + check (a, 2); + + a[N * 6 + 2] = 999; + run_3 (a, b); + check (a, 3); + + a[N * 8 + 2] = 999; + run_4 (a, b); + check (a, 4); + + return 0; +} + +/* { dg-final { scan-tree-dump {LOOP VECTORIZED} "vect" { target { { vect_int && vect_perm } && vect_element_align } } } } */ diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c index 70e9157..fdac10b 100644 --- a/gcc/tree-vect-loop.c +++ b/gcc/tree-vect-loop.c @@ -2074,14 +2074,22 @@ start_over: /* The main loop handles all iterations. */ LOOP_VINFO_PEELING_FOR_NITER (loop_vinfo) = false; else if (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo) - && LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) > 0) + && LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) >= 0) { - if (!multiple_p (LOOP_VINFO_INT_NITERS (loop_vinfo) - - LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo), + /* Work out the (constant) number of iterations that need to be + peeled for reasons other than niters. */ + unsigned int peel_niter = LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo); + if (LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo)) + peel_niter += 1; + if (!multiple_p (LOOP_VINFO_INT_NITERS (loop_vinfo) - peel_niter, LOOP_VINFO_VECT_FACTOR (loop_vinfo))) LOOP_VINFO_PEELING_FOR_NITER (loop_vinfo) = true; } else if (LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo) + /* ??? When peeling for gaps but not alignment, we could + try to check whether the (variable) niters is known to be + VF * N + 1. That's something of a niche case though. */ + || LOOP_VINFO_PEELING_FOR_GAPS (loop_vinfo) || !LOOP_VINFO_VECT_FACTOR (loop_vinfo).is_constant (&const_vf) || ((tree_ctz (LOOP_VINFO_NITERS (loop_vinfo)) < (unsigned) exact_log2 (const_vf)) |