diff options
author | Dorit Nuzman <dorit@il.ibm.com> | 2007-02-06 10:08:51 +0000 |
---|---|---|
committer | Dorit Nuzman <dorit@gcc.gnu.org> | 2007-02-06 10:08:51 +0000 |
commit | fbf798fcc5f1a456213c99d59df41adaf38ad4d8 (patch) | |
tree | 3e78c2931f5a1e916ecd248c65d21ec69fd56509 /gcc | |
parent | 426147a1e8ca92e3c32168f50dc9a2d04825c42c (diff) | |
download | gcc-fbf798fcc5f1a456213c99d59df41adaf38ad4d8.zip gcc-fbf798fcc5f1a456213c99d59df41adaf38ad4d8.tar.gz gcc-fbf798fcc5f1a456213c99d59df41adaf38ad4d8.tar.bz2 |
tree-vectorizer.c (vect_is_simple_use): Support induction.
2007-02-06 Dorit Nuzman <dorit@il.ibm.com>
Victor Kaplansky <victork@il.ibm.com>
* tree-vectorizer.c (vect_is_simple_use): Support induction.
(vect_is_simple_reduction): Support reduction with induction as
one of the operands.
(vect_is_simple_iv_evolution): Fix formatting.
* tree-vect-analyze.c (vect_mark_stmts_to_be_vectorized): Fix
formatting. Don't mark induction phis for vectorization.
(vect_analyze_scalar_cycles): Analyze all inductions, then reductions.
* tree-vect-transform.c (get_initial_def_for_induction): New function.
(vect_get_vec_def_for_operand): Support induction.
(vect_get_vec_def_for_stmt_copy): Fix formatting and add check for
induction case.
(vectorizable_reduction): Support reduction with induction as one of
the operands.
(vectorizable_type_demotion): Use def-type of stmt argument rather
than dummy def-type.
* tree-ssa-loop.c (gate_scev_const_prop): Return the value of
flag_tree_scev_cprop.
* common.opt (tree-scev-cprop): New flag.
* tree-vect-transform.c (vect_create_destination_var): Use 'kind' in
call to vect_get_new_vect_var.
Co-Authored-By: Victor Kaplansky <victork@il.ibm.com>
From-SVN: r121643
Diffstat (limited to 'gcc')
29 files changed, 892 insertions, 88 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9207c8e..8badc16 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2007-02-06 Dorit Nuzman <dorit@il.ibm.com> + Victor Kaplansky <victork@il.ibm.com> + + * tree-vectorizer.c (vect_is_simple_use): Support induction. + (vect_is_simple_reduction): Support reduction with induction as + one of the operands. + (vect_is_simple_iv_evolution): Fix formatting. + * tree-vect-analyze.c (vect_mark_stmts_to_be_vectorized): Fix + formatting. Don't mark induction phis for vectorization. + (vect_analyze_scalar_cycles): Analyze all inductions, then reductions. + * tree-vect-transform.c (get_initial_def_for_induction): New function. + (vect_get_vec_def_for_operand): Support induction. + (vect_get_vec_def_for_stmt_copy): Fix formatting and add check for + induction case. + (vectorizable_reduction): Support reduction with induction as one of + the operands. + (vectorizable_type_demotion): Use def-type of stmt argument rather + than dummy def-type. + + * tree-ssa-loop.c (gate_scev_const_prop): Return the value of + flag_tree_scev_cprop. + * common.opt (tree-scev-cprop): New flag. + + * tree-vect-transform.c (vect_create_destination_var): Use 'kind' in + call to vect_get_new_vect_var. + 2007-02-06 Ira Rosen <irar@il.ibm.com> * tree-vect-patterns.c (vect_recog_widen_mult_pattern): Check that diff --git a/gcc/common.opt b/gcc/common.opt index 0f1020c..cfb7967 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1080,6 +1080,10 @@ ftree-vectorizer-verbose= Common RejectNegative Joined -ftree-vectorizer-verbose=<number> Set the verbosity level of the vectorizer +ftree-scev-cprop +Common Report Var(flag_tree_scev_cprop) Init(1) +Enable copy propagation of scalar-evolution information. + ; -fverbose-asm causes extra commentary information to be produced in ; the generated assembly code (to make it more readable). This option ; is generally only of use to those who actually need to read the diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3f676a8..d86d872 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,28 @@ +2007-02-06 Dorit Nuzman <dorit@il.ibm.com> + + * gcc.dg/vect/vect.exp: Add support for -fno-tree-scev-cprop tests. + * gcc.dg/vect/vect-iv-1.c: New test. + * gcc.dg/vect/vect-iv-2.c: New test. + * gcc.dg/vect/vect-iv-3.c: New test. + * gcc.dg/vect/vect-iv-4.c: New test. + * gcc.dg/vect/vect-iv-5.c: New test. + * gcc.dg/vect/vect-iv-6.c: New test. + * gcc.dg/vect/vect-iv-7.c: New test. + * gcc.dg/vect/vect-iv-8.c: New test. + * gcc.dg/vect/vect-iv-9.c: New test. + * gcc.dg/vect/vect-iv-10.c: New test. + * gcc.dg/vect/vect-iv-11.c: New test. + * gcc.dg/vect/no-tree-scev-cprop-vect-iv-1.c: New test. + * gcc.dg/vect/no-tree-scev-cprop-vect-iv-2.c: New test. + * gcc.dg/vect/vect-14.c: Now vectorizable. + * gcc.dg/vect/pr21591.c: Additional loop vectorized (initilization loop). + * gcc.dg/vect/vect-27.c: Likewise. + * gcc.dg/vect/vect-29.c Likewise. + * gcc.dg/vect/vect-dv-2.c: Likewise. + * gcc.dg/vect/vect-reduc-dot-u16a.c: Likewise. + * gcc.dg/vect/vect-reduc-dot-u16b.c: Likewise. + * gcc.dg/vect/vect-widen-mult-u16.c: Likewise. + 2007-02-06 Ira Rosen <irar@il.ibm.com> * gcc.dg/vect/fast-math-vect-pow-2.c: New test. diff --git a/gcc/testsuite/gcc.dg/vect/no-tree-scev-cprop-vect-iv-1.c b/gcc/testsuite/gcc.dg/vect/no-tree-scev-cprop-vect-iv-1.c new file mode 100644 index 0000000..60c6ff5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-tree-scev-cprop-vect-iv-1.c @@ -0,0 +1,34 @@ +/* { dg-require-effective-target vect_int } */ + +#include <stdarg.h> +#include "tree-vect.h" + +#define N 26 + +int main1 (int X) +{ + int s = X; + int i; + + /* vectorization of reduction with induction. + Need -fno-tree-scev-cprop or else the loop is eliminated. */ + for (i = 0; i < N; i++) + s += i; + + return s; +} + +int main (void) +{ + int s; + check_vect (); + + s = main1 (3); + if (s != 328) + 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/no-tree-scev-cprop-vect-iv-2.c b/gcc/testsuite/gcc.dg/vect/no-tree-scev-cprop-vect-iv-2.c new file mode 100644 index 0000000..5e1c7b8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/no-tree-scev-cprop-vect-iv-2.c @@ -0,0 +1,49 @@ +/* { dg-require-effective-target vect_int } */ + +#include <stdarg.h> +#include "tree-vect.h" + +#define N 16 + +int main1 () +{ + int arr1[N]; + int k = 0; + int m = 3, i = 0; + + /* Vectorization of induction that is used after the loop. + Currently vectorizable because scev_ccp disconnects the + use-after-the-loop from the iv def inside the loop. */ + + do { + k = k + 2; + arr1[i] = k; + m = m + k; + i++; + } while (i < N); + + /* check results: */ + for (i = 0; i < N; i++) + { + if (arr1[i] != 2+2*i) + abort (); + } + + return m + k; +} + +int main (void) +{ + int res; + + check_vect (); + + res = main1 (); + if (res != 32 + 275) + abort (); + + 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/pr21591.c b/gcc/testsuite/gcc.dg/vect/pr21591.c index 8a8e30f..0a665b6 100644 --- a/gcc/testsuite/gcc.dg/vect/pr21591.c +++ b/gcc/testsuite/gcc.dg/vect/pr21591.c @@ -30,6 +30,6 @@ void f(void) free(c); } -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ +/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */ /* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-14.c b/gcc/testsuite/gcc.dg/vect/vect-14.c index 2507884..cb04076 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-14.c +++ b/gcc/testsuite/gcc.dg/vect/vect-14.c @@ -10,8 +10,7 @@ int main1 () int i; int ia[N]; - - /* Not vectorizable yet (induction). */ + /* Induction. */ for ( i = 0; i < N; i++) { ia[i] = i; } @@ -33,5 +32,5 @@ int main (void) return main1 (); } -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ +/* { 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-27.c b/gcc/testsuite/gcc.dg/vect/vect-27.c index 3b0be9c..9faf776 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-27.c +++ b/gcc/testsuite/gcc.dg/vect/vect-27.c @@ -40,7 +40,9 @@ int main (void) return main1 (); } -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_align } } } */ +/* The initialization induction loop (with aligned access) is also vectorized. */ +/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { xfail vect_no_align } } } */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target vect_no_align } } } */ /* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 1 "vect" { xfail vect_no_align } } } */ /* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 0 "vect" } } */ /* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-29.c b/gcc/testsuite/gcc.dg/vect/vect-29.c index ac39814..eef68e4 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-29.c +++ b/gcc/testsuite/gcc.dg/vect/vect-29.c @@ -46,7 +46,8 @@ int main (void) /* For targets that don't support misaligned loads we version for the load. (The store is aligned). */ -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ +/* The initialization induction loop (with aligned access) is also vectorized. */ +/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */ /* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 1 "vect" { xfail vect_no_align } } } */ /* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 0 "vect" } } */ /* { dg-final { scan-tree-dump-times "Alignment of access forced using versioning." 1 "vect" {target vect_no_align } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-dv-2.c b/gcc/testsuite/gcc.dg/vect/vect-dv-2.c index 4822fcf..30d229c 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-dv-2.c +++ b/gcc/testsuite/gcc.dg/vect/vect-dv-2.c @@ -71,7 +71,7 @@ int main () } - -/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */ +/* 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-iv-1.c b/gcc/testsuite/gcc.dg/vect/vect-iv-1.c new file mode 100644 index 0000000..4bd082a --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-iv-1.c @@ -0,0 +1,42 @@ +/* { dg-require-effective-target vect_int } */ + +#include <stdarg.h> +#include "tree-vect.h" + +#define N 16 +int result[N] = {8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38}; + +int main1 (int X) +{ + int arr[N]; + int k = X; + int m, i=0; + + /* vectorization of induction. */ + + do { + m = k + 5; + arr[i] = m; + k = k + 2; + i++; + } while (i < N); + + /* check results: */ + for (i = 0; i < N; i++) + { + if (arr[i] != result[i]) + abort (); + } + + return 0; +} + +int main (void) +{ + check_vect (); + + return main1 (3); +} + +/* { 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-iv-10.c b/gcc/testsuite/gcc.dg/vect/vect-iv-10.c new file mode 100644 index 0000000..e424200 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-iv-10.c @@ -0,0 +1,35 @@ +/* { dg-require-effective-target vect_int } */ + +#include <stdarg.h> +#include "tree-vect.h" + +#define N 16 + +int main1 () +{ + int i,j; + int ia[N]; + + /* Induction. */ + for (j=0,i=N; j<N,i>0; i--,j++) { + ia[j] = i; + } + + /* check results: */ + for (j=0,i=N; j<N,i>0; i--,j++) { + if (ia[j] != i) + abort (); + } + + return 0; +} + +int main (void) +{ + check_vect(); + + return main1 (); +} + +/* { 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-iv-11.c b/gcc/testsuite/gcc.dg/vect/vect-iv-11.c new file mode 100644 index 0000000..2caadec --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-iv-11.c @@ -0,0 +1,32 @@ +/* { dg-require-effective-target vect_int } */ + +#include <stdio.h> +#include <stdarg.h> +#include "tree-vect.h" + +int main1 (int len) +{ + int s = 0; + int i = len; + + /* vectorization of induction with reduction. */ + for ( ; i > 1; i -=2) + s += i; + + return s; +} + +int main (void) +{ + int s; + check_vect (); + + s = main1 (26); + if (s != 182) + abort (); + + 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-iv-2.c b/gcc/testsuite/gcc.dg/vect/vect-iv-2.c new file mode 100644 index 0000000..831b005 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-iv-2.c @@ -0,0 +1,49 @@ +/* { dg-require-effective-target vect_int } */ + +#include <stdarg.h> +#include "tree-vect.h" + +#define N 16 + +int main1 () +{ + int arr1[N]; + int k = 0; + int m = 3, i = 0; + + /* Vectorization of induction that is used after the loop. + Currently vectorizable because scev_ccp disconnects the + use-after-the-loop from the iv def inside the loop. */ + + do { + k = k + 2; + arr1[i] = k; + m = m + k; + i++; + } while (i < N); + + /* check results: */ + for (i = 0; i < N; i++) + { + if (arr1[i] != 2+2*i) + abort (); + } + + return m + k; +} + +int main (void) +{ + int res; + + check_vect (); + + res = main1 (); + if (res != 32 + 275) + 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-iv-3.c b/gcc/testsuite/gcc.dg/vect/vect-iv-3.c new file mode 100644 index 0000000..effa8ec --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-iv-3.c @@ -0,0 +1,44 @@ +/* { dg-require-effective-target vect_int } */ + +#include <stdarg.h> +#include "tree-vect.h" + +#define N 16 + +int main1 () +{ + int arr1[N]; + int arr2[N]; + int k = 0; + int m = 3, i = 0; + + /* vectorization of induction. + Peeling to align the store is also applied. */ + + do { + k = k + 2; + arr1[i] = k; + m = k + 3; + arr2[i] = m; + i++; + } while (i < N); + + /* check results: */ + for (i = 0; i < N; i++) + { + if (arr1[i] != 2+2*i || arr2[i] != 5 + 2*i) + abort (); + } + + return 0; +} + +int main (void) +{ + check_vect (); + + return main1 (); +} + +/* { 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-iv-4.c b/gcc/testsuite/gcc.dg/vect/vect-iv-4.c new file mode 100644 index 0000000..c860f68 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-iv-4.c @@ -0,0 +1,44 @@ +/* { dg-require-effective-target vect_int } */ + +#include <stdarg.h> +#include "tree-vect.h" + +#define N 16 + +int main1 () +{ + unsigned int arr1[N]; + unsigned short arr2[N]; + unsigned int k = 0; + unsigned short m = 3; + int i = 0; + + /* Vectorization of induction with multiple data types. */ + + do { + k = k + 2; + arr1[i] = k; + m = k + 3; + arr2[i] = m; + i++; + } while (i < N); + + /* check results: */ + for (i = 0; i < N; i++) + { + if (arr1[i] != 2+2*i || arr2[i] != 5 + 2*i) + abort (); + } + + return 0; +} + +int main (void) +{ + check_vect (); + + return main1 (); +} + +/* { 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-iv-5.c b/gcc/testsuite/gcc.dg/vect/vect-iv-5.c new file mode 100644 index 0000000..6c5cb66 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-iv-5.c @@ -0,0 +1,40 @@ +/* { dg-require-effective-target vect_int } */ + +#include <stdarg.h> +#include "tree-vect.h" + +#define N 16 + +int main1 () +{ + float arr[N]; + float f = 1.0; + int i; + + /* Vectorization of fp induction. */ + + for (i=0; i<N; i++) + { + arr[i] = f; + f += 2.0; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (arr[i] != 1.0 + 2.0*i) + abort (); + } + + return 0; +} + +int main (void) +{ + check_vect (); + + return main1 (); +} + +/* { 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-iv-6.c b/gcc/testsuite/gcc.dg/vect/vect-iv-6.c new file mode 100644 index 0000000..3c301eb --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-iv-6.c @@ -0,0 +1,49 @@ +/* { dg-require-effective-target vect_int } */ +#include <stdio.h> +#include <stdarg.h> +#include "tree-vect.h" + +#define N 16 + +int main1 (int X) +{ + int arr1[N+1]; + int arr2[N+1]; + int k = X; + int m, i=0; + + /* Vectorization of induction with non-constant initial condition X. + Also we have here two uses of the induction-variable k as defined + by the loop-header phi (as opposed to the other uses of k that are + defined in the loop), in which case we exercise the fact that we + reuse the same vector def-use-cycle for both uses. + Peeling to align the store is also applied. */ + + do { + arr2[i+1] = 2*k; + k = k + 2; + arr1[i+1] = k; + k = k + 4; + i++; + } while (i < N); + + /* check results: */ + for (i = 0; i < N; i++) + { + if (arr1[i+1] != X+6*i+2 + || arr2[i+1] != 2*(X+6*i)) + abort (); + } + + return 0; +} + +int main (void) +{ + check_vect (); + + return main1 (3); +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail vect_no_align } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-iv-7.c b/gcc/testsuite/gcc.dg/vect/vect-iv-7.c new file mode 100644 index 0000000..eafeb30 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-iv-7.c @@ -0,0 +1,42 @@ +/* { dg-require-effective-target vect_int } */ + +#include <stdarg.h> +#include "tree-vect.h" + +#define N 16 +int result[N] = {8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38}; + +int main1 (int X) +{ + int arr[N]; + int k = 3; + int m, i=0; + + /* Vectorization of induction with non-constant step X. */ + + do { + m = k + 5; + arr[i] = m; + k = k + X; + i++; + } while (i < N); + + /* check results: */ + for (i = 0; i < N; i++) + { + if (arr[i] != result[i]) + abort (); + } + + return 0; +} + +int main (void) +{ + check_vect (); + + return main1 (2); +} + +/* { 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-iv-8.c b/gcc/testsuite/gcc.dg/vect/vect-iv-8.c new file mode 100644 index 0000000..a2d4e37 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-iv-8.c @@ -0,0 +1,41 @@ +/* { dg-require-effective-target vect_int } */ + +#include <stdarg.h> +#include "tree-vect.h" + +#define N 26 + +int main1 (short X) +{ + unsigned char a[N]; + unsigned short b[N]; + unsigned int c[N]; + int i; + + /* vectorization of induction with type conversions. */ + for (i = 0; i < N; i++) + { + a[i] = (unsigned char)X; + b[i] = X; + c[i] = (unsigned int)X; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (a[i] != (char)X || b[i] != X || c[i] != (int)X) + abort (); + } + + return 0; +} + +int main (void) +{ + check_vect (); + + return main1 (3); +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_pack_mod && vect_unpack } } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-iv-9.c b/gcc/testsuite/gcc.dg/vect/vect-iv-9.c new file mode 100644 index 0000000..12d4d35 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-iv-9.c @@ -0,0 +1,37 @@ +/* { dg-require-effective-target vect_int } */ + +#include <stdarg.h> +#include "tree-vect.h" + +#define N 26 +int a[N]; + +int main1 (int X) +{ + int s = X; + int i; + + /* vectorization of reduction with induction. */ + for (i = 0; i < N; i++) + s += (i + a[i]); + + return s; +} + +int main (void) +{ + int s, i; + check_vect (); + + for (i = 0; i < N; i++) + a[i] = 2*i; + + s = main1 (3); + if (s != 978) + abort (); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16a.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16a.c index 38753f7..334cc23 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16a.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16a.c @@ -46,7 +46,7 @@ int main (void) return 0; } +/* The initialization loop in main also gets vectorized. */ /* { dg-final { scan-tree-dump-times "vect_recog_dot_prod_pattern: detected" 1 "vect" { xfail *-*-* } } } */ -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_short_mult && vect_widen_sum_hi_to_si } } } } */ - +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { target { vect_short_mult && vect_widen_sum_hi_to_si } } } } */ /* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16b.c b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16b.c index 7c83108..9bb5cdf 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16b.c +++ b/gcc/testsuite/gcc.dg/vect/vect-reduc-dot-u16b.c @@ -51,6 +51,8 @@ int main (void) /* Once the dot-product pattern is detected, we expect that loop to be vectorized on vect_udot_hi targets (targets that support dot-product of unsigned shorts) and targets that support widening multiplication. */ -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ +/* The induction loop in main is vectorized. */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { xfail *-*-* } } } */ +/* { 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-widen-mult-u16.c b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u16.c index 3531d20..c2cd080 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u16.c +++ b/gcc/testsuite/gcc.dg/vect/vect-widen-mult-u16.c @@ -42,6 +42,8 @@ int main (void) return 0; } -/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */ +/*The induction loop is vectorized */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" { xfail *-*-* } } } */ +/* { 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 723e9b6..547dbd4 100644 --- a/gcc/testsuite/gcc.dg/vect/vect.exp +++ b/gcc/testsuite/gcc.dg/vect/vect.exp @@ -156,6 +156,12 @@ lappend DEFAULT_VECTCFLAGS "-fno-trapping-math" dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/no-trapping-math-*.\[cS\]]] \ "" $DEFAULT_VECTCFLAGS +# -fno-tree-scev-cprop +set DEFAULT_VECTCFLAGS $SAVED_DEFAULT_VECTCFLAGS +lappend DEFAULT_VECTCFLAGS "-fno-tree-scev-cprop" +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/no-tree-scev-cprop-*.\[cS\]]] \ + "" $DEFAULT_VECTCFLAGS + # With -Os lappend DEFAULT_VECTCFLAGS "-Os" dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/Os-vect-*.\[cS\]]] \ diff --git a/gcc/tree-ssa-loop.c b/gcc/tree-ssa-loop.c index f6392c5..bdf7ade 100644 --- a/gcc/tree-ssa-loop.c +++ b/gcc/tree-ssa-loop.c @@ -280,7 +280,7 @@ struct tree_opt_pass pass_iv_canon = static bool gate_scev_const_prop (void) { - return true; + return flag_tree_scev_cprop; } struct tree_opt_pass pass_scev_cprop = diff --git a/gcc/tree-vect-analyze.c b/gcc/tree-vect-analyze.c index 88c937c..4d74d18 100644 --- a/gcc/tree-vect-analyze.c +++ b/gcc/tree-vect-analyze.c @@ -509,58 +509,69 @@ vect_analyze_scalar_cycles (loop_vec_info loop_vinfo) tree phi; struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); basic_block bb = loop->header; - tree dummy; + tree dumy; + VEC(tree,heap) *worklist = VEC_alloc (tree, heap, 64); if (vect_print_dump_info (REPORT_DETAILS)) fprintf (vect_dump, "=== vect_analyze_scalar_cycles ==="); + /* First - identify all inductions. */ for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi)) { tree access_fn = NULL; tree def = PHI_RESULT (phi); stmt_vec_info stmt_vinfo = vinfo_for_stmt (phi); - tree reduc_stmt; if (vect_print_dump_info (REPORT_DETAILS)) { - fprintf (vect_dump, "Analyze phi: "); - print_generic_expr (vect_dump, phi, TDF_SLIM); + fprintf (vect_dump, "Analyze phi: "); + print_generic_expr (vect_dump, phi, TDF_SLIM); } /* Skip virtual phi's. The data dependences that are associated with virtual defs/uses (i.e., memory accesses) are analyzed elsewhere. */ - if (!is_gimple_reg (SSA_NAME_VAR (def))) - { - if (vect_print_dump_info (REPORT_DETAILS)) - fprintf (vect_dump, "virtual phi. skip."); - continue; - } + continue; STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_unknown_def_type; /* Analyze the evolution function. */ - access_fn = analyze_scalar_evolution (loop, def); + if (access_fn && vect_print_dump_info (REPORT_DETAILS)) + { + fprintf (vect_dump, "Access function of PHI: "); + print_generic_expr (vect_dump, access_fn, TDF_SLIM); + } - if (!access_fn) - continue; + if (!access_fn + || !vect_is_simple_iv_evolution (loop->num, access_fn, &dumy, &dumy)) + { + VEC_safe_push (tree, heap, worklist, phi); + continue; + } if (vect_print_dump_info (REPORT_DETAILS)) - { - fprintf (vect_dump, "Access function of PHI: "); - print_generic_expr (vect_dump, access_fn, TDF_SLIM); - } + fprintf (vect_dump, "Detected induction."); + STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_induction_def; + } - if (vect_is_simple_iv_evolution (loop->num, access_fn, &dummy, &dummy)) - { - if (vect_print_dump_info (REPORT_DETAILS)) - fprintf (vect_dump, "Detected induction."); - STMT_VINFO_DEF_TYPE (stmt_vinfo) = vect_induction_def; - continue; - } - /* TODO: handle invariant phis */ + /* Second - identify all reductions. */ + while (VEC_length (tree, worklist) > 0) + { + tree phi = VEC_pop (tree, worklist); + tree def = PHI_RESULT (phi); + stmt_vec_info stmt_vinfo = vinfo_for_stmt (phi); + tree reduc_stmt; + + if (vect_print_dump_info (REPORT_DETAILS)) + { + fprintf (vect_dump, "Analyze phi: "); + print_generic_expr (vect_dump, phi, TDF_SLIM); + } + + gcc_assert (is_gimple_reg (SSA_NAME_VAR (def))); + gcc_assert (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_unknown_def_type); reduc_stmt = vect_is_simple_reduction (loop, phi); if (reduc_stmt) @@ -574,9 +585,9 @@ vect_analyze_scalar_cycles (loop_vec_info loop_vinfo) else if (vect_print_dump_info (REPORT_DETAILS)) fprintf (vect_dump, "Unknown def-use cycle pattern."); - } + VEC_free (tree, heap, worklist); return; } @@ -1908,7 +1919,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo) tree scalar_type; if (vect_print_dump_info (REPORT_DETAILS)) - fprintf (vect_dump, "=== vect_analyze_data_refs ==="); + fprintf (vect_dump, "=== vect_analyze_data_refs ===\n"); compute_data_dependences_for_loop (loop, true, &LOOP_VINFO_DATAREFS (loop_vinfo), @@ -1933,7 +1944,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo) /* Update DR field in stmt_vec_info struct. */ stmt = DR_STMT (dr); stmt_info = vinfo_for_stmt (stmt); - + if (STMT_VINFO_DATA_REF (stmt_info)) { if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS)) @@ -2249,14 +2260,21 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) /* case 2.2: */ if (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def) - { - gcc_assert (relevant == vect_unused_in_loop && live_p); - relevant = vect_used_by_reduction; - live_p = false; - } + { + gcc_assert (relevant == vect_unused_in_loop && live_p); + relevant = vect_used_by_reduction; + live_p = false; + } + i = 0; FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE) { + if (vect_print_dump_info (REPORT_DETAILS)) + { + fprintf (vect_dump, "worklist: examine use %d: ", i++); + print_generic_expr (vect_dump, use, TDF_SLIM); + } + /* case 1: we are only interested in uses that need to be vectorized. Uses that are used for address computation are not considered relevant. @@ -2265,25 +2283,19 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) continue; if (!vect_is_simple_use (use, loop_vinfo, &def_stmt, &def, &dt)) - { - if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS)) - fprintf (vect_dump, "not vectorized: unsupported use in stmt."); + { + if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS)) + fprintf (vect_dump, "not vectorized: unsupported use in stmt."); VEC_free (tree, heap, worklist); - return false; + return false; } if (!def_stmt || IS_EMPTY_STMT (def_stmt)) continue; - if (vect_print_dump_info (REPORT_DETAILS)) - { - fprintf (vect_dump, "worklist: examine use %d: ", i); - print_generic_expr (vect_dump, use, TDF_SLIM); - } - bb = bb_for_stmt (def_stmt); - if (!flow_bb_inside_loop_p (loop, bb)) - continue; + if (!flow_bb_inside_loop_p (loop, bb)) + continue; /* case 2.1: the reduction-use does not mark the defining-phi as relevant. */ @@ -2291,6 +2303,9 @@ vect_mark_stmts_to_be_vectorized (loop_vec_info loop_vinfo) && TREE_CODE (def_stmt) == PHI_NODE) continue; + if (dt == vect_induction_def && TREE_CODE (def_stmt) == PHI_NODE) + continue; + vect_mark_relevant (&worklist, def_stmt, relevant, live_p); } } /* while worklist */ diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c index fc95e60..d7488b1 100644 --- a/gcc/tree-vect-transform.c +++ b/gcc/tree-vect-transform.c @@ -462,7 +462,7 @@ vect_create_destination_var (tree scalar_dest, tree vectype) new_name = get_name (scalar_dest); if (!new_name) new_name = "var_"; - vec_dest = vect_get_new_vect_var (type, vect_simple_var, new_name); + vec_dest = vect_get_new_vect_var (type, kind, new_name); add_referenced_var (vec_dest); return vec_dest; @@ -510,6 +510,189 @@ vect_init_vector (tree stmt, tree vector_var, tree vector_type) } +/* Function get_initial_def_for_induction + + Input: + STMT - a stmt that performs an induction operation in the loop. + IV_PHI - the initial value of the induction variable + + Output: + Return a vector variable, initialized with the first VF values of + the induction variable. E.g., for an iv with IV_PHI='X' and + evolution S, for a vector of 4 units, we want to return: + [X, X + S, X + 2*S, X + 3*S]. */ + +static tree +get_initial_def_for_induction (tree stmt, tree iv_phi) +{ + stmt_vec_info stmt_vinfo = vinfo_for_stmt (stmt); + loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo); + struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + tree scalar_type = TREE_TYPE (iv_phi); + tree vectype = get_vectype_for_scalar_type (scalar_type); + int nunits = GET_MODE_NUNITS (TYPE_MODE (vectype)); + edge pe = loop_preheader_edge (loop); + basic_block new_bb; + block_stmt_iterator bsi; + tree vec, vec_init, vec_step, t; + tree access_fn; + tree new_var; + tree new_name; + tree init_stmt; + tree induction_phi, induc_def, new_stmt, vec_def, vec_dest; + tree init_expr, step_expr; + int vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo); + int i; + bool ok; + int ncopies = vf / nunits; + tree expr; + stmt_vec_info phi_info = vinfo_for_stmt (iv_phi); + + gcc_assert (phi_info); + + if (STMT_VINFO_VEC_STMT (phi_info)) + { + induction_phi = STMT_VINFO_VEC_STMT (phi_info); + gcc_assert (TREE_CODE (induction_phi) == PHI_NODE); + + if (vect_print_dump_info (REPORT_DETAILS)) + { + fprintf (vect_dump, "induction already vectorized:"); + print_generic_expr (vect_dump, iv_phi, TDF_SLIM); + fprintf (vect_dump, "\n"); + print_generic_expr (vect_dump, induction_phi, TDF_SLIM); + } + + return PHI_RESULT (induction_phi); + } + + gcc_assert (ncopies >= 1); + + access_fn = analyze_scalar_evolution (loop, PHI_RESULT (iv_phi)); + gcc_assert (access_fn); + ok = vect_is_simple_iv_evolution (loop->num, access_fn, &init_expr, &step_expr); + gcc_assert (ok); + + /* Create the vector that holds the initial_value of the induction. */ + new_name = init_expr; + t = NULL_TREE; + t = tree_cons (NULL_TREE, init_expr, t); + for (i = 1; i < nunits; i++) + { + /* Create: new_name = new_name + step_expr */ + new_var = vect_get_new_vect_var (scalar_type, vect_scalar_var, "var_"); + add_referenced_var (new_var); + init_stmt = build2 (GIMPLE_MODIFY_STMT, void_type_node, new_var, + fold_build2 (PLUS_EXPR, scalar_type, new_name, step_expr)); + new_name = make_ssa_name (new_var, init_stmt); + GIMPLE_STMT_OPERAND (init_stmt, 0) = new_name; + + new_bb = bsi_insert_on_edge_immediate (pe, init_stmt); + gcc_assert (!new_bb); + + if (vect_print_dump_info (REPORT_DETAILS)) + { + fprintf (vect_dump, "created new init_stmt: "); + print_generic_expr (vect_dump, init_stmt, TDF_SLIM); + } + t = tree_cons (NULL_TREE, new_name, t); + } + vec = build_constructor_from_list (vectype, nreverse (t)); + vec_init = vect_init_vector (stmt, vec, vectype); + + + /* Create the vector that holds the step of the induction. */ + expr = build_int_cst (scalar_type, vf); + new_name = fold_build2 (MULT_EXPR, scalar_type, expr, step_expr); + t = NULL_TREE; + for (i = 0; i < nunits; i++) + t = tree_cons (NULL_TREE, unshare_expr (new_name), t); + vec = build_constructor_from_list (vectype, t); + vec_step = vect_init_vector (stmt, vec, vectype); + + + /* Create the following def-use cycle: + loop prolog: + vec_init = [X, X+S, X+2*S, X+3*S] + vec_step = [VF*S, VF*S, VF*S, VF*S] + loop: + vec_iv = PHI <vec_init, vec_loop> + ... + STMT + ... + vec_loop = vec_iv + vec_step; */ + + /* Create the induction-phi that defines the induction-operand. */ + vec_dest = vect_get_new_vect_var (vectype, vect_simple_var, "vec_iv_"); + add_referenced_var (vec_dest); + induction_phi = create_phi_node (vec_dest, loop->header); + set_stmt_info (get_stmt_ann (induction_phi), + new_stmt_vec_info (induction_phi, loop_vinfo)); + induc_def = PHI_RESULT (induction_phi); + + /* Create the iv update inside the loop */ + new_stmt = build2 (GIMPLE_MODIFY_STMT, void_type_node, NULL_TREE, + build2 (PLUS_EXPR, vectype, induc_def, vec_step)); + vec_def = make_ssa_name (vec_dest, new_stmt); + GIMPLE_STMT_OPERAND (new_stmt, 0) = vec_def; + bsi = bsi_for_stmt (stmt); + vect_finish_stmt_generation (stmt, new_stmt, &bsi); + + /* Set the arguments of the phi node: */ + add_phi_arg (induction_phi, vec_init, loop_preheader_edge (loop)); + add_phi_arg (induction_phi, vec_def, loop_latch_edge (loop)); + + + /* In case the vectorization factor (VF) is bigger than the number + of elements that we can fit in a vectype (nunits), we have to generate + more than one vector stmt - i.e - we need to "unroll" the + vector stmt by a factor VF/nunits. For more details see documentation + in vectorizable_operation. */ + + if (ncopies > 1) + { + stmt_vec_info prev_stmt_vinfo; + + /* Create the vector that holds the step of the induction. */ + expr = build_int_cst (scalar_type, nunits); + new_name = fold_build2 (MULT_EXPR, scalar_type, expr, step_expr); + t = NULL_TREE; + for (i = 0; i < nunits; i++) + t = tree_cons (NULL_TREE, unshare_expr (new_name), t); + vec = build_constructor_from_list (vectype, t); + vec_step = vect_init_vector (stmt, vec, vectype); + + vec_def = induc_def; + prev_stmt_vinfo = vinfo_for_stmt (induction_phi); + for (i = 1; i < ncopies; i++) + { + /* vec_i = vec_prev + vec_{step*nunits} */ + + new_stmt = build2 (GIMPLE_MODIFY_STMT, void_type_node, NULL_TREE, + build2 (PLUS_EXPR, vectype, vec_def, vec_step)); + vec_def = make_ssa_name (vec_dest, new_stmt); + GIMPLE_STMT_OPERAND (new_stmt, 0) = vec_def; + bsi = bsi_for_stmt (stmt); + vect_finish_stmt_generation (stmt, new_stmt, &bsi); + + STMT_VINFO_RELATED_STMT (prev_stmt_vinfo) = new_stmt; + prev_stmt_vinfo = vinfo_for_stmt (new_stmt); + } + } + + if (vect_print_dump_info (REPORT_DETAILS)) + { + fprintf (vect_dump, "transform induction: created def-use cycle:"); + print_generic_expr (vect_dump, induction_phi, TDF_SLIM); + fprintf (vect_dump, "\n"); + print_generic_expr (vect_dump, SSA_NAME_DEF_STMT (vec_def), TDF_SLIM); + } + + STMT_VINFO_VEC_STMT (phi_info) = induction_phi; + return induc_def; +} + + /* Function vect_get_vec_def_for_operand. OP is an operand in STMT. This function returns a (vector) def that will be @@ -634,9 +817,10 @@ vect_get_vec_def_for_operand (tree op, tree stmt, tree *scalar_def) /* Case 5: operand is defined by loop-header phi - induction. */ case vect_induction_def: { - if (vect_print_dump_info (REPORT_DETAILS)) - fprintf (vect_dump, "induction - unsupported."); - internal_error ("no support for induction"); /* FORNOW */ + gcc_assert (TREE_CODE (def_stmt) == PHI_NODE); + + /* Get the def before the loop */ + return get_initial_def_for_induction (stmt, def_stmt); } default: @@ -707,14 +891,14 @@ vect_get_vec_def_for_stmt_copy (enum vect_def_type dt, tree vec_oprnd) tree vec_stmt_for_operand; stmt_vec_info def_stmt_info; - if (dt == vect_invariant_def || dt == vect_constant_def) - { - /* Do nothing; can reuse same def. */ ; - return vec_oprnd; - } + /* Do nothing; can reuse same def. */ + if (dt == vect_invariant_def || dt == vect_constant_def ) + return vec_oprnd; vec_stmt_for_operand = SSA_NAME_DEF_STMT (vec_oprnd); def_stmt_info = vinfo_for_stmt (vec_stmt_for_operand); + if (dt == vect_induction_def) + gcc_assert (TREE_CODE (vec_stmt_for_operand) == PHI_NODE); gcc_assert (def_stmt_info); vec_stmt_for_operand = STMT_VINFO_RELATED_STMT (def_stmt_info); gcc_assert (vec_stmt_for_operand); @@ -1386,8 +1570,11 @@ vectorizable_reduction (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) op = TREE_OPERAND (operation, i); is_simple_use = vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt); gcc_assert (is_simple_use); - gcc_assert (dt == vect_loop_def || dt == vect_invariant_def || - dt == vect_constant_def); + if (dt != vect_loop_def + && dt != vect_invariant_def + && dt != vect_constant_def + && dt != vect_induction_def) + return false; } op = TREE_OPERAND (operation, i); @@ -2260,9 +2447,8 @@ vectorizable_type_demotion (tree stmt, block_stmt_iterator *bsi, /* Handle uses. */ if (j == 0) { - enum vect_def_type dt = vect_unknown_def_type; /* Dummy */ vec_oprnd0 = vect_get_vec_def_for_operand (op0, stmt, NULL); - vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt, vec_oprnd0); + vec_oprnd1 = vect_get_vec_def_for_stmt_copy (dt0, vec_oprnd0); } else { diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 870163d..9f64f2c 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -1745,13 +1745,6 @@ vect_is_simple_use (tree operand, loop_vec_info loop_vinfo, tree *def_stmt, return false; } - if (*dt == vect_induction_def) - { - if (vect_print_dump_info (REPORT_DETAILS)) - fprintf (vect_dump, "induction not supported."); - return false; - } - return true; } @@ -2050,7 +2043,7 @@ vect_is_simple_reduction (struct loop *loop, tree phi) */ def1 = SSA_NAME_DEF_STMT (op1); def2 = SSA_NAME_DEF_STMT (op2); - if (!def1 || !def2) + if (!def1 || !def2 || IS_EMPTY_STMT (def1) || IS_EMPTY_STMT (def2)) { if (vect_print_dump_info (REPORT_DETAILS)) { @@ -2060,9 +2053,15 @@ vect_is_simple_reduction (struct loop *loop, tree phi) return NULL_TREE; } - if (TREE_CODE (def1) == GIMPLE_MODIFY_STMT + + /* Check that one def is the reduction def, defined by PHI, + the other def is either defined in the loop by a GIMPLE_MODIFY_STMT, + or it's an induction (defined by some phi node). */ + + if (def2 == phi && flow_bb_inside_loop_p (loop, bb_for_stmt (def1)) - && def2 == phi) + && (TREE_CODE (def1) == GIMPLE_MODIFY_STMT + || STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def1)) == vect_induction_def)) { if (vect_print_dump_info (REPORT_DETAILS)) { @@ -2071,9 +2070,10 @@ vect_is_simple_reduction (struct loop *loop, tree phi) } return def_stmt; } - else if (TREE_CODE (def2) == GIMPLE_MODIFY_STMT - && flow_bb_inside_loop_p (loop, bb_for_stmt (def2)) - && def1 == phi) + else if (def1 == phi + && flow_bb_inside_loop_p (loop, bb_for_stmt (def2)) + && (TREE_CODE (def2) == GIMPLE_MODIFY_STMT + || STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def2)) == vect_induction_def)) { /* Swap operands (just for simplicity - so that the rest of the code can assume that the reduction variable is always the last (second) @@ -2110,7 +2110,6 @@ vect_is_simple_iv_evolution (unsigned loop_nb, tree access_fn, tree * init, { tree init_expr; tree step_expr; - tree evolution_part = evolution_part_in_loop_num (access_fn, loop_nb); /* When there is no evolution in this loop, the evolution function @@ -2124,8 +2123,7 @@ vect_is_simple_iv_evolution (unsigned loop_nb, tree access_fn, tree * init, return false; step_expr = evolution_part; - init_expr = unshare_expr (initial_condition_in_loop_num (access_fn, - loop_nb)); + init_expr = unshare_expr (initial_condition_in_loop_num (access_fn, loop_nb)); if (vect_print_dump_info (REPORT_DETAILS)) { @@ -2139,7 +2137,7 @@ vect_is_simple_iv_evolution (unsigned loop_nb, tree access_fn, tree * init, *step = step_expr; if (TREE_CODE (step_expr) != INTEGER_CST) - { + { if (vect_print_dump_info (REPORT_DETAILS)) fprintf (vect_dump, "step unknown."); return false; |