From: Victor Kaplansky Date: Thu, 16 Aug 2007 14:20:39 +0000 (+0000) Subject: tree-vectorizer.c (new_loop_vec_info): Initialize new field. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=bc1edb77ba75d9a7b2c780a0fe8f04af0b3b6479;p=gcc.git tree-vectorizer.c (new_loop_vec_info): Initialize new field. gcc/ChangeLog * tree-vectorizer.c (new_loop_vec_info): Initialize new field. (destroy_loop_vec_info): Add call to VEC_free. * tree-vectorizer.h (may_alias_ddrs): Define. (LOOP_VINFO_MAY_ALIAS_DDRS): Define. * tree-vect-analyze.c (vect_analyze_data_ref_dependence): Change reporting to dump. (vect_is_duplicate_ddr): New. (vect_mark_for_runtime_alias_test): New. (vect_analyze_data_ref_dependences) Add call to vect_mark_for_runtime_alias_test. (vect_enhance_data_refs_alignment): Define local variable vect_versioning_for_alias_required, don't perform peeling for alignment if versioning for alias is required. (vect_enhance_data_refs_alignment): Use PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS instead of PARAM_VECT_MAX_VERSION_CHECKS. * tree-vect-transform.c (vect_create_cond_for_alias_checks): New. (vect_transform_loop): Add call to vect_create_cond_for_alias_checks. (vect_vfa_segment_size): New. * params.def (PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS): Rename. (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS): Define. * gcc/doc/invoke.texi (vect-max-version-for-alignment-checks): Document. (vect-max-version-for-alias-checks): Document. (vect-max-version-checks): Remove. gcc/testsuite/ChangeLog * gcc.dg/vect/vect-vfa-01.c: New. * gcc.dg/vect/vect-vfa-02.c: New. * gcc.dg/vect/vect-vfa-03.c: New. * gcc.dg/vect/vect-vfa-04.c: New. * gcc.dg/vect/vect-102a.c, gcc.dg/vect/vect-51.c, gcc.dg/vect/pr29145.c, gcc.dg/vect/vect-43.c, gcc.dg/vect/vect-61.c, gcc.dg/vect/vect-53.c, gcc.dg/vect/vect-45.c, gcc.dg/vect/vect-101.c, gcc.dg/vect/vect-37.c, gcc.dg/vect/vect-79.c, gcc.dg/vect/vect-102.c, gcc.dg/vect/vect-dv-2.c, gcc.dg/vect/vect-57.c, gcc.dg/vect/vect-49.c, gfortran.dg/vect/pr19049.f90: Rename to start with prefix no-vfa-. * gcc.dg/vect/vect.exp: Disable versioning for alias when test starts with no-vfa-. * gfortran.dg/vect/vect.exp: Likewise. From-SVN: r127559 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6829864d57d..db120c094c4 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,36 @@ +2007-08-16 Victor Kaplansky + + * tree-vectorizer.c (new_loop_vec_info): Initialize new + field. + (destroy_loop_vec_info): Add call to VEC_free. + * tree-vectorizer.h (may_alias_ddrs): Define. + (LOOP_VINFO_MAY_ALIAS_DDRS): Define. + * tree-vect-analyze.c (vect_analyze_data_ref_dependence): + Change reporting to dump. + (vect_is_duplicate_ddr): New. + (vect_mark_for_runtime_alias_test): New. + (vect_analyze_data_ref_dependences) Add call to + vect_mark_for_runtime_alias_test. + (vect_enhance_data_refs_alignment): Define local variable + vect_versioning_for_alias_required, don't perform + peeling for alignment if versioning for alias is + required. + (vect_enhance_data_refs_alignment): Use + PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS instead of + PARAM_VECT_MAX_VERSION_CHECKS. + * tree-vect-transform.c + (vect_create_cond_for_alias_checks): New. + (vect_transform_loop): Add call to + vect_create_cond_for_alias_checks. + (vect_vfa_segment_size): New. + * params.def (PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS): + Rename. + (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS): Define. + * gcc/doc/invoke.texi + (vect-max-version-for-alignment-checks): Document. + (vect-max-version-for-alias-checks): Document. + (vect-max-version-checks): Remove. + 2007-08-16 Uros Bizjak * config/i386/i386.md (*rep_movdi_rex64): Emit "rep" prefix on diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 944cb4631a2..eed4f10b506 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -6741,10 +6741,15 @@ value is 500. When set to 1, use expensive methods to eliminate all redundant constraints. The default value is 0. -@item vect-max-version-checks -The maximum number of runtime checks that can be performed when doing -loop versioning in the vectorizer. See option ftree-vect-loop-version -for more information. +@item vect-max-version-for-alignment-checks +The maximum number of runtime checks that can be performed when +doing loop versioning for alignment in the vectorizer. See option +ftree-vect-loop-version for more information. + +@item vect-max-version-for-alias-checks +The maximum number of runtime checks that can be performed when +doing loop versioning for alias in the vectorizer. See option +ftree-vect-loop-version for more information. @item max-iterations-to-track diff --git a/gcc/params.def b/gcc/params.def index 32216764473..bcdb4bb2da2 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -485,11 +485,16 @@ DEFPARAM(PARAM_OMEGA_ELIMINATE_REDUNDANT_CONSTRAINTS, "When set to 1, use expensive methods to eliminate all redundant constraints", 0, 0, 1) -DEFPARAM(PARAM_VECT_MAX_VERSION_CHECKS, - "vect-max-version-checks", - "Bound on number of runtime checks inserted by the vectorizer's loop versioning", +DEFPARAM(PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS, + "vect-max-version-for-alignment-checks", + "Bound on number of runtime checks inserted by the vectorizer's loop versioning for alignment check", 6, 0, 0) +DEFPARAM(PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS, + "vect-max-version-for-alias-checks", + "Bound on number of runtime checks inserted by the vectorizer's loop versioning for alias check", + 10, 0, 0) + DEFPARAM(PARAM_MAX_CSELIB_MEMORY_LOCATIONS, "max-cselib-memory-locations", "The maximum memory locations recorded by cselib", diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0b79ae97313..387b5791921 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,22 @@ +2007-08-16 Victor Kaplansky + + * gcc.dg/vect/vect-vfa-01.c: New. + * gcc.dg/vect/vect-vfa-02.c: New. + * gcc.dg/vect/vect-vfa-03.c: New. + * gcc.dg/vect/vect-vfa-04.c: New. + * gcc.dg/vect/vect-102a.c, gcc.dg/vect/vect-51.c, + gcc.dg/vect/pr29145.c, gcc.dg/vect/vect-43.c, + gcc.dg/vect/vect-61.c, gcc.dg/vect/vect-53.c, + gcc.dg/vect/vect-45.c, gcc.dg/vect/vect-101.c, + gcc.dg/vect/vect-37.c, gcc.dg/vect/vect-79.c, + gcc.dg/vect/vect-102.c, gcc.dg/vect/vect-dv-2.c, + gcc.dg/vect/vect-57.c, gcc.dg/vect/vect-49.c, + gfortran.dg/vect/pr19049.f90: Rename to start with + prefix no-vfa-. + * gcc.dg/vect/vect.exp: Disable versioning for alias + when test starts with no-vfa-. + * gfortran.dg/vect/vect.exp: Likewise. + 2007-08-16 Richard Sandiford * gcc.dg/torture/pr32897.c: New test. diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-pr29145.c b/gcc/testsuite/gcc.dg/vect/no-vfa-pr29145.c new file mode 100644 index 00000000000..97d190ca278 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-pr29145.c @@ -0,0 +1,48 @@ +/* { dg-require-effective-target vect_int } */ + +#include +#include "tree-vect.h" + +void with_restrict(int * __restrict p) +{ + int i; + int *q = p - 2; + + for (i = 0; i < 1000; ++i) { + p[i] = q[i]; + } +} + +void without_restrict(int * p) +{ + int i; + int *q = p - 2; + + for (i = 0; i < 1000; ++i) { + p[i] = q[i]; + } +} + +int main(void) +{ + int i; + int a[1002]; + int b[1002]; + + for (i = 0; i < 1002; ++i) { + a[i] = b[i] = i; + } + + with_restrict(a + 2); + without_restrict(b + 2); + + for (i = 0; i < 1002; ++i) { + if (a[i] != b[i]) + abort(); + } + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 2 "vect" } } */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-101.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-101.c new file mode 100644 index 00000000000..e195a58af5f --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-101.c @@ -0,0 +1,49 @@ +/* { dg-require-effective-target vect_int } */ + +#include +#include +#include "tree-vect.h" + +#define N 9 + +struct extraction +{ + int a[N]; + int b[N]; +}; + +static int a[N] = {1,2,3,4,5,6,7,8,9}; +static int b[N] = {2,3,4,5,6,7,8,9,0}; + +int main1 (int x, int y) { + int i; + struct extraction *p; + p = (struct extraction *) malloc (sizeof (struct extraction)); + + /* Not vectorizable: different unknown offset. */ + for (i = 0; i < N; i++) + { + *((int *)p + x + i) = a[i]; + *((int *)p + y + i) = b[i]; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (p->a[i] != a[i] || p->b[i] != b[i]) + abort(); + } + return 0; +} + +int main (void) +{ + check_vect (); + + return main1 (0, N); +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" } } */ +/* { dg-final { scan-tree-dump-times "can't determine dependence" 1 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ + diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-102.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-102.c new file mode 100644 index 00000000000..49df4f9bc90 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-102.c @@ -0,0 +1,57 @@ +/* { dg-require-effective-target vect_int } */ + +#include +#include +#include "tree-vect.h" + +#define N 9 + +struct extraction +{ + int a[N]; + int b[N]; +}; + +static int a[N] = {1,2,3,4,5,6,7,8,9}; +static int b[N] = {2,3,4,5,6,7,8,9,9}; +volatile int foo; + +int main1 (int x, int y) { + int i; + struct extraction *p; + p = (struct extraction *) malloc (sizeof (struct extraction)); + + for (i = 0; i < N; i++) + { + p->a[i] = a[i]; + if (foo == 135) + abort (); /* to avoid vectorization */ + } + + /* Not vectorizable: distance 1. */ + for (i = 0; i < N - 1; i++) + { + *((int *)p + x + i) = *((int *)p + x + i + 1); + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (p->a[i] != b[i]) + abort(); + } + return 0; +} + +int main (void) +{ + check_vect (); + + foo = 0; + return main1 (0, N); +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" } } */ +/* { dg-final { scan-tree-dump-times "possible dependence between data-refs" 1 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ + diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-102a.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-102a.c new file mode 100644 index 00000000000..35023fc65dc --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-102a.c @@ -0,0 +1,57 @@ +/* { dg-require-effective-target vect_int } */ + +#include +#include +#include "tree-vect.h" + +#define N 9 + +struct extraction +{ + int a[N]; + int b[N]; +}; + +static int a[N] = {1,2,3,4,5,6,7,8,9}; +static int b[N] = {2,3,4,5,6,7,8,9,9}; +volatile int foo; + +int main1 (int x, int y) { + int i; + struct extraction *p; + p = (struct extraction *) malloc (sizeof (struct extraction)); + + for (i = 0; i < N; i++) + { + p->a[i] = a[i]; + if (foo == 135) + abort (); /* to avoid vectorization */ + } + + /* Not vectorizable: distance 1. */ + for (i = 0; i < N - 1; i++) + { + p->a[x + i] = p->a[x + i + 1]; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (p->a[i] != b[i]) + abort(); + } + return 0; +} + +int main (void) +{ + check_vect (); + + foo = 0; + return main1 (0, N); +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" } } */ +/* { dg-final { scan-tree-dump-times "possible dependence between data-refs" 1 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ + diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-37.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-37.c new file mode 100644 index 00000000000..e54e0c5166c --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-37.c @@ -0,0 +1,61 @@ +/* { dg-require-effective-target vect_int } */ + +#include +#include "tree-vect.h" + +#define N 16 +char x[N] __attribute__ ((__aligned__(16))); + +int main1 (char *y) +{ + struct { + char *p; + char *q; + } s; + char cb[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45}; + int i; + + /* Not vectorized - can't antialias the pointer s.p from the array cb. */ + s.p = y; + for (i = 0; i < N; i++) + { + s.p[i] = cb[i]; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (s.p[i] != cb[i]) + abort (); + } + + /* Not vectorized - can't antialias the pointer s.p from the pointer s.q. */ + s.q = cb; + for (i = 0; i < N; i++) + { + s.p[i] = s.q[i]; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (s.p[i] != s.q[i]) + abort (); + } + + return 0; +} + +int main (void) +{ + check_vect (); + + return main1 (x); +} + +/* Currently the loops fail to vectorize due to aliasing problems. + If/when the aliasing problems are resolved, unalignment may + prevent vectorization on some targets. */ +/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "can't determine dependence between" 2 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-43.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-43.c new file mode 100644 index 00000000000..258da2827f7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-43.c @@ -0,0 +1,78 @@ +/* { dg-require-effective-target vect_float } */ + +#include +#include "tree-vect.h" + +#define N 256 + +void bar (float *pa, float *pb, float *pc) +{ + int i; + + /* check results: */ + for (i = 0; i < N; i++) + { + if (pa[i] != (pb[i] * pc[i])) + abort (); + } + + return; +} + + +int +main1 (float *pa) +{ + int i; + float pb[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57}; + float pc[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; + + /* Not vectorizable: pa may alias pb and/or pc, since their addresses escape. */ + for (i = 0; i < N; i++) + { + pa[i] = pb[i] * pc[i]; + } + + bar (pa,pb,pc); + + return 0; +} + +int +main2 (float * pa) +{ + int i; + float pb[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57}; + float pc[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; + + /* Vectorizable: pb and pc addresses do not escape. */ + for (i = 0; i < N; i++) + { + pa[i] = pb[i] * pc[i]; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (pa[i] != (pb[i] * pc[i])) + abort (); + } + + return 0; +} + +int main (void) +{ + int i; + float a[N] __attribute__ ((__aligned__(16))); + + check_vect (); + + main1 (a); + main2 (a); + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ +/* { dg-final { scan-tree-dump-times "Alignment of access forced using versioning" 1 "vect" { target vect_no_align } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-45.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-45.c new file mode 100644 index 00000000000..8a998564319 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-45.c @@ -0,0 +1,59 @@ +/* { dg-require-effective-target vect_float } */ + +#include +#include "tree-vect.h" + +#define N 256 + +void bar (const float *pa, const float *pb, const float *pc) +{ + int i; + + /* check results: */ + for (i = 0; i < N; i++) + { + if (pa[i] != (pb[i] * pc[i])) + abort (); + } + + return; +} + +/* Unaligned pointer accesses, with unknown alignment. + The loop bound is known and divisible by the vectorization factor. + Can't prove that the pointers don't alias. + vect-51.c is similar to this one with one difference: + the loop bound is unknown. + vect-44.c is similar to this one with one difference: + Aliasing is not a problem. */ + +int +main1 (float *pa, float *pb, float *pc) +{ + int i; + + for (i = 0; i < N; i++) + { + pa[i] = pb[i] * pc[i]; + } + + bar (pa,pb,pc); + + return 0; +} + +int main (void) +{ + int i; + float a[N]; + float b[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57}; + float c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; + + check_vect (); + + main1 (a,b,c); + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-49.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-49.c new file mode 100644 index 00000000000..8dfd0e749b5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-49.c @@ -0,0 +1,61 @@ +/* { dg-require-effective-target vect_float } */ + +#include +#include "tree-vect.h" + +#define N 256 + +void bar (float *pa, float *pb, float *pc) +{ + int i; + + /* check results: */ + for (i = 0; i < N; i++) + { + if (pa[i] != (pb[i] * pc[i])) + abort (); + } + + return; +} + +/* Unaligned pointer read accesses, aligned pointer write access. + The loop bound is known and divisible by the vectorization factor. + Can't prove that the pointers don't alias. + vect-53.c is similar to this one with one difference: + the loop bound is unknown. + vect-48.c is similar to this one with one difference: + aliasing is not a problem. */ + +int +main1 (float *pb, float *pc) +{ + float pa[N] __attribute__ ((__aligned__(16))); + int i; + + for (i = 0; i < N; i++) + { + pa[i] = pb[i] * pc[i]; + } + + bar (pa,pb,pc); + + return 0; +} + +int main (void) +{ + int i; + float b[N+1] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60}; + float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; + + check_vect (); + + main1 (b,c); + main1 (&b[1],c); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-51.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-51.c new file mode 100644 index 00000000000..541a5ffef3b --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-51.c @@ -0,0 +1,59 @@ +/* { dg-require-effective-target vect_float } */ + +#include +#include "tree-vect.h" + +#define N 256 + +void bar (const float *pa, const float *pb, const float *pc) +{ + int i; + + /* check results: */ + for (i = 0; i < N; i++) + { + if (pa[i] != (pb[i] * pc[i])) + abort (); + } + + return; +} + +/* Unaligned pointer accesses, with unknown alignment. + The loop bound is unknown. + Can't prove that the pointers don't alias. + vect-45.c is similar to this one with one difference: + the loop bound is known. + vect-50.c is similar to this one with one difference: + Aliasing is not a problem. */ + +int +main1 (int n, float *pa, float *pb, float *pc) +{ + int i; + + for (i = 0; i < n; i++) + { + pa[i] = pb[i] * pc[i]; + } + + bar (pa,pb,pc); + + return 0; +} + +int main (void) +{ + int i; + float a[N]; + float b[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57}; + float c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; + + check_vect (); + + main1 (N,a,b,c); + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-53.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-53.c new file mode 100644 index 00000000000..91eaabeb93b --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-53.c @@ -0,0 +1,62 @@ +/* { dg-require-effective-target vect_float } */ + +#include +#include "tree-vect.h" + +#define N 256 + +void bar (const float *pa, const float *pb, const float *pc) +{ + int i; + + /* check results: */ + for (i = 0; i < N; i++) + { + if (pa[i] != (pb[i] * pc[i])) + abort (); + } + + return; +} + +/* Unaligned pointer read accesses, aligned pointer write access. + The loop bound is unknown. + Can't prove that the pointers don't alias. + vect-49.c is similar to this one with one difference: + the loop bound is known. + vect-52.c is similar to this one with one difference: + aliasing is not a problem. */ + +int +main1 (int n, float *pb, float *pc) +{ + float pa[N] __attribute__ ((__aligned__(16))); + int i; + + for (i = 0; i < n; i++) + { + pa[i] = pb[i] * pc[i]; + } + + bar (pa,pb,pc); + + return 0; +} + +int main (void) +{ + int i; + float a[N] __attribute__ ((__aligned__(16))); + float b[N+1] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60}; + float c[N+1] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}; + + check_vect (); + + main1 (N,&b[1],c); + main1 (N,&b[1],&c[1]); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-57.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-57.c new file mode 100644 index 00000000000..bcac95a0393 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-57.c @@ -0,0 +1,62 @@ +/* { dg-require-effective-target vect_float } */ + +#include +#include "tree-vect.h" + +#define N 256 + +void bar (float *pa, float *pb, float *pc) +{ + int i; + + /* check results: */ + for (i = 0; i < N/2; i++) + { + if (pa[i] != (pb[i+1] * pc[i+1])) + abort (); + } + + return; +} + +/* Unaligned pointer read accesses with known alignment, + and an unaligned write access with unknown alignment. + The loop bound is known and divisible by the vectorization factor. + Can't prove that the pointers don't alias. + vect-61.c is similar to this one with one difference: + the loop bound is unknown. + vect-56.c is similar to this one with two differences: + aliasing is a problem, and the write access is aligned. */ + +int +main1 (float *pa) +{ + int i; + float b[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57}; + float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; + float *pb = b; + float *pc = c; + + for (i = 0; i < N/2; i++) + { + pa[i] = pb[i+1] * pc[i+1]; + } + + bar (pa, pb, pc); + + return 0; +} + +int main (void) +{ + int i; + float a[N] __attribute__ ((__aligned__(16))); + + check_vect (); + main1 (a); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-61.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-61.c new file mode 100644 index 00000000000..9f4e8e9882b --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-61.c @@ -0,0 +1,64 @@ +/* { dg-require-effective-target vect_int } */ +/* { dg-require-effective-target vect_float } */ + +#include +#include "tree-vect.h" + +#define N 256 + +void bar (float *pa, float *pb, float *pc) +{ + int i; + + /* check results: */ + for (i = 0; i < N/2; i++) + { + if (pa[i] != (pb[i+1] * pc[i+1])) + abort (); + } + + return; +} + +/* Unaligned pointer read accesses with known alignment, + and an unaligned write access with unknown alignment. + The loop bound is iunknown. + Can't prove that the pointers don't alias. + vect-57.c is similar to this one with one difference: + the loop bound is known. + vect-60.c is similar to this one with two differences: + aliasing is not a problem, and the write access is unaligned. */ + +int +main1 (int n , float *pa) +{ + int i; + float b[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57}; + float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; + float *pb = b; + float *pc = c; + + for (i = 0; i < n/2; i++) + { + pa[i] = pb[i+1] * pc[i+1]; + } + + bar (pa,pb,pc); + + return 0; +} + +int main (void) +{ + int i; + int n=N; + float a[N] __attribute__ ((__aligned__(16))); + + check_vect (); + main1 (n,a); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-79.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-79.c new file mode 100644 index 00000000000..8e98e4d0ed9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-79.c @@ -0,0 +1,50 @@ +/* { dg-require-effective-target vect_float } */ + +#include +#include "tree-vect.h" + +#define N 16 + +float fa[N] __attribute__ ((__aligned__(16))); +float fb[N+4] __attribute__ ((__aligned__(16))) = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 7.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0}; +float fc[N] __attribute__ ((__aligned__(16))) = {0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 7.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5, 15.5}; + +/* Like vect-80.c but the pointers are not annotated as restricted, + and therefore can't be antialiased. */ + +int +main1 (float *pa, float *pb, float *pc) +{ + int i; + float *q = pb + 4; + + for (i = 0; i < N; i++) + { + pa[i] = q[i] * pc[i]; + } + + for (i = 0; i < N; i++) + { + if (pa[i] != q[i] * pc[i]) + abort(); + } + + return 0; +} + + +int main (void) +{ + check_vect (); + + main1 (fa, fb, fc); + + return 0; +} + +/* Currently the loops fail to vectorize due to aliasing problems. + If/when the aliasing problems are resolved, unalignment may + prevent vectorization on some targets. */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "can't determine dependence between" 1 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-dv-2.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-dv-2.c new file mode 100644 index 00000000000..30d229c1996 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-dv-2.c @@ -0,0 +1,77 @@ +/* { dg-require-effective-target vect_int } */ + +#include +#include +#include "tree-vect.h" + +#define N 64 +#define MAX 42 + +extern void abort(void); + +int main () +{ + int A[N]; + int B[N]; + int C[N]; + int D[N]; + + int i, j; + + check_vect (); + + for (i = 0; i < N; i++) + { + A[i] = i; + B[i] = i; + C[i] = i; + D[i] = i; + } + + /* Vectorizable */ + for (i = 0; i < N-20; i++) + { + A[i] = A[i+20]; + } + + /* check results: */ + for (i = 0; i < N-20; i++) + { + if (A[i] != D[i+20]) + abort (); + } + + /* Vectorizable */ + for (i = 0; i < 16; i++) + { + B[i] = B[i] + 5; + } + + /* check results: */ + for (i = 0; i < 16; i++) + { + if (B[i] != C[i] + 5) + abort (); + } + + /* Not vectorizable */ + for (i = 0; i < 4; i++) + { + C[i] = C[i+3]; + } + + /* check results: */ + for (i = 0; i < 4; i++) + { + if (C[i] != D[i+3]) + abort (); + } + + return 0; +} + + +/* The initialization induction loop (with aligned access) is also vectorized. */ +/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" } } */ +/* { dg-final { scan-tree-dump-times "accesses have the same alignment." 2 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/pr29145.c b/gcc/testsuite/gcc.dg/vect/pr29145.c deleted file mode 100644 index 97d190ca278..00000000000 --- a/gcc/testsuite/gcc.dg/vect/pr29145.c +++ /dev/null @@ -1,48 +0,0 @@ -/* { dg-require-effective-target vect_int } */ - -#include -#include "tree-vect.h" - -void with_restrict(int * __restrict p) -{ - int i; - int *q = p - 2; - - for (i = 0; i < 1000; ++i) { - p[i] = q[i]; - } -} - -void without_restrict(int * p) -{ - int i; - int *q = p - 2; - - for (i = 0; i < 1000; ++i) { - p[i] = q[i]; - } -} - -int main(void) -{ - int i; - int a[1002]; - int b[1002]; - - for (i = 0; i < 1002; ++i) { - a[i] = b[i] = i; - } - - with_restrict(a + 2); - without_restrict(b + 2); - - for (i = 0; i < 1002; ++i) { - if (a[i] != b[i]) - abort(); - } - return 0; -} - -/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 2 "vect" } } */ -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ -/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-101.c b/gcc/testsuite/gcc.dg/vect/vect-101.c deleted file mode 100644 index e195a58af5f..00000000000 --- a/gcc/testsuite/gcc.dg/vect/vect-101.c +++ /dev/null @@ -1,49 +0,0 @@ -/* { dg-require-effective-target vect_int } */ - -#include -#include -#include "tree-vect.h" - -#define N 9 - -struct extraction -{ - int a[N]; - int b[N]; -}; - -static int a[N] = {1,2,3,4,5,6,7,8,9}; -static int b[N] = {2,3,4,5,6,7,8,9,0}; - -int main1 (int x, int y) { - int i; - struct extraction *p; - p = (struct extraction *) malloc (sizeof (struct extraction)); - - /* Not vectorizable: different unknown offset. */ - for (i = 0; i < N; i++) - { - *((int *)p + x + i) = a[i]; - *((int *)p + y + i) = b[i]; - } - - /* check results: */ - for (i = 0; i < N; i++) - { - if (p->a[i] != a[i] || p->b[i] != b[i]) - abort(); - } - return 0; -} - -int main (void) -{ - check_vect (); - - return main1 (0, N); -} - -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" } } */ -/* { dg-final { scan-tree-dump-times "can't determine dependence" 1 "vect" } } */ -/* { dg-final { cleanup-tree-dump "vect" } } */ - diff --git a/gcc/testsuite/gcc.dg/vect/vect-102.c b/gcc/testsuite/gcc.dg/vect/vect-102.c deleted file mode 100644 index 49df4f9bc90..00000000000 --- a/gcc/testsuite/gcc.dg/vect/vect-102.c +++ /dev/null @@ -1,57 +0,0 @@ -/* { dg-require-effective-target vect_int } */ - -#include -#include -#include "tree-vect.h" - -#define N 9 - -struct extraction -{ - int a[N]; - int b[N]; -}; - -static int a[N] = {1,2,3,4,5,6,7,8,9}; -static int b[N] = {2,3,4,5,6,7,8,9,9}; -volatile int foo; - -int main1 (int x, int y) { - int i; - struct extraction *p; - p = (struct extraction *) malloc (sizeof (struct extraction)); - - for (i = 0; i < N; i++) - { - p->a[i] = a[i]; - if (foo == 135) - abort (); /* to avoid vectorization */ - } - - /* Not vectorizable: distance 1. */ - for (i = 0; i < N - 1; i++) - { - *((int *)p + x + i) = *((int *)p + x + i + 1); - } - - /* check results: */ - for (i = 0; i < N; i++) - { - if (p->a[i] != b[i]) - abort(); - } - return 0; -} - -int main (void) -{ - check_vect (); - - foo = 0; - return main1 (0, N); -} - -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" } } */ -/* { dg-final { scan-tree-dump-times "possible dependence between data-refs" 1 "vect" } } */ -/* { dg-final { cleanup-tree-dump "vect" } } */ - diff --git a/gcc/testsuite/gcc.dg/vect/vect-102a.c b/gcc/testsuite/gcc.dg/vect/vect-102a.c deleted file mode 100644 index 35023fc65dc..00000000000 --- a/gcc/testsuite/gcc.dg/vect/vect-102a.c +++ /dev/null @@ -1,57 +0,0 @@ -/* { dg-require-effective-target vect_int } */ - -#include -#include -#include "tree-vect.h" - -#define N 9 - -struct extraction -{ - int a[N]; - int b[N]; -}; - -static int a[N] = {1,2,3,4,5,6,7,8,9}; -static int b[N] = {2,3,4,5,6,7,8,9,9}; -volatile int foo; - -int main1 (int x, int y) { - int i; - struct extraction *p; - p = (struct extraction *) malloc (sizeof (struct extraction)); - - for (i = 0; i < N; i++) - { - p->a[i] = a[i]; - if (foo == 135) - abort (); /* to avoid vectorization */ - } - - /* Not vectorizable: distance 1. */ - for (i = 0; i < N - 1; i++) - { - p->a[x + i] = p->a[x + i + 1]; - } - - /* check results: */ - for (i = 0; i < N; i++) - { - if (p->a[i] != b[i]) - abort(); - } - return 0; -} - -int main (void) -{ - check_vect (); - - foo = 0; - return main1 (0, N); -} - -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" } } */ -/* { dg-final { scan-tree-dump-times "possible dependence between data-refs" 1 "vect" } } */ -/* { dg-final { cleanup-tree-dump "vect" } } */ - diff --git a/gcc/testsuite/gcc.dg/vect/vect-37.c b/gcc/testsuite/gcc.dg/vect/vect-37.c deleted file mode 100644 index e54e0c5166c..00000000000 --- a/gcc/testsuite/gcc.dg/vect/vect-37.c +++ /dev/null @@ -1,61 +0,0 @@ -/* { dg-require-effective-target vect_int } */ - -#include -#include "tree-vect.h" - -#define N 16 -char x[N] __attribute__ ((__aligned__(16))); - -int main1 (char *y) -{ - struct { - char *p; - char *q; - } s; - char cb[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45}; - int i; - - /* Not vectorized - can't antialias the pointer s.p from the array cb. */ - s.p = y; - for (i = 0; i < N; i++) - { - s.p[i] = cb[i]; - } - - /* check results: */ - for (i = 0; i < N; i++) - { - if (s.p[i] != cb[i]) - abort (); - } - - /* Not vectorized - can't antialias the pointer s.p from the pointer s.q. */ - s.q = cb; - for (i = 0; i < N; i++) - { - s.p[i] = s.q[i]; - } - - /* check results: */ - for (i = 0; i < N; i++) - { - if (s.p[i] != s.q[i]) - abort (); - } - - return 0; -} - -int main (void) -{ - check_vect (); - - return main1 (x); -} - -/* Currently the loops fail to vectorize due to aliasing problems. - If/when the aliasing problems are resolved, unalignment may - prevent vectorization on some targets. */ -/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { xfail *-*-* } } } */ -/* { dg-final { scan-tree-dump-times "can't determine dependence between" 2 "vect" } } */ -/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-43.c b/gcc/testsuite/gcc.dg/vect/vect-43.c deleted file mode 100644 index 258da2827f7..00000000000 --- a/gcc/testsuite/gcc.dg/vect/vect-43.c +++ /dev/null @@ -1,78 +0,0 @@ -/* { dg-require-effective-target vect_float } */ - -#include -#include "tree-vect.h" - -#define N 256 - -void bar (float *pa, float *pb, float *pc) -{ - int i; - - /* check results: */ - for (i = 0; i < N; i++) - { - if (pa[i] != (pb[i] * pc[i])) - abort (); - } - - return; -} - - -int -main1 (float *pa) -{ - int i; - float pb[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57}; - float pc[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; - - /* Not vectorizable: pa may alias pb and/or pc, since their addresses escape. */ - for (i = 0; i < N; i++) - { - pa[i] = pb[i] * pc[i]; - } - - bar (pa,pb,pc); - - return 0; -} - -int -main2 (float * pa) -{ - int i; - float pb[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57}; - float pc[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; - - /* Vectorizable: pb and pc addresses do not escape. */ - for (i = 0; i < N; i++) - { - pa[i] = pb[i] * pc[i]; - } - - /* check results: */ - for (i = 0; i < N; i++) - { - if (pa[i] != (pb[i] * pc[i])) - abort (); - } - - return 0; -} - -int main (void) -{ - int i; - float a[N] __attribute__ ((__aligned__(16))); - - check_vect (); - - main1 (a); - main2 (a); - return 0; -} - -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ -/* { dg-final { scan-tree-dump-times "Alignment of access forced using versioning" 1 "vect" { target vect_no_align } } } */ -/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-45.c b/gcc/testsuite/gcc.dg/vect/vect-45.c deleted file mode 100644 index 8a998564319..00000000000 --- a/gcc/testsuite/gcc.dg/vect/vect-45.c +++ /dev/null @@ -1,59 +0,0 @@ -/* { dg-require-effective-target vect_float } */ - -#include -#include "tree-vect.h" - -#define N 256 - -void bar (const float *pa, const float *pb, const float *pc) -{ - int i; - - /* check results: */ - for (i = 0; i < N; i++) - { - if (pa[i] != (pb[i] * pc[i])) - abort (); - } - - return; -} - -/* Unaligned pointer accesses, with unknown alignment. - The loop bound is known and divisible by the vectorization factor. - Can't prove that the pointers don't alias. - vect-51.c is similar to this one with one difference: - the loop bound is unknown. - vect-44.c is similar to this one with one difference: - Aliasing is not a problem. */ - -int -main1 (float *pa, float *pb, float *pc) -{ - int i; - - for (i = 0; i < N; i++) - { - pa[i] = pb[i] * pc[i]; - } - - bar (pa,pb,pc); - - return 0; -} - -int main (void) -{ - int i; - float a[N]; - float b[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57}; - float c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; - - check_vect (); - - main1 (a,b,c); - return 0; -} - -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ -/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-49.c b/gcc/testsuite/gcc.dg/vect/vect-49.c deleted file mode 100644 index 8dfd0e749b5..00000000000 --- a/gcc/testsuite/gcc.dg/vect/vect-49.c +++ /dev/null @@ -1,61 +0,0 @@ -/* { dg-require-effective-target vect_float } */ - -#include -#include "tree-vect.h" - -#define N 256 - -void bar (float *pa, float *pb, float *pc) -{ - int i; - - /* check results: */ - for (i = 0; i < N; i++) - { - if (pa[i] != (pb[i] * pc[i])) - abort (); - } - - return; -} - -/* Unaligned pointer read accesses, aligned pointer write access. - The loop bound is known and divisible by the vectorization factor. - Can't prove that the pointers don't alias. - vect-53.c is similar to this one with one difference: - the loop bound is unknown. - vect-48.c is similar to this one with one difference: - aliasing is not a problem. */ - -int -main1 (float *pb, float *pc) -{ - float pa[N] __attribute__ ((__aligned__(16))); - int i; - - for (i = 0; i < N; i++) - { - pa[i] = pb[i] * pc[i]; - } - - bar (pa,pb,pc); - - return 0; -} - -int main (void) -{ - int i; - float b[N+1] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60}; - float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; - - check_vect (); - - main1 (b,c); - main1 (&b[1],c); - - return 0; -} - -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ -/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-51.c b/gcc/testsuite/gcc.dg/vect/vect-51.c deleted file mode 100644 index 541a5ffef3b..00000000000 --- a/gcc/testsuite/gcc.dg/vect/vect-51.c +++ /dev/null @@ -1,59 +0,0 @@ -/* { dg-require-effective-target vect_float } */ - -#include -#include "tree-vect.h" - -#define N 256 - -void bar (const float *pa, const float *pb, const float *pc) -{ - int i; - - /* check results: */ - for (i = 0; i < N; i++) - { - if (pa[i] != (pb[i] * pc[i])) - abort (); - } - - return; -} - -/* Unaligned pointer accesses, with unknown alignment. - The loop bound is unknown. - Can't prove that the pointers don't alias. - vect-45.c is similar to this one with one difference: - the loop bound is known. - vect-50.c is similar to this one with one difference: - Aliasing is not a problem. */ - -int -main1 (int n, float *pa, float *pb, float *pc) -{ - int i; - - for (i = 0; i < n; i++) - { - pa[i] = pb[i] * pc[i]; - } - - bar (pa,pb,pc); - - return 0; -} - -int main (void) -{ - int i; - float a[N]; - float b[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57}; - float c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; - - check_vect (); - - main1 (N,a,b,c); - return 0; -} - -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ -/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-53.c b/gcc/testsuite/gcc.dg/vect/vect-53.c deleted file mode 100644 index 91eaabeb93b..00000000000 --- a/gcc/testsuite/gcc.dg/vect/vect-53.c +++ /dev/null @@ -1,62 +0,0 @@ -/* { dg-require-effective-target vect_float } */ - -#include -#include "tree-vect.h" - -#define N 256 - -void bar (const float *pa, const float *pb, const float *pc) -{ - int i; - - /* check results: */ - for (i = 0; i < N; i++) - { - if (pa[i] != (pb[i] * pc[i])) - abort (); - } - - return; -} - -/* Unaligned pointer read accesses, aligned pointer write access. - The loop bound is unknown. - Can't prove that the pointers don't alias. - vect-49.c is similar to this one with one difference: - the loop bound is known. - vect-52.c is similar to this one with one difference: - aliasing is not a problem. */ - -int -main1 (int n, float *pb, float *pc) -{ - float pa[N] __attribute__ ((__aligned__(16))); - int i; - - for (i = 0; i < n; i++) - { - pa[i] = pb[i] * pc[i]; - } - - bar (pa,pb,pc); - - return 0; -} - -int main (void) -{ - int i; - float a[N] __attribute__ ((__aligned__(16))); - float b[N+1] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57,60}; - float c[N+1] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20}; - - check_vect (); - - main1 (N,&b[1],c); - main1 (N,&b[1],&c[1]); - - return 0; -} - -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ -/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-57.c b/gcc/testsuite/gcc.dg/vect/vect-57.c deleted file mode 100644 index bcac95a0393..00000000000 --- a/gcc/testsuite/gcc.dg/vect/vect-57.c +++ /dev/null @@ -1,62 +0,0 @@ -/* { dg-require-effective-target vect_float } */ - -#include -#include "tree-vect.h" - -#define N 256 - -void bar (float *pa, float *pb, float *pc) -{ - int i; - - /* check results: */ - for (i = 0; i < N/2; i++) - { - if (pa[i] != (pb[i+1] * pc[i+1])) - abort (); - } - - return; -} - -/* Unaligned pointer read accesses with known alignment, - and an unaligned write access with unknown alignment. - The loop bound is known and divisible by the vectorization factor. - Can't prove that the pointers don't alias. - vect-61.c is similar to this one with one difference: - the loop bound is unknown. - vect-56.c is similar to this one with two differences: - aliasing is a problem, and the write access is aligned. */ - -int -main1 (float *pa) -{ - int i; - float b[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57}; - float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; - float *pb = b; - float *pc = c; - - for (i = 0; i < N/2; i++) - { - pa[i] = pb[i+1] * pc[i+1]; - } - - bar (pa, pb, pc); - - return 0; -} - -int main (void) -{ - int i; - float a[N] __attribute__ ((__aligned__(16))); - - check_vect (); - main1 (a); - - return 0; -} - -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ -/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-61.c b/gcc/testsuite/gcc.dg/vect/vect-61.c deleted file mode 100644 index 9f4e8e9882b..00000000000 --- a/gcc/testsuite/gcc.dg/vect/vect-61.c +++ /dev/null @@ -1,64 +0,0 @@ -/* { dg-require-effective-target vect_int } */ -/* { dg-require-effective-target vect_float } */ - -#include -#include "tree-vect.h" - -#define N 256 - -void bar (float *pa, float *pb, float *pc) -{ - int i; - - /* check results: */ - for (i = 0; i < N/2; i++) - { - if (pa[i] != (pb[i+1] * pc[i+1])) - abort (); - } - - return; -} - -/* Unaligned pointer read accesses with known alignment, - and an unaligned write access with unknown alignment. - The loop bound is iunknown. - Can't prove that the pointers don't alias. - vect-57.c is similar to this one with one difference: - the loop bound is known. - vect-60.c is similar to this one with two differences: - aliasing is not a problem, and the write access is unaligned. */ - -int -main1 (int n , float *pa) -{ - int i; - float b[N] __attribute__ ((__aligned__(16))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57}; - float c[N] __attribute__ ((__aligned__(16))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19}; - float *pb = b; - float *pc = c; - - for (i = 0; i < n/2; i++) - { - pa[i] = pb[i+1] * pc[i+1]; - } - - bar (pa,pb,pc); - - return 0; -} - -int main (void) -{ - int i; - int n=N; - float a[N] __attribute__ ((__aligned__(16))); - - check_vect (); - main1 (n,a); - - return 0; -} - -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ -/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-79.c b/gcc/testsuite/gcc.dg/vect/vect-79.c deleted file mode 100644 index 8e98e4d0ed9..00000000000 --- a/gcc/testsuite/gcc.dg/vect/vect-79.c +++ /dev/null @@ -1,50 +0,0 @@ -/* { dg-require-effective-target vect_float } */ - -#include -#include "tree-vect.h" - -#define N 16 - -float fa[N] __attribute__ ((__aligned__(16))); -float fb[N+4] __attribute__ ((__aligned__(16))) = {0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 7.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0}; -float fc[N] __attribute__ ((__aligned__(16))) = {0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 7.5, 9.5, 10.5, 11.5, 12.5, 13.5, 14.5, 15.5}; - -/* Like vect-80.c but the pointers are not annotated as restricted, - and therefore can't be antialiased. */ - -int -main1 (float *pa, float *pb, float *pc) -{ - int i; - float *q = pb + 4; - - for (i = 0; i < N; i++) - { - pa[i] = q[i] * pc[i]; - } - - for (i = 0; i < N; i++) - { - if (pa[i] != q[i] * pc[i]) - abort(); - } - - return 0; -} - - -int main (void) -{ - check_vect (); - - main1 (fa, fb, fc); - - return 0; -} - -/* Currently the loops fail to vectorize due to aliasing problems. - If/when the aliasing problems are resolved, unalignment may - prevent vectorization on some targets. */ -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ -/* { dg-final { scan-tree-dump-times "can't determine dependence between" 1 "vect" } } */ -/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-dv-2.c b/gcc/testsuite/gcc.dg/vect/vect-dv-2.c deleted file mode 100644 index 30d229c1996..00000000000 --- a/gcc/testsuite/gcc.dg/vect/vect-dv-2.c +++ /dev/null @@ -1,77 +0,0 @@ -/* { dg-require-effective-target vect_int } */ - -#include -#include -#include "tree-vect.h" - -#define N 64 -#define MAX 42 - -extern void abort(void); - -int main () -{ - int A[N]; - int B[N]; - int C[N]; - int D[N]; - - int i, j; - - check_vect (); - - for (i = 0; i < N; i++) - { - A[i] = i; - B[i] = i; - C[i] = i; - D[i] = i; - } - - /* Vectorizable */ - for (i = 0; i < N-20; i++) - { - A[i] = A[i+20]; - } - - /* check results: */ - for (i = 0; i < N-20; i++) - { - if (A[i] != D[i+20]) - abort (); - } - - /* Vectorizable */ - for (i = 0; i < 16; i++) - { - B[i] = B[i] + 5; - } - - /* check results: */ - for (i = 0; i < 16; i++) - { - if (B[i] != C[i] + 5) - abort (); - } - - /* Not vectorizable */ - for (i = 0; i < 4; i++) - { - C[i] = C[i+3]; - } - - /* check results: */ - for (i = 0; i < 4; i++) - { - if (C[i] != D[i+3]) - abort (); - } - - return 0; -} - - -/* The initialization induction loop (with aligned access) is also vectorized. */ -/* { dg-final { scan-tree-dump-times "vectorized 3 loops" 1 "vect" } } */ -/* { dg-final { scan-tree-dump-times "accesses have the same alignment." 2 "vect" } } */ -/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-vfa-01.c b/gcc/testsuite/gcc.dg/vect/vect-vfa-01.c new file mode 100644 index 00000000000..ea5523ed177 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-vfa-01.c @@ -0,0 +1,39 @@ +/* { dg-require-effective-target vect_int } */ + +#include +#include "tree-vect.h" + +#define N 16 +int result[N] = {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}; +int X[N] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}; +int Y[N] = {}; + +void +foo (int *in, int *out) +{ + int i; + + for (i = 0; i < N; i++) + out[i] = in[i] + 2; +} + +int +main (void) +{ + int i; + + check_vect (); + + foo (X, Y); + + /* check results: */ + for (i = 0; i < N; i++) + { + if (Y[i] != result[i]) + abort (); + } + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-vfa-02.c b/gcc/testsuite/gcc.dg/vect/vect-vfa-02.c new file mode 100644 index 00000000000..80d85a785c6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-vfa-02.c @@ -0,0 +1,47 @@ +/* { dg-require-effective-target vect_int } */ + +#include +#include "tree-vect.h" + +#define N 16 +int resultY[N] = {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27}; +int resultZ[N] = {13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28}; +int X[N] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}; +int Y[N] = {}; +int Z[N] = {}; + +void +foo (int *in, int *out1, int *out2) +{ + int i; + + for (i = 0; i < N; i++) + { + out1[i] = in[i] + 2; + out2[i] = in[i] + 3; + } +} + +int +main (void) +{ + int i; + + check_vect (); + + foo (X, Y, Z); + + /* check results: */ + for (i = 0; i < N; i++) + { + if (Y[i] != resultY[i]) + abort (); + + if (Z[i] != resultZ[i]) + abort (); + } + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-vfa-03.c b/gcc/testsuite/gcc.dg/vect/vect-vfa-03.c new file mode 100644 index 00000000000..aa001bf4d6f --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-vfa-03.c @@ -0,0 +1,58 @@ +/* { dg-require-effective-target vect_int } */ + +#include +#include "tree-vect.h" + +#define N 16 +struct S +{ + unsigned short a; + unsigned short b; +}; + +struct S result[N] = {12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, + 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, + 24, 25, 25, 26, 26, 27, 27, 28}; +struct S X[N] = {10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, + 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25}; +struct S Y[N] = {}; + +void +foo (struct S * in, struct S * out) +{ + int i; + + for (i = 0; i < N; i++) + { + out[i].a = in[i].a + 2; + out[i].b = in[i].b + 3; + } +} + +int +main (void) +{ + int i; + + check_vect (); + + foo (X, Y); + + /* check results: */ + for (i = 0; i < N; i++) + { + if (Y[i].a != result[i].a) + abort (); + + if (Y[i].b != result[i].b) + abort (); + + } + return 0; +} + +/* Needs interleaving support. */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_interleave && vect_extract_even_odd } } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 0 "vect" { xfail { vect_interleave && vect_extract_even_odd } } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-vfa-04.c b/gcc/testsuite/gcc.dg/vect/vect-vfa-04.c new file mode 100644 index 00000000000..e43df0086c0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-vfa-04.c @@ -0,0 +1,38 @@ +/* { dg-require-effective-target vect_int } */ + +#include +#include "tree-vect.h" + +#define N 16 +int result[] = {10, 11, 15, 16, 20, 21, 25, 26, 30, 31, 35, 36, 40, 41, 45, 46, 50, 51}; +int X[] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0}; + +void +foo (int *in, int *out) +{ + int i; + + for (i = 0; i < N; i++) + out[i] = in[i] + 5; +} + +int +main (void) +{ + int i; + + check_vect (); + + foo (X, &X[2]); + + /* check results: */ + for (i = 0; i < N+2; i++) + { + if (X[i] != result[i]) + abort (); + } + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect.exp b/gcc/testsuite/gcc.dg/vect/vect.exp index 88ce4d9f483..2208f727d1e 100644 --- a/gcc/testsuite/gcc.dg/vect/vect.exp +++ b/gcc/testsuite/gcc.dg/vect/vect.exp @@ -113,6 +113,12 @@ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/vect-*.\[cS\]]] \ global SAVED_DEFAULT_VECTCFLAGS set SAVED_DEFAULT_VECTCFLAGS $DEFAULT_VECTCFLAGS +# --param vect-max-version-for-alias-checks=0 tests +set DEFAULT_VECTCFLAGS $SAVED_DEFAULT_VECTCFLAGS +lappend DEFAULT_VECTCFLAGS "--param" "vect-max-version-for-alias-checks=0" +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/no-vfa-*.\[cS\]]] \ + "" $DEFAULT_VECTCFLAGS + # -ffast-math tests set DEFAULT_VECTCFLAGS $SAVED_DEFAULT_VECTCFLAGS lappend DEFAULT_VECTCFLAGS "-ffast-math" diff --git a/gcc/testsuite/gfortran.dg/vect/no-vfa-pr32457.f90 b/gcc/testsuite/gfortran.dg/vect/no-vfa-pr32457.f90 new file mode 100644 index 00000000000..07a2b6056fb --- /dev/null +++ b/gcc/testsuite/gfortran.dg/vect/no-vfa-pr32457.f90 @@ -0,0 +1,15 @@ +! { dg-do compile } +! { dg-require-effective-target vect_float } + +SUBROUTINE KEEL(RBOUND) + REAL, DIMENSION(0:100) :: RBOUND + DO N = 1, NP1 + RBOUND(N) = RBOUND(N-1) + 1 + END DO + DO N = 1, NS + WRITE (16,'(I5)') SRAD(N) + END DO +END SUBROUTINE KEEL + +! { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" } } +! { dg-final { cleanup-tree-dump "vect" } } diff --git a/gcc/testsuite/gfortran.dg/vect/pr32457.f90 b/gcc/testsuite/gfortran.dg/vect/pr32457.f90 deleted file mode 100644 index 07a2b6056fb..00000000000 --- a/gcc/testsuite/gfortran.dg/vect/pr32457.f90 +++ /dev/null @@ -1,15 +0,0 @@ -! { dg-do compile } -! { dg-require-effective-target vect_float } - -SUBROUTINE KEEL(RBOUND) - REAL, DIMENSION(0:100) :: RBOUND - DO N = 1, NP1 - RBOUND(N) = RBOUND(N-1) + 1 - END DO - DO N = 1, NS - WRITE (16,'(I5)') SRAD(N) - END DO -END SUBROUTINE KEEL - -! { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" } } -! { dg-final { cleanup-tree-dump "vect" } } diff --git a/gcc/testsuite/gfortran.dg/vect/vect.exp b/gcc/testsuite/gfortran.dg/vect/vect.exp index 6a72e57ef02..3cc41c70482 100644 --- a/gcc/testsuite/gfortran.dg/vect/vect.exp +++ b/gcc/testsuite/gfortran.dg/vect/vect.exp @@ -90,7 +90,18 @@ proc check_effective_target_lp64_or_vect_no_align { } { dg-init # Main loop. -gfortran-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[fF\]{,90,95,03} ]] $DEFAULT_VECTCFLAGS +gfortran-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/vect-*.\[fF\]{,90,95,03} ]] $DEFAULT_VECTCFLAGS +gfortran-dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/pr-*.\[fF\]{,90,95,03} ]] $DEFAULT_VECTCFLAGS + +#### Tests with special options +global SAVED_DEFAULT_VECTCFLAGS +set SAVED_DEFAULT_VECTCFLAGS $DEFAULT_VECTCFLAGS + +# --param vect-max-version-for-alias-checks=0 tests +set DEFAULT_VECTCFLAGS $SAVED_DEFAULT_VECTCFLAGS +lappend DEFAULT_VECTCFLAGS "--param" "vect-max-version-for-alias-checks=0" +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/no-vfa-*.\[fF\]{,90,95,03} ]] \ + "" $DEFAULT_VECTCFLAGS # Clean up. set dg-do-what-default ${save-dg-do-what-default} diff --git a/gcc/tree-vect-analyze.c b/gcc/tree-vect-analyze.c index 3e2b4c73fd8..cc43ad61aef 100644 --- a/gcc/tree-vect-analyze.c +++ b/gcc/tree-vect-analyze.c @@ -1039,10 +1039,10 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know) { - if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS)) + if (vect_print_dump_info (REPORT_DR_DETAILS)) { fprintf (vect_dump, - "not vectorized: can't determine dependence between "); + "versioning for alias required: can't determine dependence between "); print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM); fprintf (vect_dump, " and "); print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM); @@ -1052,9 +1052,9 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, if (DDR_NUM_DIST_VECTS (ddr) == 0) { - if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS)) + if (vect_print_dump_info (REPORT_DR_DETAILS)) { - fprintf (vect_dump, "not vectorized: bad dist vector for "); + fprintf (vect_dump, "versioning for alias required: bad dist vector for "); print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM); fprintf (vect_dump, " and "); print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM); @@ -1108,10 +1108,11 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, continue; } - if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS)) + if (vect_print_dump_info (REPORT_DR_DETAILS)) { fprintf (vect_dump, - "not vectorized: possible dependence between data-refs "); + "versioning for alias required: possible dependence " + "between data-refs "); print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM); fprintf (vect_dump, " and "); print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM); @@ -1123,6 +1124,77 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr, return false; } +/* Return TRUE if DDR_NEW is already found in MAY_ALIAS_DDRS list. */ + +static bool +vect_is_duplicate_ddr (VEC (ddr_p, heap) * may_alias_ddrs, ddr_p ddr_new) +{ + unsigned i; + ddr_p ddr; + + for (i = 0; VEC_iterate (ddr_p, may_alias_ddrs, i, ddr); i++) + { + tree dref_A_i, dref_B_i, dref_A_j, dref_B_j; + + dref_A_i = DR_REF (DDR_A (ddr)); + dref_B_i = DR_REF (DDR_B (ddr)); + dref_A_j = DR_REF (DDR_A (ddr_new)); + dref_B_j = DR_REF (DDR_B (ddr_new)); + + if ((operand_equal_p (dref_A_i, dref_A_j, 0) + && operand_equal_p (dref_B_i, dref_B_j, 0)) + || (operand_equal_p (dref_A_i, dref_B_j, 0) + && operand_equal_p (dref_B_i, dref_A_j, 0))) + { + if (vect_print_dump_info (REPORT_DR_DETAILS)) + { + fprintf (vect_dump, "found same pair of data references "); + print_generic_expr (vect_dump, dref_A_i, TDF_SLIM); + fprintf (vect_dump, " and "); + print_generic_expr (vect_dump, dref_B_i, TDF_SLIM); + } + return true; + } + } + return false; +} + +/* Save DDR in LOOP_VINFO list of ddrs that may alias and need to be + tested at run-time. Returns false if number of run-time checks + inserted by vectorizer is greater than maximum defined by + PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS. */ +static bool +vect_mark_for_runtime_alias_test (ddr_p ddr, loop_vec_info loop_vinfo) +{ + if (vect_print_dump_info (REPORT_DR_DETAILS)) + { + fprintf (vect_dump, "mark for run-time aliasing test between "); + print_generic_expr (vect_dump, DR_REF (DDR_A (ddr)), TDF_SLIM); + fprintf (vect_dump, " and "); + print_generic_expr (vect_dump, DR_REF (DDR_B (ddr)), TDF_SLIM); + } + + /* Do not add to the list duplicate ddrs. */ + if (vect_is_duplicate_ddr (LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo), ddr)) + return true; + + if (VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)) + >= (unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS)) + { + if (vect_print_dump_info (REPORT_DR_DETAILS)) + { + fprintf (vect_dump, + "disable versioning for alias - max number of generated " + "checks exceeded."); + } + + VEC_truncate (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo), 0); + + return false; + } + VEC_safe_push (ddr_p, heap, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo), ddr); + return true; +} /* Function vect_analyze_data_ref_dependences. @@ -1133,7 +1205,7 @@ static bool vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo) { unsigned int i; - VEC (ddr_p, heap) *ddrs = LOOP_VINFO_DDRS (loop_vinfo); + VEC (ddr_p, heap) * ddrs = LOOP_VINFO_DDRS (loop_vinfo); struct data_dependence_relation *ddr; if (vect_print_dump_info (REPORT_DETAILS)) @@ -1141,7 +1213,11 @@ vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo) for (i = 0; VEC_iterate (ddr_p, ddrs, i, ddr); i++) if (vect_analyze_data_ref_dependence (ddr, loop_vinfo)) + { + /* Add to list of ddrs that need to be tested at run-time. */ + if (!vect_mark_for_runtime_alias_test (ddr, loop_vinfo)) return false; + } return true; } @@ -1554,6 +1630,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) bool stat; tree stmt; stmt_vec_info stmt_info; + int vect_versioning_for_alias_required; if (vect_print_dump_info (REPORT_DETAILS)) fprintf (vect_dump, "=== vect_enhance_data_refs_alignment ==="); @@ -1619,9 +1696,15 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) } } - /* Often peeling for alignment will require peeling for loop-bound, which in - turn requires that we know how to adjust the loop ivs after the loop. */ - if (!vect_can_advance_ivs_p (loop_vinfo) + vect_versioning_for_alias_required = + (VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)) > 0); + + /* Temporarily, if versioning for alias is required, we disable peeling + until we support peeling and versioning. Often peeling for alignment + will require peeling for loop-bound, which in turn requires that we + know how to adjust the loop ivs after the loop. */ + if (vect_versioning_for_alias_required + || !vect_can_advance_ivs_p (loop_vinfo) || !slpeel_can_duplicate_loop_p (loop, single_exit (loop))) do_peeling = false; @@ -1749,7 +1832,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo) if (known_alignment_for_access_p (dr) || VEC_length (tree, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo)) - >= (unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_CHECKS)) + >= (unsigned) PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS)) { do_versioning = false; break; diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c index 8316aab9e86..16beffceef5 100644 --- a/gcc/tree-vect-transform.c +++ b/gcc/tree-vect-transform.c @@ -5805,6 +5805,146 @@ vect_create_cond_for_align_checks (loop_vec_info loop_vinfo, and_tmp_name, ptrsize_zero); } +/* Function vect_vfa_segment_size. + + Create an expression that computes the size of segment + that will be accessed for a data reference. The functions takes into + account that realignment loads may access one more vector. + + Input: + DR: The data reference. + VECT_FACTOR: vectorization factor. + + Return an exrpession whose value is the size of segment which will be + accessed by DR. */ + +static tree +vect_vfa_segment_size (struct data_reference *dr, tree vect_factor) +{ + tree segment_length; + + if (vect_supportable_dr_alignment (dr) == dr_unaligned_software_pipeline) + { + tree vector_size = + build_int_cst (integer_type_node, + GET_MODE_SIZE (TYPE_MODE (STMT_VINFO_VECTYPE + (vinfo_for_stmt (DR_STMT (dr)))))); + + segment_length = + fold_convert (sizetype, + fold_build2 (PLUS_EXPR, integer_type_node, + fold_build2 (MULT_EXPR, integer_type_node, DR_STEP (dr), + vect_factor), + vector_size)); + + + } + else + { + segment_length = + fold_convert (sizetype, + fold_build2 (MULT_EXPR, integer_type_node, DR_STEP (dr), + vect_factor)); + } + + return segment_length; +} + +/* Function vect_create_cond_for_alias_checks. + + Create a conditional expression that represents the run-time checks for + overlapping of address ranges represented by a list of data references + relations passed as input. + + Input: + COND_EXPR - input conditional expression. New conditions will be chained + with logical and operation. + LOOP_VINFO - field LOOP_VINFO_MAY_ALIAS_STMTS contains the list of ddrs + to be checked. + + Output: + COND_EXPR - conditional expression. + COND_EXPR_STMT_LIST - statements needed to construct the conditional + expression. + The returned value is the conditional expression to be used in the if + statement that controls which version of the loop gets executed at runtime. +*/ + +static void +vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo, + tree * cond_expr, + tree * cond_expr_stmt_list) +{ + VEC (ddr_p, heap) * may_alias_ddrs = + LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo); + tree vect_factor = + build_int_cst (integer_type_node, LOOP_VINFO_VECT_FACTOR (loop_vinfo)); + + ddr_p ddr; + unsigned int i; + tree part_cond_expr; + + /* Create expression + ((store_ptr_0 + store_segment_length_0) < load_ptr_0) + || (load_ptr_0 + load_segment_length_0) < store_ptr_0)) + && + ... + && + ((store_ptr_n + store_segment_length_n) < load_ptr_n) + || (load_ptr_n + load_segment_length_n) < store_ptr_n)) */ + + if (VEC_empty (ddr_p, may_alias_ddrs)) + return; + + for (i = 0; VEC_iterate (ddr_p, may_alias_ddrs, i, ddr); i++) + { + tree stmt_a = DR_STMT (DDR_A (ddr)); + tree stmt_b = DR_STMT (DDR_B (ddr)); + + tree addr_base_a = + vect_create_addr_base_for_vector_ref (stmt_a, cond_expr_stmt_list, + NULL_TREE); + tree addr_base_b = + vect_create_addr_base_for_vector_ref (stmt_b, cond_expr_stmt_list, + NULL_TREE); + + tree segment_length_a = vect_vfa_segment_size (DDR_A (ddr), vect_factor); + tree segment_length_b = vect_vfa_segment_size (DDR_B (ddr), vect_factor); + + if (vect_print_dump_info (REPORT_DR_DETAILS)) + { + fprintf (vect_dump, + "create runtime check for data references "); + print_generic_expr (vect_dump, DR_REF (DDR_A (ddr)), TDF_SLIM); + fprintf (vect_dump, " and "); + print_generic_expr (vect_dump, DR_REF (DDR_B (ddr)), TDF_SLIM); + } + + + part_cond_expr = + fold_build2 (TRUTH_OR_EXPR, boolean_type_node, + fold_build2 (LT_EXPR, boolean_type_node, + fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (addr_base_a), + addr_base_a, + segment_length_a), + addr_base_b), + fold_build2 (LT_EXPR, boolean_type_node, + fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (addr_base_b), + addr_base_b, + segment_length_b), + addr_base_a)); + + if (*cond_expr) + *cond_expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, + *cond_expr, part_cond_expr); + else + *cond_expr = part_cond_expr; + } + if (vect_print_dump_info (REPORT_VECTORIZED_LOOPS)) + fprintf (vect_dump, "created %u versioning for alias checks.\n", + VEC_length (ddr_p, may_alias_ddrs)); + +} /* Function vect_transform_loop. @@ -5827,16 +5967,21 @@ vect_transform_loop (loop_vec_info loop_vinfo) if (vect_print_dump_info (REPORT_DETAILS)) fprintf (vect_dump, "=== vec_transform_loop ==="); - /* If the loop has data references that may or may not be aligned then + /* If the loop has data references that may or may not be aligned or/and + has data reference relations whose independence was not proven then two versions of the loop need to be generated, one which is vectorized and one which isn't. A test is then generated to control which of the loops is executed. The test checks for the alignment of all of the - data references that may or may not be aligned. */ + data references that may or may not be aligned. An additional + sequence of runtime tests is generated for each pairs of DDRs whose + independence was not proven. The vectorized version of loop is + executed only if both alias and alignment tests are passed. */ - if (VEC_length (tree, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))) + if (VEC_length (tree, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo)) + || VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo))) { struct loop *nloop; - tree cond_expr; + tree cond_expr = NULL_TREE; tree cond_expr_stmt_list = NULL_TREE; basic_block condition_bb; block_stmt_iterator cond_exp_bsi; @@ -5845,9 +5990,23 @@ vect_transform_loop (loop_vec_info loop_vinfo) edge new_exit_e, e; tree orig_phi, new_phi, arg; unsigned prob = 4 * REG_BR_PROB_BASE / 5; + tree gimplify_stmt_list; - cond_expr = vect_create_cond_for_align_checks (loop_vinfo, + if (VEC_length (tree, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))) + cond_expr = + vect_create_cond_for_align_checks (loop_vinfo, &cond_expr_stmt_list); + + if (VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo))) + vect_create_cond_for_alias_checks (loop_vinfo, &cond_expr, &cond_expr_stmt_list); + + cond_expr = + fold_build2 (NE_EXPR, boolean_type_node, cond_expr, integer_zero_node); + cond_expr = + force_gimple_operand (cond_expr, &gimplify_stmt_list, true, + NULL_TREE); + append_to_statement_list (gimplify_stmt_list, &cond_expr_stmt_list); + initialize_original_copy_tables (); nloop = loop_version (loop, cond_expr, &condition_bb, prob, prob, REG_BR_PROB_BASE - prob, true); diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 6834e25684e..6dc0c727c0c 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -1414,8 +1414,11 @@ new_loop_vec_info (struct loop *loop) LOOP_VINFO_DATAREFS (res) = VEC_alloc (data_reference_p, heap, 10); LOOP_VINFO_DDRS (res) = VEC_alloc (ddr_p, heap, 10 * 10); LOOP_VINFO_UNALIGNED_DR (res) = NULL; - LOOP_VINFO_MAY_MISALIGN_STMTS (res) - = VEC_alloc (tree, heap, PARAM_VALUE (PARAM_VECT_MAX_VERSION_CHECKS)); + LOOP_VINFO_MAY_MISALIGN_STMTS (res) = + VEC_alloc (tree, heap, PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIGNMENT_CHECKS)); + LOOP_VINFO_MAY_ALIAS_DDRS (res) = + VEC_alloc (ddr_p, heap, PARAM_VALUE (PARAM_VECT_MAX_VERSION_FOR_ALIAS_CHECKS)); + return res; } @@ -1495,6 +1498,7 @@ destroy_loop_vec_info (loop_vec_info loop_vinfo) free_data_refs (LOOP_VINFO_DATAREFS (loop_vinfo)); free_dependence_relations (LOOP_VINFO_DDRS (loop_vinfo)); VEC_free (tree, heap, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo)); + VEC_free (ddr_p, heap, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)); free (loop_vinfo); loop->aux = NULL; diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index 40f22056ee9..d96b9443b96 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -133,6 +133,10 @@ typedef struct _loop_vec_info { /* All data dependences in the loop. */ VEC (ddr_p, heap) *ddrs; + /* Data Dependence Relations defining address ranges that are candidates + for a run-time aliasing check. */ + VEC (ddr_p, heap) *may_alias_ddrs; + /* Statements in the loop that have data references that are candidates for a runtime (loop versioning) misalignment check. */ VEC(tree,heap) *may_misalign_stmts; @@ -157,6 +161,7 @@ typedef struct _loop_vec_info { #define LOOP_VINFO_UNALIGNED_DR(L) (L)->unaligned_dr #define LOOP_VINFO_MAY_MISALIGN_STMTS(L) (L)->may_misalign_stmts #define LOOP_VINFO_LOC(L) (L)->loop_line_number +#define LOOP_VINFO_MAY_ALIAS_DDRS(L) (L)->may_alias_ddrs #define NITERS_KNOWN_P(n) \ (host_integerp ((n),0) \