passes.c (init_optimization_passes): Move veclower after SSA.
authorArtjoms Sinkarovs <artyom.shinkaroff@gmail.com>
Thu, 4 Nov 2010 10:54:33 +0000 (10:54 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 4 Nov 2010 10:54:33 +0000 (10:54 +0000)
2010-11-04  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
Richard Guenther  <rguenther@suse.de>

* passes.c (init_optimization_passes): Move veclower after SSA.
* tree-vect-generic.c (uniform_vector_p): New function.
(expand_vector_operations_1): Handle conversion.
(pass_lower_vector): Update SSA form.

testsuite/
* gcc.dg/vec-scal-opt.c: New testcase.
* gcc.dg/vec-scal-opt1.c: New testcase.
* gcc.dg/vec-scal-opt2.c: New testcase.

From-SVN: r166303

gcc/ChangeLog
gcc/passes.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/vec-scal-opt.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vec-scal-opt1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vec-scal-opt2.c [new file with mode: 0644]
gcc/tree-vect-generic.c

index 712366c8846d0256feb94c30aba9ec606975454d..7c903436186b67e39cc204a25f1e53adc447aae6 100644 (file)
@@ -1,3 +1,11 @@
+2010-11-04  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
+       Richard Guenther  <rguenther@suse.de>
+
+       * passes.c (init_optimization_passes): Move veclower after SSA.
+       * tree-vect-generic.c (uniform_vector_p): New function.
+       (expand_vector_operations_1): Handle conversion.
+       (pass_lower_vector): Update SSA form.
+
 2010-11-04  Iain Sandoe  <iains@gcc.gnu.org>
 
        * gcc/configure.ac: Filter -mdynamic-no-pic from CFLAGS when testing for
index 1ee3400e0cac15bf66dcd31d880cdb3cdbaa03bb..5da5ea8ab6cd954b96aa69076037743980060028 100644 (file)
@@ -736,7 +736,6 @@ init_optimization_passes (void)
   NEXT_PASS (pass_refactor_eh);
   NEXT_PASS (pass_lower_eh);
   NEXT_PASS (pass_build_cfg);
-  NEXT_PASS (pass_lower_vector);
   NEXT_PASS (pass_warn_function_return);
   NEXT_PASS (pass_build_cgraph_edges);
   NEXT_PASS (pass_inline_parameters);
@@ -755,6 +754,7 @@ init_optimization_passes (void)
 
       NEXT_PASS (pass_referenced_vars);
       NEXT_PASS (pass_build_ssa);
+      NEXT_PASS (pass_lower_vector);
       NEXT_PASS (pass_early_warn_uninitialized);
       /* Note that it is not strictly necessary to schedule an early
         inline pass here.  However, some test cases (e.g.,
index bbcf32deb2885b4fba37c654b4cdca201503db1e..e76da86e091827c6c0e4154b019dc9729af8f15a 100644 (file)
@@ -1,7 +1,14 @@
+2010-11-04  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
+       Richard Guenther  <rguenther@suse.de>
+
+       * gcc.dg/vec-scal-opt.c: New testcase.
+       * gcc.dg/vec-scal-opt1.c: New testcase.
+       * gcc.dg/vec-scal-opt2.c: New testcase.
+
 2010-11-04  Iain Sandoe  <iains@gcc.gnu.org>
 
-       * lib/plugin-support.exp (plugin-test-execute): Filter -mdynamic-no-pic from
-       plugin build flags on Darwin targets.
+       * lib/plugin-support.exp (plugin-test-execute): Filter -mdynamic-no-pic
+       from plugin build flags on Darwin targets.
 
 2010-11-03  H.J. Lu  <hongjiu.lu@intel.com>
 
diff --git a/gcc/testsuite/gcc.dg/vec-scal-opt.c b/gcc/testsuite/gcc.dg/vec-scal-opt.c
new file mode 100644 (file)
index 0000000..0af49cf
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-veclower" } */
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+short k;
+
+int main (int argc, char *argv[]) {
+   k = argc;
+   vector(8, short) v0 = {argc,1,2,3,4,5,6,7};
+   vector(8, short) v2 = {k,   k,k,k,k,k,k,k};
+   vector(8, short) r1;
+
+   r1 = v0 >> v2;
+
+   return vidx(short, r1, 0);
+}
+
+/* { dg-final { scan-tree-dump-times ">> k.\[0-9_\]*" 1 "veclower" } } */
+/* { dg-final { cleanup-tree-dump "veclower" } } */
diff --git a/gcc/testsuite/gcc.dg/vec-scal-opt1.c b/gcc/testsuite/gcc.dg/vec-scal-opt1.c
new file mode 100644 (file)
index 0000000..e4ef8a9
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-veclower" } */
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+short k;
+
+int main (int argc, char *argv[]) {
+   vector(8, short) v0 = {argc,1,2,3,4,5,6,7};
+   vector(8, short) r1;
+
+   r1 = v0 >> (vector(8, short)){2,2,2,2,2,2,2,2};
+
+   return vidx(short, r1, 0);
+}
+
+/* { dg-final { scan-tree-dump-times ">> 2" 1 "veclower" } } */
+/* { dg-final { cleanup-tree-dump "veclower" } } */
diff --git a/gcc/testsuite/gcc.dg/vec-scal-opt2.c b/gcc/testsuite/gcc.dg/vec-scal-opt2.c
new file mode 100644 (file)
index 0000000..f9ed1bb
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-veclower" } */
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+   vector(8, short) v0 = {argc,1,2,3,4,5,6,7};
+   vector(8, short) v1 = {2,2,2,2,2,2,2,2};
+   vector(8, short) r1;
+
+   r1 = v0 >> v1;
+
+   return vidx(short, r1, 0);
+}
+
+/* { dg-final { scan-tree-dump-times ">> 2" 1 "veclower" } } */
+/* { dg-final { cleanup-tree-dump "veclower" } } */
index 1fd29629e6649e70284a5bbe164f74a14ae45bd8..3f582402443dc05fcc22f2f61031bca62906a74a 100644 (file)
@@ -284,6 +284,55 @@ expand_vector_addition (gimple_stmt_iterator *gsi,
                                    a, b, code);
 }
 
+/* Check if vector VEC consists of all the equal elements and
+   that the number of elements corresponds to the type of VEC.
+   The function returns first element of the vector
+   or NULL_TREE if the vector is not uniform.  */
+static tree
+uniform_vector_p (tree vec)
+{
+  tree first, t, els;
+  unsigned i;
+
+  if (vec == NULL_TREE)
+    return NULL_TREE;
+
+  if (TREE_CODE (vec) == VECTOR_CST)
+    {
+      els = TREE_VECTOR_CST_ELTS (vec);
+      first = TREE_VALUE (els);
+      els = TREE_CHAIN (els);
+
+      for (t = els; t; t = TREE_CHAIN (t))
+       if (!operand_equal_p (first, TREE_VALUE (t), 0))
+         return NULL_TREE;
+
+      return first;
+    }
+
+  else if (TREE_CODE (vec) == CONSTRUCTOR)
+    {
+      first = error_mark_node;
+
+      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (vec), i, t)
+        {
+          if (i == 0)
+            {
+              first = t;
+              continue;
+            }
+         if (!operand_equal_p (first, t, 0))
+           return NULL_TREE;
+        }
+      if (i != TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec)))
+       return NULL_TREE;
+      
+      return first;
+    }
+  
+  return NULL_TREE;
+}
+
 static tree
 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
                         gimple assign, enum tree_code code)
@@ -392,7 +441,7 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
   tree lhs, rhs1, rhs2 = NULL, type, compute_type;
   enum tree_code code;
   enum machine_mode compute_mode;
-  optab op;
+  optab op = NULL;
   enum gimple_rhs_class rhs_class;
   tree new_rhs;
 
@@ -434,18 +483,44 @@ expand_vector_operations_1 (gimple_stmt_iterator *gsi)
       || code == LROTATE_EXPR
       || code == RROTATE_EXPR)
     {
-      /* If the 2nd argument is vector, we need a vector/vector shift */
+      bool vector_scalar_shift;
+      op = optab_for_tree_code (code, type, optab_scalar);
+      
+      /* Vector/Scalar shift is supported.  */
+      vector_scalar_shift = (op && (optab_handler (op, TYPE_MODE (type)) 
+                                   != CODE_FOR_nothing));
+
+      /* If the 2nd argument is vector, we need a vector/vector shift.
+         Except all the elements in the second vector are the same.  */
       if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2))))
-       op = optab_for_tree_code (code, type, optab_vector);
-      else
-       {
-         /* Try for a vector/scalar shift, and if we don't have one, see if we
-            have a vector/vector shift */
-         op = optab_for_tree_code (code, type, optab_scalar);
-         if (!op
-             || optab_handler (op, TYPE_MODE (type)) == CODE_FOR_nothing)
-           op = optab_for_tree_code (code, type, optab_vector);
-       }
+        {
+          tree first;
+          gimple def_stmt;
+
+          /* Check whether we have vector <op> {x,x,x,x} where x
+             could be a scalar variable or a constant. Transform
+             vector <op> {x,x,x,x} ==> vector <op> scalar.  */
+          if (vector_scalar_shift 
+              && ((TREE_CODE (rhs2) == VECTOR_CST
+                  && (first = uniform_vector_p (rhs2)) != NULL_TREE)
+                 || (TREE_CODE (rhs2) == SSA_NAME 
+                     && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
+                     && gimple_assign_single_p (def_stmt)
+                     && (first = uniform_vector_p
+                           (gimple_assign_rhs1 (def_stmt))) != NULL_TREE)))
+            {
+              gimple_assign_set_rhs2 (stmt, first);
+              update_stmt (stmt);
+              rhs2 = first;
+            }
+          else
+            op = optab_for_tree_code (code, type, optab_vector);
+        }
+    
+      /* Try for a vector/scalar shift, and if we don't have one, see if we
+         have a vector/vector shift */
+      else if (!vector_scalar_shift)
+        op = optab_for_tree_code (code, type, optab_vector);
     }
   else
     op = optab_for_tree_code (code, type, optab_default);
@@ -559,8 +634,9 @@ struct gimple_opt_pass pass_lower_vector =
   0,                                   /* properties_provided */
   0,                                   /* properties_destroyed */
   0,                                   /* todo_flags_start */
-  TODO_dump_func | TODO_ggc_collect
-    | TODO_verify_stmts                        /* todo_flags_finish */
+  TODO_dump_func | TODO_update_ssa     /* todo_flags_finish */
+    | TODO_verify_ssa
+    | TODO_verify_stmts | TODO_verify_flow
  }
 };