diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 26 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-dv-1.c | 22 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-dv-2.c | 73 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-ifcvt-1.c | 74 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-ifcvt-2.c | 31 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-ifcvt-3.c | 31 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-ifcvt-4.c | 31 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-ifcvt-5.c | 31 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-ifcvt-6.c | 31 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-ifcvt-7.c | 31 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-ifcvt-9.c | 36 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/vect/vect-none.c | 3 | ||||
-rw-r--r-- | gcc/testsuite/lib/target-supports.exp | 19 | ||||
-rw-r--r-- | gcc/tree-data-ref.c | 4 | ||||
-rw-r--r-- | gcc/tree-data-ref.h | 2 | ||||
-rw-r--r-- | gcc/tree-vect-analyze.c | 92 | ||||
-rw-r--r-- | gcc/tree-vect-transform.c | 146 | ||||
-rw-r--r-- | gcc/tree-vectorizer.c | 11 | ||||
-rw-r--r-- | gcc/tree-vectorizer.h | 6 |
20 files changed, 693 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a43ccf4..bc5f1a3 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2005-04-11 Devang Patel <dpatel@apple.com> + + * tree-data-ref.c (build_classic_dist_vector, + compute_subscript_distance): Make externally visible. + * tree-data-ref.h (build_classic_dist_vector, + compute_subscript_distance): Same. + * tree-vect-analyze.c (vect_analyze_data_ref_dependence): + Check distance vector against vectorization factor. + (vect_analyze_loop): Determine vectorizaion factor before + analyzing data dependences. + * tree-vectorizer.c (loops_num): Make it externally visible and + rename ... + * tree-vectorizer.c (vect_loops_num): ... new name. + * tree-vectorizer.h (vect_loops_num): New. + +2005-04-11 Devang Patel <dpatel@apple.com> + + * tree-vect-analyze.c (vect_analyze_operations): Check + vectorizable codition. + * tree-vect-transform.c (vect_is_simple_cond): New function. + (vectorizable_condition): New function. + (vect_transform_stmt): Handle condition_vec_info_type. + * tree-vectorizer.h (enum stmt_vec_info_type): Add + condition_vec_info_type. + (vectorizable_condition): New. + 2005-04-11 Geoffrey Keating <geoffk@apple.com> * config/t-slibgcc-darwin: Don't put shared libraries in diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5271167..e7d40f8 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,20 @@ +2004-04-11 Devang Patel <dpatel@apple.com> + + * lib/target-supports.exp (check_effective_target_vect_condition): New. + * gcc.dg/vect/vect-ifcvt-1.c: New test. + * gcc.dg/vect/vect-ifcvt-2.c: New test. + * gcc.dg/vect/vect-ifcvt-3.c: New test. + * gcc.dg/vect/vect-ifcvt-4.c: New test. + * gcc.dg/vect/vect-ifcvt-5.c: New test. + * gcc.dg/vect/vect-ifcvt-6.c: New test. + * gcc.dg/vect/vect-ifcvt-7.c: New test. + * gcc.dg/vect/vect-none.c: Now one loop is vectorized. + +2004-04-11 Devang Patel <dpatel@apple.com> + + * gcc.dg/vect/vect-dv-1.c: New test. + * gcc.dg/vect/vect-dv-2.c: New test. + 2005-04-11 Diego Novillo <dnovillo@redhat.com> PR tree-optimization/20933 diff --git a/gcc/testsuite/gcc.dg/vect/vect-dv-1.c b/gcc/testsuite/gcc.dg/vect/vect-dv-1.c new file mode 100644 index 0000000..20fe1be --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-dv-1.c @@ -0,0 +1,22 @@ +/* Test compiler crash when dependence analyzer can not represent + dependence relation by distance vector. */ +/* { dg-do compile } */ +/* { dg-require-effective-target vect_int } */ + +int x[199]; + +void foo() + +{ + int t,j; + + for (j=99;j>0;j--) + x [j+j]=x[j]; + + for (j=198;j>=100;j--) + if(x[j]) + { + x[j-63]=x[j-3]-x[j]; + } +} + diff --git a/gcc/testsuite/gcc.dg/vect/vect-dv-2.c b/gcc/testsuite/gcc.dg/vect/vect-dv-2.c new file mode 100644 index 0000000..dfcfc64 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-dv-2.c @@ -0,0 +1,73 @@ +/* { dg-do run } */ +/* { dg-require-effective-target vect_int } */ + +#include <stdarg.h> +#include <signal.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; + + for (i = 0; i < N; i++) + { + A[i] = i; + B[i] = i; + C[i] = i; + D[i] = i; + } + + /* Vectorizable */ + for (i = 0; i < 16; i++) + { + A[i] = A[i+20]; + } + + /* check results: */ + for (i = 0; i < 16; i++) + { + if (A[i] != A[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; +} + + + +/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { xfail vect_no_align } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-ifcvt-1.c b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-1.c new file mode 100644 index 0000000..385e2d1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-1.c @@ -0,0 +1,74 @@ +/* { dg-require-effective-target vect_condition } */ +/* { dg-do run } */ + +#include <stdarg.h> +#include <signal.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; + + for (i = 0; i < N; i++) + { + A[i] = i; + B[i] = i; + C[i] = i; + D[i] = i; + } + + /* Vectorizable */ + for (i = 0; i < 16; i++) + { + A[i] = A[i+20]; + } + + /* check results: */ + for (i = 0; i < 16; i++) + { + if (A[i] != A[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; +} + + + +/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { xfail vect_no_align } } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-ifcvt-2.c b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-2.c new file mode 100644 index 0000000..d270154 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-2.c @@ -0,0 +1,31 @@ +/* { dg-require-effective-target vect_condition } */ +/* { dg-do run } */ + +#include <stdarg.h> +#include <signal.h> + +#define N 16 +#define MAX 42 + +extern void abort(void); + +int main () +{ + int A[N] = {36,39,42,45,43,32,21,12,23,34,45,56,67,78,89,11}; + int B[N] = {0,0,42,42,42,0,0,0,0,0,42,42,42,42,42,0}; + int i, j; + + for (i = 0; i < 16; i++) + A[i] = ( A[i] >= MAX ? MAX : 0); + + /* check results: */ + for (i = 0; i < N; i++) + if (A[i] != B[i]) + abort (); + + return 0; +} + + + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-ifcvt-3.c b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-3.c new file mode 100644 index 0000000..46dafa5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-3.c @@ -0,0 +1,31 @@ +/* { dg-require-effective-target vect_condition } */ +/* { dg-do run } */ + +#include <stdarg.h> +#include <signal.h> + +#define N 16 +#define MAX 42 + +extern void abort(void); + +int main () +{ + int A[N] = {36,39,42,45,43,32,21,12,23,34,45,56,67,78,89,11}; + int B[N] = {0,0,0,42,42,0,0,0,0,0,42,42,42,42,42,0}; + int i, j; + + for (i = 0; i < 16; i++) + A[i] = ( A[i] > MAX ? MAX : 0); + + /* check results: */ + for (i = 0; i < N; i++) + if (A[i] != B[i]) + abort (); + + return 0; +} + + + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-ifcvt-4.c b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-4.c new file mode 100644 index 0000000..2fc5b21 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-4.c @@ -0,0 +1,31 @@ +/* { dg-require-effective-target vect_condition } */ +/* { dg-do run } */ + +#include <stdarg.h> +#include <signal.h> + +#define N 16 +#define MAX 42 + +extern void abort(void); + +int main () +{ + int A[N] = {36,39,42,45,43,32,21,12,23,34,45,56,67,78,89,11}; + int B[N] = {42,42,42,0,0,42,42,42,42,42,0,0,0,0,0,42}; + int i, j; + + for (i = 0; i < 16; i++) + A[i] = ( A[i] <= MAX ? MAX : 0); + + /* check results: */ + for (i = 0; i < N; i++) + if (A[i] != B[i]) + abort (); + + return 0; +} + + + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-ifcvt-5.c b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-5.c new file mode 100644 index 0000000..e721090 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-5.c @@ -0,0 +1,31 @@ +/* { dg-require-effective-target vect_condition } */ +/* { dg-do run } */ + +#include <stdarg.h> +#include <signal.h> + +#define N 16 +#define MAX 42 + +extern void abort(void); + +int main () +{ + int A[N] = {36,39,42,45,43,32,21,12,23,34,45,56,67,78,89,11}; + int B[N] = {42,42,0,0,0,42,42,42,42,42,0,0,0,0,0,42}; + int i, j; + + for (i = 0; i < 16; i++) + A[i] = ( A[i] < MAX ? MAX : 0); + + /* check results: */ + for (i = 0; i < N; i++) + if (A[i] != B[i]) + abort (); + + return 0; +} + + + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-ifcvt-6.c b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-6.c new file mode 100644 index 0000000..80aa3d2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-6.c @@ -0,0 +1,31 @@ +/* { dg-require-effective-target vect_condition } */ +/* { dg-do run } */ + +#include <stdarg.h> +#include <signal.h> + +#define N 16 +#define MAX 42 + +extern void abort(void); + +int main () +{ + int A[N] = {36,39,42,45,43,32,21,42,23,34,45,56,67,42,89,11}; + int B[N] = {42,42,0,42,42,42,42,0,42,42,42,42,42,0,42,42}; + int i, j; + + for (i = 0; i < 16; i++) + A[i] = ( A[i] != MAX ? MAX : 0); + + /* check results: */ + for (i = 0; i < N; i++) + if (A[i] != B[i]) + abort (); + + return 0; +} + + + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-ifcvt-7.c b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-7.c new file mode 100644 index 0000000..ef22119 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-7.c @@ -0,0 +1,31 @@ +/* { dg-require-effective-target vect_condition } */ +/* { dg-do run } */ + +#include <stdarg.h> +#include <signal.h> + +#define N 16 +#define MAX 42 + +extern void abort(void); + +int main () +{ + int A[N] = {36,39,42,45,43,32,21,12,23,34,45,56,42,78,89,11}; + int B[N] = {42,42,0,42,42,42,42,42,42,42,42,42,0,42,42,42}; + int i, j; + + for (i = 0; i < 16; i++) + A[i] = ( A[i] == MAX ? 0 : MAX); + + /* check results: */ + for (i = 0; i < N; i++) + if (A[i] != B[i]) + abort (); + + return 0; +} + + + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-ifcvt-9.c b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-9.c new file mode 100644 index 0000000..cb0dc80 --- /dev/null +++ b/gcc/testsuite/gcc.dg/vect/vect-ifcvt-9.c @@ -0,0 +1,36 @@ +/* { dg-require-effective-target vect_condition } */ +/* { dg-do run } */ + +#include <stdarg.h> +#include <signal.h> + +#define N 16 +#define MAX 42 + +extern void abort(void); + +int A[N] = {36,39,42,45,43,32,21,12,23,34,45,56,67,78,89,11}; +int B[N] = {0,0,42,42,42,0,0,0,0,0,42,42,42,42,42,0}; +void foo () __attribute__((always_inline)); +void foo () +{ + int i, j; + + for (i = 0; i < 16; i++) + A[i] = ( A[i] >= MAX ? MAX : 0); +} + +int main () +{ + + int i, j; + foo (); + /* check results: */ + for (i = 0; i < N; i++) + if (A[i] != B[i]) + abort (); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/vect/vect-none.c b/gcc/testsuite/gcc.dg/vect/vect-none.c index 4cc8e0b..924c421 100644 --- a/gcc/testsuite/gcc.dg/vect/vect-none.c +++ b/gcc/testsuite/gcc.dg/vect/vect-none.c @@ -181,5 +181,6 @@ foo (int n) } /* { dg-final { scan-tree-dump-times "vectorized " 3 "vect"} } */ -/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 3 "vect"} } */ +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect"} } */ +/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 2 "vect"} } */ /* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp index c3f8110..52200e9 100644 --- a/gcc/testsuite/lib/target-supports.exp +++ b/gcc/testsuite/lib/target-supports.exp @@ -835,6 +835,25 @@ proc check_effective_target_vect_no_align { } { return $et_vect_no_align_saved } +# Return 1 if the target supports vector conditional operations, 0 otherwise. + +proc check_effective_target_vect_condition { } { + global et_vect_cond_saved + + if [info exists et_vect_int_cond] { + verbose "check_effective_target_vect_cond: using cached result" 2 + } else { + set et_vect_cond_saved 0 + if { [istarget powerpc*-*-*] } { + set et_vect_cond_saved 1 + } + } + + verbose "check_effective_target_vect_cond: returning $et_vect_cond_saved" 2 + return $et_vect_cond_saved +} + + # Return 1 if the target matches the effective target 'arg', 0 otherwise. # This can be used with any check_* proc that takes no argument and # returns only 1 or 0. It could be used with check_* procs that take diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c index 882163d..b984c04 100644 --- a/gcc/tree-data-ref.c +++ b/gcc/tree-data-ref.c @@ -646,7 +646,7 @@ all_chrecs_equal_p (tree chrec) /* Determine for each subscript in the data dependence relation DDR the distance. */ -static void +void compute_subscript_distance (struct data_dependence_relation *ddr) { if (DDR_ARE_DEPENDENT (ddr) == NULL_TREE) @@ -1769,7 +1769,7 @@ subscript_dependence_tester (struct data_dependence_relation *ddr) starting at FIRST_LOOP_DEPTH. Return TRUE otherwise. */ -static bool +bool build_classic_dist_vector (struct data_dependence_relation *ddr, int nb_loops, int first_loop_depth) { diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h index ea3bb7d..03c0736 100644 --- a/gcc/tree-data-ref.h +++ b/gcc/tree-data-ref.h @@ -176,6 +176,8 @@ extern bool array_base_name_differ_p (struct data_reference *, extern void free_dependence_relation (struct data_dependence_relation *); extern void free_dependence_relations (varray_type); extern void free_data_refs (varray_type); +extern void compute_subscript_distance (struct data_dependence_relation *); +extern bool build_classic_dist_vector (struct data_dependence_relation *, int, int); diff --git a/gcc/tree-vect-analyze.c b/gcc/tree-vect-analyze.c index be6d81c..6ece91d 100644 --- a/gcc/tree-vect-analyze.c +++ b/gcc/tree-vect-analyze.c @@ -494,7 +494,8 @@ vect_analyze_operations (loop_vec_info loop_vinfo) ok = (vectorizable_operation (stmt, NULL, NULL) || vectorizable_assignment (stmt, NULL, NULL) || vectorizable_load (stmt, NULL, NULL) - || vectorizable_store (stmt, NULL, NULL)); + || vectorizable_store (stmt, NULL, NULL) + || vectorizable_condition (stmt, NULL, NULL)); if (!ok) { @@ -774,6 +775,12 @@ vect_analyze_data_ref_dependence (struct data_reference *dra, { bool differ_p; struct data_dependence_relation *ddr; + struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo); + int vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo); + int dist = 0; + unsigned int loop_depth = 0; + struct loop *loop_nest = loop; + if (!vect_base_addr_differ_p (dra, drb, &differ_p)) { @@ -797,7 +804,65 @@ vect_analyze_data_ref_dependence (struct data_reference *dra, if (DDR_ARE_DEPENDENT (ddr) == chrec_known) return false; - + + if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know) + { + if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS, + LOOP_LOC (loop_vinfo))) + { + fprintf (vect_dump, + "not vectorized: 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); + } + return true; + } + + /* Find loop depth. */ + while (loop_nest) + { + if (loop_nest->outer && loop_nest->outer->outer) + { + loop_nest = loop_nest->outer; + loop_depth++; + } + else + break; + } + + /* Compute distance vector. */ + compute_subscript_distance (ddr); + build_classic_dist_vector (ddr, vect_loops_num, loop_nest->depth); + + if (!DDR_DIST_VECT (ddr)) + { + if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS, + LOOP_LOC (loop_vinfo))) + { + fprintf (vect_dump, "not vectorized: 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); + } + return true; + } + + dist = DDR_DIST_VECT (ddr)[loop_depth]; + + /* Same loop iteration. */ + if (dist == 0) + { + if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo))) + fprintf (vect_dump, "dependence distance 0."); + return false; + } + + if (dist >= vectorization_factor) + /* Dependence distance does not create dependence, as far as vectorization + is concerned, in this case. */ + return false; + if (vect_print_dump_info (REPORT_UNVECTORIZED_LOOPS, LOOP_LOC (loop_vinfo))) { @@ -815,10 +880,7 @@ vect_analyze_data_ref_dependence (struct data_reference *dra, /* Function vect_analyze_data_ref_dependences. Examine all the data references in the loop, and make sure there do not - exist any data dependences between them. - - TODO: dependences which distance is greater than the vectorization factor - can be ignored. */ + exist any data dependences between them. */ static bool vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo) @@ -2567,6 +2629,15 @@ vect_analyze_loop (struct loop *loop) return NULL; } + ok = vect_determine_vectorization_factor (loop_vinfo); + if (!ok) + { + if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo))) + fprintf (vect_dump, "can't determine vectorization factor."); + destroy_loop_vec_info (loop_vinfo); + return NULL; + } + /* Analyze data dependences between the data-refs in the loop. FORNOW: fail at the first data dependence that we encounter. */ @@ -2591,15 +2662,6 @@ vect_analyze_loop (struct loop *loop) return NULL; } - ok = vect_determine_vectorization_factor (loop_vinfo); - if (!ok) - { - if (vect_print_dump_info (REPORT_DETAILS, LOOP_LOC (loop_vinfo))) - fprintf (vect_dump, "can't determine vectorization factor."); - destroy_loop_vec_info (loop_vinfo); - return NULL; - } - /* Analyze the alignment of the data-refs in the loop. FORNOW: Only aligned accesses are handled. */ diff --git a/gcc/tree-vect-transform.c b/gcc/tree-vect-transform.c index 4779228..69d532f 100644 --- a/gcc/tree-vect-transform.c +++ b/gcc/tree-vect-transform.c @@ -57,6 +57,7 @@ static tree vect_get_vec_def_for_operand (tree, tree); static tree vect_init_vector (tree, tree); static void vect_finish_stmt_generation (tree stmt, tree vec_stmt, block_stmt_iterator *bsi); +static bool vect_is_simple_cond (tree, loop_vec_info); static void update_vuses_to_preheader (tree, struct loop*); /* Utility function dealing with loop peeling (not peeling itself). */ @@ -1141,6 +1142,145 @@ vectorizable_load (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) return true; } +/* Function vect_is_simple_cond. + + Input: + LOOP - the loop that is being vectorized. + COND - Condition that is checked for simple use. + + Returns whether a COND can be vectorized. Checkes whether + condition operands are supportable using vec_is_simple_use. */ + +static bool +vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo) +{ + tree lhs, rhs; + + if (TREE_CODE_CLASS (TREE_CODE (cond)) != tcc_comparison) + return false; + + lhs = TREE_OPERAND (cond, 0); + rhs = TREE_OPERAND (cond, 1); + + if (TREE_CODE (lhs) == SSA_NAME) + { + tree lhs_def_stmt = SSA_NAME_DEF_STMT (lhs); + if (!vect_is_simple_use (lhs, loop_vinfo, &lhs_def_stmt)) + return false; + } + else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST) + return false; + + if (TREE_CODE (rhs) == SSA_NAME) + { + tree rhs_def_stmt = SSA_NAME_DEF_STMT (rhs); + if (!vect_is_simple_use (rhs, loop_vinfo, &rhs_def_stmt)) + return false; + } + else if (TREE_CODE (rhs) != INTEGER_CST && TREE_CODE (rhs) != REAL_CST) + return false; + + return true; +} + +/* vectorizable_condition. + + Check if STMT is conditional modify expression that can be vectorized. + If VEC_STMT is also passed, vectorize the STMT: create a vectorized + stmt using VEC_COND_EXPR to replace it, put it in VEC_STMT, and insert it + at BSI. + + Return FALSE if not a vectorizable STMT, TRUE otherwise. */ + +bool +vectorizable_condition (tree stmt, block_stmt_iterator *bsi, tree *vec_stmt) +{ + tree scalar_dest = NULL_TREE; + tree vec_dest = NULL_TREE; + tree op = NULL_TREE; + tree cond_expr, then_clause, else_clause; + stmt_vec_info stmt_info = vinfo_for_stmt (stmt); + tree vectype = STMT_VINFO_VECTYPE (stmt_info); + tree vec_cond_lhs, vec_cond_rhs, vec_then_clause, vec_else_clause; + tree vec_compare, vec_cond_expr; + tree new_temp; + loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info); + enum machine_mode vec_mode; + + if (!STMT_VINFO_RELEVANT_P (stmt_info)) + return false; + + if (TREE_CODE (stmt) != MODIFY_EXPR) + return false; + + op = TREE_OPERAND (stmt, 1); + + if (TREE_CODE (op) != COND_EXPR) + return false; + + cond_expr = TREE_OPERAND (op, 0); + then_clause = TREE_OPERAND (op, 1); + else_clause = TREE_OPERAND (op, 2); + + if (!vect_is_simple_cond (cond_expr, loop_vinfo)) + return false; + + if (TREE_CODE (then_clause) == SSA_NAME) + { + tree then_def_stmt = SSA_NAME_DEF_STMT (then_clause); + if (!vect_is_simple_use (then_clause, loop_vinfo, &then_def_stmt)) + return false; + } + else if (TREE_CODE (then_clause) != INTEGER_CST + && TREE_CODE (then_clause) != REAL_CST) + return false; + + if (TREE_CODE (else_clause) == SSA_NAME) + { + tree else_def_stmt = SSA_NAME_DEF_STMT (else_clause); + if (!vect_is_simple_use (else_clause, loop_vinfo, &else_def_stmt)) + return false; + } + else if (TREE_CODE (else_clause) != INTEGER_CST + && TREE_CODE (else_clause) != REAL_CST) + return false; + + + vec_mode = TYPE_MODE (vectype); + + if (!vec_stmt) + { + STMT_VINFO_TYPE (stmt_info) = condition_vec_info_type; + return expand_vec_cond_expr_p (op, vec_mode); + } + + /* Transform */ + + /* Handle def. */ + scalar_dest = TREE_OPERAND (stmt, 0); + vec_dest = vect_create_destination_var (scalar_dest, vectype); + + /* Handle cond expr. */ + vec_cond_lhs = + vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 0), stmt); + vec_cond_rhs = + vect_get_vec_def_for_operand (TREE_OPERAND (cond_expr, 1), stmt); + vec_then_clause = vect_get_vec_def_for_operand (then_clause, stmt); + vec_else_clause = vect_get_vec_def_for_operand (else_clause, stmt); + + /* Arguments are ready. create the new vector stmt. */ + vec_compare = build2 (TREE_CODE (cond_expr), vectype, + vec_cond_lhs, vec_cond_rhs); + vec_cond_expr = build (VEC_COND_EXPR, vectype, + vec_compare, vec_then_clause, vec_else_clause); + + *vec_stmt = build2 (MODIFY_EXPR, vectype, vec_dest, vec_cond_expr); + new_temp = make_ssa_name (vec_dest, *vec_stmt); + TREE_OPERAND (*vec_stmt, 0) = new_temp; + vect_finish_stmt_generation (stmt, *vec_stmt, bsi); + + return true; +} /* Function vect_transform_stmt. @@ -1176,6 +1316,12 @@ vect_transform_stmt (tree stmt, block_stmt_iterator *bsi) gcc_assert (done); is_store = true; break; + + case condition_vec_info_type: + done = vectorizable_condition (stmt, bsi, &vec_stmt); + gcc_assert (done); + break; + default: if (vect_print_dump_info (REPORT_DETAILS, UNKNOWN_LOC)) fprintf (vect_dump, "stmt not supported."); diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c index 63dd2d2..c264ee0 100644 --- a/gcc/tree-vectorizer.c +++ b/gcc/tree-vectorizer.c @@ -178,7 +178,8 @@ FILE *vect_dump; to mark that it's uninitialized. */ enum verbosity_levels vect_verbosity_level = MAX_VERBOSITY_LEVEL; - +/* Number of loops, at the beginning of vectorization. */ +unsigned int vect_loops_num; /************************************************************************* Simple Loop Peeling Utilities @@ -1821,7 +1822,7 @@ vect_is_simple_iv_evolution (unsigned loop_nb, tree access_fn, tree * init, void vectorize_loops (struct loops *loops) { - unsigned int i, loops_num; + unsigned int i; unsigned int num_vectorized_loops = 0; /* Fix the verbosity level if not defined explicitly by the user. */ @@ -1841,8 +1842,8 @@ vectorize_loops (struct loops *loops) /* If some loop was duplicated, it gets bigger number than all previously defined loops. This fact allows us to run only over initial loops skipping newly generated ones. */ - loops_num = loops->num; - for (i = 1; i < loops_num; i++) + vect_loops_num = loops->num; + for (i = 1; i < vect_loops_num; i++) { loop_vec_info loop_vinfo; struct loop *loop = loops->parray[i]; @@ -1866,7 +1867,7 @@ vectorize_loops (struct loops *loops) /* ----------- Finalize. ----------- */ - for (i = 1; i < loops_num; i++) + for (i = 1; i < vect_loops_num; i++) { struct loop *loop = loops->parray[i]; loop_vec_info loop_vinfo; diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h index a38edd0..3620b2b 100644 --- a/gcc/tree-vectorizer.h +++ b/gcc/tree-vectorizer.h @@ -144,7 +144,8 @@ enum stmt_vec_info_type { load_vec_info_type, store_vec_info_type, op_vec_info_type, - assignment_vec_info_type + assignment_vec_info_type, + condition_vec_info_type }; typedef struct _stmt_vec_info { @@ -277,6 +278,8 @@ known_alignment_for_access_p (struct data_reference *data_ref_info) extern FILE *vect_dump; extern enum verbosity_levels vect_verbosity_level; +/* Number of loops, at the beginning of vectorization. */ +extern unsigned int vect_loops_num; /*-----------------------------------------------------------------*/ /* Function prototypes. */ /*-----------------------------------------------------------------*/ @@ -327,6 +330,7 @@ extern bool vectorizable_load (tree, block_stmt_iterator *, tree *); extern bool vectorizable_store (tree, block_stmt_iterator *, tree *); extern bool vectorizable_operation (tree, block_stmt_iterator *, tree *); extern bool vectorizable_assignment (tree, block_stmt_iterator *, tree *); +extern bool vectorizable_condition (tree, block_stmt_iterator *, tree *); /* Driver for transformation stage. */ extern void vect_transform_loop (loop_vec_info, struct loops *); |