diff options
-rw-r--r-- | gcc/ChangeLog | 33 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 13 | ||||
-rw-r--r-- | gcc/params.def | 11 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/no-vfa-pr29145.c (renamed from gcc/testsuite/gcc.dg/vect/pr29145.c) | 0 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/no-vfa-vect-101.c (renamed from gcc/testsuite/gcc.dg/vect/vect-101.c) | 0 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/no-vfa-vect-102.c (renamed from gcc/testsuite/gcc.dg/vect/vect-102.c) | 0 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/no-vfa-vect-102a.c (renamed from gcc/testsuite/gcc.dg/vect/vect-102a.c) | 0 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/no-vfa-vect-37.c (renamed from gcc/testsuite/gcc.dg/vect/vect-37.c) | 0 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/no-vfa-vect-43.c (renamed from gcc/testsuite/gcc.dg/vect/vect-43.c) | 0 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/no-vfa-vect-45.c (renamed from gcc/testsuite/gcc.dg/vect/vect-45.c) | 0 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/no-vfa-vect-49.c (renamed from gcc/testsuite/gcc.dg/vect/vect-49.c) | 0 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/no-vfa-vect-51.c (renamed from gcc/testsuite/gcc.dg/vect/vect-51.c) | 0 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/no-vfa-vect-53.c (renamed from gcc/testsuite/gcc.dg/vect/vect-53.c) | 0 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/no-vfa-vect-57.c (renamed from gcc/testsuite/gcc.dg/vect/vect-57.c) | 0 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/no-vfa-vect-61.c (renamed from gcc/testsuite/gcc.dg/vect/vect-61.c) | 0 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/no-vfa-vect-79.c (renamed from gcc/testsuite/gcc.dg/vect/vect-79.c) | 0 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/no-vfa-vect-dv-2.c (renamed from gcc/testsuite/gcc.dg/vect/vect-dv-2.c) | 0 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-vfa-01.c | 39 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-vfa-02.c | 47 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-vfa-03.c | 58 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-vfa-04.c | 38 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect.exp | 6 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/vect/no-vfa-pr32457.f90 (renamed from gcc/testsuite/gfortran.dg/vect/pr32457.f90) | 0 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/vect/vect.exp | 13 | ||||
-rw-r--r-- | gcc/tree-vect-analyze.c | 105 | ||||
-rw-r--r-- | gcc/tree-vect-transform.c | 169 | ||||
-rw-r--r-- | gcc/tree-vectorizer.c | 8 | ||||
-rw-r--r-- | gcc/tree-vectorizer.h | 5 |
29 files changed, 538 insertions, 26 deletions
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 <victork@il.ibm.com> + + * 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 <ubizjak@gmail.com> * 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 <victork@il.ibm.com> + + * 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 <richard@codesourcery.com> * gcc.dg/torture/pr32897.c: New test. diff --git a/gcc/testsuite/gcc.dg/vect/pr29145.c b/gcc/testsuite/gcc.dg/vect/no-vfa-pr29145.c index 97d190ca278..97d190ca278 100644 --- a/gcc/testsuite/gcc.dg/vect/pr29145.c +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-pr29145.c diff --git a/gcc/testsuite/gcc.dg/vect/vect-101.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-101.c index e195a58af5f..e195a58af5f 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-101.c +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-101.c diff --git a/gcc/testsuite/gcc.dg/vect/vect-102.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-102.c index 49df4f9bc90..49df4f9bc90 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-102.c +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-102.c diff --git a/gcc/testsuite/gcc.dg/vect/vect-102a.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-102a.c index 35023fc65dc..35023fc65dc 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-102a.c +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-102a.c diff --git a/gcc/testsuite/gcc.dg/vect/vect-37.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-37.c index e54e0c5166c..e54e0c5166c 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-37.c +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-37.c diff --git a/gcc/testsuite/gcc.dg/vect/vect-43.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-43.c index 258da2827f7..258da2827f7 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-43.c +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-43.c diff --git a/gcc/testsuite/gcc.dg/vect/vect-45.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-45.c index 8a998564319..8a998564319 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-45.c +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-45.c diff --git a/gcc/testsuite/gcc.dg/vect/vect-49.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-49.c index 8dfd0e749b5..8dfd0e749b5 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-49.c +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-49.c diff --git a/gcc/testsuite/gcc.dg/vect/vect-51.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-51.c index 541a5ffef3b..541a5ffef3b 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-51.c +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-51.c diff --git a/gcc/testsuite/gcc.dg/vect/vect-53.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-53.c index 91eaabeb93b..91eaabeb93b 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-53.c +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-53.c diff --git a/gcc/testsuite/gcc.dg/vect/vect-57.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-57.c index bcac95a0393..bcac95a0393 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-57.c +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-57.c diff --git a/gcc/testsuite/gcc.dg/vect/vect-61.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-61.c index 9f4e8e9882b..9f4e8e9882b 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-61.c +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-61.c diff --git a/gcc/testsuite/gcc.dg/vect/vect-79.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-79.c index 8e98e4d0ed9..8e98e4d0ed9 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-79.c +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-79.c diff --git a/gcc/testsuite/gcc.dg/vect/vect-dv-2.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-dv-2.c index 30d229c1996..30d229c1996 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-dv-2.c +++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-dv-2.c 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 <stdarg.h> +#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 <stdarg.h> +#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 <stdarg.h> +#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 <stdarg.h> +#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/pr32457.f90 b/gcc/testsuite/gfortran.dg/vect/no-vfa-pr32457.f90 index 07a2b6056fb..07a2b6056fb 100644 --- a/gcc/testsuite/gfortran.dg/vect/pr32457.f90 +++ b/gcc/testsuite/gfortran.dg/vect/no-vfa-pr32457.f90 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) \ |