OSDN Git Service

* tree-data-ref.c (build_classic_dist_vector,
authordpatel <dpatel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Apr 2005 01:35:54 +0000 (01:35 +0000)
committerdpatel <dpatel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 12 Apr 2005 01:35:54 +0000 (01:35 +0000)
         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.

         * 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.

         * 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.

         * gcc.dg/vect/vect-dv-1.c: New test.
         * gcc.dg/vect/vect-dv-2.c: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@97999 138bc75d-0d04-0410-961f-82ee72b054a4

20 files changed:
gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vect/vect-dv-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-dv-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-ifcvt-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-ifcvt-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-ifcvt-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-ifcvt-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-ifcvt-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-ifcvt-6.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-ifcvt-7.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-ifcvt-9.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vect/vect-none.c
gcc/testsuite/lib/target-supports.exp
gcc/tree-data-ref.c
gcc/tree-data-ref.h
gcc/tree-vect-analyze.c
gcc/tree-vect-transform.c
gcc/tree-vectorizer.c
gcc/tree-vectorizer.h

index a43ccf4..bc5f1a3 100644 (file)
@@ -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
index 5271167..e7d40f8 100644 (file)
@@ -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 (file)
index 0000000..20fe1be
--- /dev/null
@@ -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 (file)
index 0000000..dfcfc64
--- /dev/null
@@ -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 (file)
index 0000000..385e2d1
--- /dev/null
@@ -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 (file)
index 0000000..d270154
--- /dev/null
@@ -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 (file)
index 0000000..46dafa5
--- /dev/null
@@ -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 (file)
index 0000000..2fc5b21
--- /dev/null
@@ -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 (file)
index 0000000..e721090
--- /dev/null
@@ -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 (file)
index 0000000..80aa3d2
--- /dev/null
@@ -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 (file)
index 0000000..ef22119
--- /dev/null
@@ -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 (file)
index 0000000..cb0dc80
--- /dev/null
@@ -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" } } */
index 4cc8e0b..924c421 100644 (file)
@@ -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" } } */
index c3f8110..52200e9 100644 (file)
@@ -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
index 882163d..b984c04 100644 (file)
@@ -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)
 {
index ea3bb7d..03c0736 100644 (file)
@@ -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);
 
 
 \f
index be6d81c..6ece91d 100644 (file)
@@ -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.  */
 
index 4779228..69d532f 100644 (file)
@@ -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.");
index 63dd2d2..c264ee0 100644 (file)
@@ -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;
 \f
 /*************************************************************************
   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;
index a38edd0..3620b2b 100644 (file)
@@ -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 *);