summaryrefslogtreecommitdiffstats
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog26
-rw-r--r--gcc/testsuite/ChangeLog17
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-dv-1.c22
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-dv-2.c73
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-ifcvt-1.c74
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-ifcvt-2.c31
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-ifcvt-3.c31
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-ifcvt-4.c31
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-ifcvt-5.c31
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-ifcvt-6.c31
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-ifcvt-7.c31
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-ifcvt-9.c36
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-none.c3
-rw-r--r--gcc/testsuite/lib/target-supports.exp19
-rw-r--r--gcc/tree-data-ref.c4
-rw-r--r--gcc/tree-data-ref.h2
-rw-r--r--gcc/tree-vect-analyze.c92
-rw-r--r--gcc/tree-vect-transform.c146
-rw-r--r--gcc/tree-vectorizer.c11
-rw-r--r--gcc/tree-vectorizer.h6
20 files changed, 693 insertions, 24 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index a43ccf4981a..bc5f1a31c7e 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 52711671912..e7d40f87f03 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 00000000000..20fe1beb28a
--- /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 00000000000..dfcfc64862c
--- /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 00000000000..385e2d1b780
--- /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 00000000000..d2701540aea
--- /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 00000000000..46dafa50cab
--- /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 00000000000..2fc5b217205
--- /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 00000000000..e7210902982
--- /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 00000000000..80aa3d222bd
--- /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 00000000000..ef22119dac5
--- /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 00000000000..cb0dc808718
--- /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 4cc8e0b2b17..924c421bcae 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 c3f811017c8..52200e9128f 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 882163d0a7f..b984c04d07a 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 ea3bb7ddd30..03c0736d469 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 be6d81c7e96..6ece91d1eff 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 47792284334..69d532f894f 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 63dd2d201d2..c264ee0c4f8 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 a38edd0785f..3620b2bf16d 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 *);
OpenPOWER on IntegriCloud