public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Fold vector to scalar optimization
@ 2010-11-01 20:21 Artem Shinkarov
  2010-11-02 11:04 ` Richard Guenther
  0 siblings, 1 reply; 12+ messages in thread
From: Artem Shinkarov @ 2010-11-01 20:21 UTC (permalink / raw)
  To: gcc-patches; +Cc: Joseph S. Myers, Richard Guenther

[-- Attachment #1: Type: text/plain, Size: 522 bytes --]

This patch folds a vector of equal values to the scalar in
vector-shift operation.

ChangeLog:

2010-11-01  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>

     gcc/
     * passes.c (init_optimization_passes): Move veclower after SSA.
     * tree-vect-generic.c (expand_vector_operations_1): Handle conversion.

     gcc/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.


bootstrapped and tested on x86_64_unknown-linux

OK?

[-- Attachment #2: vec-scal-opt.c.v2.diff --]
[-- Type: text/x-diff, Size: 6640 bytes --]

Index: gcc/testsuite/gcc.dg/vec-scal-opt2.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt2.c	(revision 0)
@@ -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,2,3,4,5,6,7};
+   vector(8, short) v1 = {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: gcc/testsuite/gcc.dg/vec-scal-opt.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt.c	(revision 0)
@@ -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,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" } } */
Index: gcc/testsuite/gcc.dg/vec-scal-opt1.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt1.c	(revision 0)
@@ -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,2,3,4,5,6,7};
+   vector(8, short) r1;
+
+   r1 = v0 >> (vector(8, short)){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" } } */
Index: gcc/tree-vect-generic.c
===================================================================
--- gcc/tree-vect-generic.c	(revision 166126)
+++ gcc/tree-vect-generic.c	(working copy)
@@ -392,7 +392,7 @@ expand_vector_operations_1 (gimple_stmt_
   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;
 
@@ -436,8 +436,72 @@ expand_vector_operations_1 (gimple_stmt_
     {
       /* If the 2nd argument is vector, we need a vector/vector shift */
       if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2))))
-	op = optab_for_tree_code (code, type, optab_vector);
-      else
+        {
+          /* Chack 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 (TREE_CODE (rhs2) == SSA_NAME
+              && TREE_CODE (TREE_TYPE (rhs2)) == VECTOR_TYPE)
+            {
+              gimple def_stmt;
+              def_stmt = SSA_NAME_DEF_STMT (rhs2);
+
+              if (gimple_assign_single_p (def_stmt))
+                {
+                  tree var = gimple_assign_rhs1 (def_stmt);
+
+                  /* Check for {cst,cst,cst,...} case.  */
+                  if (TREE_CODE (var) == VECTOR_CST)
+                    {
+                      tree first, t, els = TREE_VECTOR_CST_ELTS (var);
+                      bool eq = true;
+                      
+                      first = TREE_VALUE (els);
+                      els = TREE_CHAIN (els);
+
+                      for (t = els; t; t = TREE_CHAIN (t))
+                        if (!(eq = operand_equal_p (first, TREE_VALUE(t), 0)))
+                          break;
+
+                      if (eq) /* All the elements are the same.  */
+                        {
+                          gimple_assign_set_rhs2 (stmt, first);
+                          update_stmt (stmt);
+                          rhs2 = first;
+                        }
+                    }
+                  /* Check for {x,x,x,...} case.  */
+                  else if (TREE_CODE (var) == CONSTRUCTOR)
+                    {
+                      tree t, first = error_mark_node;
+                      bool eq = true;
+                      unsigned HOST_WIDE_INT i;
+
+                      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (var), i, t)
+                        {
+                          if (i == 0)
+                            {
+                              first = t;
+                              continue;
+                            }
+                          if (!(eq = (first == t)))
+                            break;
+                        }
+                      
+                      if (eq) /* All the elements are the same.  */
+                        {
+                          gimple_assign_set_rhs2 (stmt, first);
+                          update_stmt (stmt);
+                          rhs2 = first;
+                        }
+                    }
+                }
+            }
+          else    
+            op = optab_for_tree_code (code, type, optab_vector);
+        }
+
+      if (!VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2))))
 	{
 	  /* Try for a vector/scalar shift, and if we don't have one, see if we
 	     have a vector/vector shift */
Index: gcc/passes.c
===================================================================
--- gcc/passes.c	(revision 166126)
+++ gcc/passes.c	(working copy)
@@ -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.,

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fold vector to scalar optimization
  2010-11-01 20:21 Fold vector to scalar optimization Artem Shinkarov
@ 2010-11-02 11:04 ` Richard Guenther
  2010-11-02 16:20   ` Artem Shinkarov
  0 siblings, 1 reply; 12+ messages in thread
From: Richard Guenther @ 2010-11-02 11:04 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: gcc-patches, Joseph S. Myers

On Mon, Nov 1, 2010 at 9:11 PM, Artem Shinkarov
<artyom.shinkaroff@gmail.com> wrote:
> This patch folds a vector of equal values to the scalar in
> vector-shift operation.
>
> ChangeLog:
>
> 2010-11-01  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
>
>     gcc/
>     * passes.c (init_optimization_passes): Move veclower after SSA.
>     * tree-vect-generic.c (expand_vector_operations_1): Handle conversion.
>
>     gcc/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.
>
>
> bootstrapped and tested on x86_64_unknown-linux
>
> OK?

@@ -436,8 +436,72 @@ expand_vector_operations_1 (gimple_stmt_
     {
       /* If the 2nd argument is vector, we need a vector/vector shift */
       if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2))))
-       op = optab_for_tree_code (code, type, optab_vector);
-      else
+        {
+          /* Chack whether we have vector <op> {x,x,x,x} where x

Typo.  'Check'

+             could be a scalar variable or a constant. Transform
+             vector <op> {x,x,x,x} ==> vector <op> scalar.  */
+          if (TREE_CODE (rhs2) == SSA_NAME
+              && TREE_CODE (TREE_TYPE (rhs2)) == VECTOR_TYPE)

So this misses the case when rhs2 is a VECTOR_CST.  Also in
case we have such a constant vector but then no support for
vector <<>> scalar we wil expand it again.  So I think it's better
to check the two case up-front and only rewrite the shift operand
if the scalar variant is supported.

For less gratious indents please split recognizing a vector with
all the same elements into a separate function like
bool uniform_vector_p (tree vector).

Thanks,
Richard.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fold vector to scalar optimization
  2010-11-02 11:04 ` Richard Guenther
@ 2010-11-02 16:20   ` Artem Shinkarov
  2010-11-02 18:58     ` Richard Henderson
  0 siblings, 1 reply; 12+ messages in thread
From: Artem Shinkarov @ 2010-11-02 16:20 UTC (permalink / raw)
  To: Richard Guenther; +Cc: gcc-patches, Joseph S. Myers

[-- Attachment #1: Type: text/plain, Size: 2405 bytes --]

Here is a version with the fixes.

ChangeLog:

2010-11-01  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>

    gcc/
    * passes.c (init_optimization_passes): Move veclower after SSA.
    * tree-vect-generic.c (expand_vector_operations_1): Handle conversion.

    gcc/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.


bootstrapped and tested on x86_64_unknown-linux

Ok?


On Tue, Nov 2, 2010 at 11:03 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Mon, Nov 1, 2010 at 9:11 PM, Artem Shinkarov
> <artyom.shinkaroff@gmail.com> wrote:
>> This patch folds a vector of equal values to the scalar in
>> vector-shift operation.
>>
>> ChangeLog:
>>
>> 2010-11-01  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
>>
>>     gcc/
>>     * passes.c (init_optimization_passes): Move veclower after SSA.
>>     * tree-vect-generic.c (expand_vector_operations_1): Handle conversion.
>>
>>     gcc/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.
>>
>>
>> bootstrapped and tested on x86_64_unknown-linux
>>
>> OK?
>
> @@ -436,8 +436,72 @@ expand_vector_operations_1 (gimple_stmt_
>     {
>       /* If the 2nd argument is vector, we need a vector/vector shift */
>       if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2))))
> -       op = optab_for_tree_code (code, type, optab_vector);
> -      else
> +        {
> +          /* Chack whether we have vector <op> {x,x,x,x} where x
>
> Typo.  'Check'
>
> +             could be a scalar variable or a constant. Transform
> +             vector <op> {x,x,x,x} ==> vector <op> scalar.  */
> +          if (TREE_CODE (rhs2) == SSA_NAME
> +              && TREE_CODE (TREE_TYPE (rhs2)) == VECTOR_TYPE)
>
> So this misses the case when rhs2 is a VECTOR_CST.  Also in
> case we have such a constant vector but then no support for
> vector <<>> scalar we wil expand it again.  So I think it's better
> to check the two case up-front and only rewrite the shift operand
> if the scalar variant is supported.
>
> For less gratious indents please split recognizing a vector with
> all the same elements into a separate function like
> bool uniform_vector_p (tree vector).
>
> Thanks,
> Richard.
>

[-- Attachment #2: vec-scal-opt.c.v3.diff --]
[-- Type: text/x-diff, Size: 7545 bytes --]

Index: gcc/testsuite/gcc.dg/vec-scal-opt2.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt2.c	(revision 0)
@@ -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: gcc/testsuite/gcc.dg/vec-scal-opt.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt.c	(revision 0)
@@ -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" } } */
Index: gcc/testsuite/gcc.dg/vec-scal-opt1.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt1.c	(revision 0)
@@ -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" } } */
Index: gcc/tree-vect-generic.c
===================================================================
--- gcc/tree-vect-generic.c	(revision 166126)
+++ gcc/tree-vect-generic.c	(working copy)
@@ -284,6 +284,58 @@ expand_vector_addition (gimple_stmt_iter
 				    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.
+   Function sets ELEMENT with the first element of the vector
+   or NULL_TREE if comparison failed.  */
+static bool uniform_vector_p (tree vec, tree *element)
+{
+  tree first, t, els;
+  bool eq = true;
+  unsigned HOST_WIDE_INT i;
+
+  *element = NULL_TREE;
+
+  if (vec == NULL_TREE)
+    return false;
+
+  if (TREE_CODE (vec) == VECTOR_CST)
+    {
+      els = TREE_VECTOR_CST_ELTS (vec);
+      first = TREE_VALUE (els);
+      els = TREE_CHAIN (els);
+
+      for (t = els, i = 0; t; t = TREE_CHAIN (t), i++)
+        if (!(eq = operand_equal_p (first, TREE_VALUE(t), 0)))
+          break;
+
+      *element = first;
+      return eq && (i == TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec))-1);
+    }
+
+  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 (!(eq = (first == t)))
+            break;
+        }
+      
+      *element = first;
+      return eq && (i == TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec)));
+      
+    }
+  
+  return false;
+}
+
 static tree
 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
 			 gimple assign, enum tree_code code)
@@ -392,7 +444,7 @@ expand_vector_operations_1 (gimple_stmt_
   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 +486,44 @@ expand_vector_operations_1 (gimple_stmt_
       || 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, var = NULL_TREE;
+          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 && (var = rhs2))
+                  ||
+                  (TREE_CODE (rhs2) == SSA_NAME 
+                   && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
+                   && gimple_assign_single_p (def_stmt)
+                   && (var = gimple_assign_rhs1 (def_stmt))))
+              && uniform_vector_p (var, &first))
+                {
+                  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);
Index: gcc/passes.c
===================================================================
--- gcc/passes.c	(revision 166126)
+++ gcc/passes.c	(working copy)
@@ -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.,

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fold vector to scalar optimization
  2010-11-02 16:20   ` Artem Shinkarov
@ 2010-11-02 18:58     ` Richard Henderson
  2010-11-03 11:47       ` Artem Shinkarov
  0 siblings, 1 reply; 12+ messages in thread
From: Richard Henderson @ 2010-11-02 18:58 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: Richard Guenther, gcc-patches, Joseph S. Myers

> +        if (!(eq = operand_equal_p (first, TREE_VALUE(t), 0)))
...
> +          if (!(eq = (first == t)))

Do not bury assignments inside conditionals.


r~

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fold vector to scalar optimization
  2010-11-02 18:58     ` Richard Henderson
@ 2010-11-03 11:47       ` Artem Shinkarov
  2010-11-03 12:18         ` Nathan Froyd
  0 siblings, 1 reply; 12+ messages in thread
From: Artem Shinkarov @ 2010-11-03 11:47 UTC (permalink / raw)
  To: Richard Henderson; +Cc: Richard Guenther, gcc-patches, Joseph S. Myers

[-- Attachment #1: Type: text/plain, Size: 283 bytes --]

All right, here we go.

On Tue, Nov 2, 2010 at 6:57 PM, Richard Henderson <rth@redhat.com> wrote:
>> +        if (!(eq = operand_equal_p (first, TREE_VALUE(t), 0)))
> ...
>> +          if (!(eq = (first == t)))
>
> Do not bury assignments inside conditionals.
>
>
> r~
>

[-- Attachment #2: vec-scal-opt.c.v3.diff --]
[-- Type: text/x-diff, Size: 7711 bytes --]

Index: gcc/testsuite/gcc.dg/vec-scal-opt2.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt2.c	(revision 0)
@@ -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: gcc/testsuite/gcc.dg/vec-scal-opt.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt.c	(revision 0)
@@ -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" } } */
Index: gcc/testsuite/gcc.dg/vec-scal-opt1.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt1.c	(revision 0)
@@ -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" } } */
Index: gcc/tree-vect-generic.c
===================================================================
--- gcc/tree-vect-generic.c	(revision 166126)
+++ gcc/tree-vect-generic.c	(working copy)
@@ -284,6 +284,60 @@ expand_vector_addition (gimple_stmt_iter
 				    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.
+   Function sets ELEMENT with the first element of the vector
+   or NULL_TREE if comparison failed.  */
+static bool uniform_vector_p (tree vec, tree *element)
+{
+  tree first, t, els;
+  bool eq = true;
+  unsigned HOST_WIDE_INT i;
+
+  *element = NULL_TREE;
+
+  if (vec == NULL_TREE)
+    return false;
+
+  if (TREE_CODE (vec) == VECTOR_CST)
+    {
+      els = TREE_VECTOR_CST_ELTS (vec);
+      first = TREE_VALUE (els);
+      els = TREE_CHAIN (els);
+
+      for (t = els, i = 0; t; t = TREE_CHAIN (t), i++)
+        eq = operand_equal_p (first, TREE_VALUE(t), 0);
+        if (!eq)
+          break;
+
+      *element = first;
+      return eq && (i == TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec))-1);
+    }
+
+  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;
+            }
+          eq = (first == t);
+          if (!eq)
+            break;
+        }
+      
+      *element = first;
+      return eq && (i == TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec)));
+      
+    }
+  
+  return false;
+}
+
 static tree
 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
 			 gimple assign, enum tree_code code)
@@ -392,7 +446,7 @@ expand_vector_operations_1 (gimple_stmt_
   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 +488,48 @@ expand_vector_operations_1 (gimple_stmt_
       || code == LROTATE_EXPR
       || code == RROTATE_EXPR)
     {
-      /* If the 2nd argument is vector, we need a vector/vector shift */
+      bool vector_scalar_shift;
+      tree x = build_int_cst (integer_type_node, 2);
+
+      warning (0, x == build_int_cst (integer_type_node, 2) ? "Yes" : "No");
+      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, var = NULL_TREE;
+          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 && (var = rhs2))
+                  ||
+                  (TREE_CODE (rhs2) == SSA_NAME 
+                   && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
+                   && gimple_assign_single_p (def_stmt)
+                   && (var = gimple_assign_rhs1 (def_stmt))))
+              && uniform_vector_p (var, &first))
+                {
+                  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);
Index: gcc/passes.c
===================================================================
--- gcc/passes.c	(revision 166126)
+++ gcc/passes.c	(working copy)
@@ -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.,

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fold vector to scalar optimization
  2010-11-03 11:47       ` Artem Shinkarov
@ 2010-11-03 12:18         ` Nathan Froyd
  2010-11-03 13:23           ` Artem Shinkarov
  0 siblings, 1 reply; 12+ messages in thread
From: Nathan Froyd @ 2010-11-03 12:18 UTC (permalink / raw)
  To: Artem Shinkarov
  Cc: Richard Henderson, Richard Guenther, gcc-patches, Joseph S. Myers

On Wed, Nov 03, 2010 at 11:45:26AM +0000, Artem Shinkarov wrote:
> On Tue, Nov 2, 2010 at 6:57 PM, Richard Henderson <rth@redhat.com> wrote:
> > Do not bury assignments inside conditionals.
>
> All right, here we go.
>
> Index: gcc/tree-vect-generic.c
> ===================================================================
> --- gcc/tree-vect-generic.c	(revision 166126)
> +++ gcc/tree-vect-generic.c	(working copy)
> @@ -284,6 +284,60 @@ expand_vector_addition (gimple_stmt_iter
>  				    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.
> +   Function sets ELEMENT with the first element of the vector
> +   or NULL_TREE if comparison failed.  */
> +static bool uniform_vector_p (tree vec, tree *element)
> +{
> ...
> +      for (t = els, i = 0; t; t = TREE_CHAIN (t), i++)
> +        eq = operand_equal_p (first, TREE_VALUE(t), 0);
> +        if (!eq)
> +          break;

When unburying assignments, please make sure that the new code has the
same semantics as the old.

-Nathan

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fold vector to scalar optimization
  2010-11-03 12:18         ` Nathan Froyd
@ 2010-11-03 13:23           ` Artem Shinkarov
  2010-11-03 16:26             ` Richard Henderson
  0 siblings, 1 reply; 12+ messages in thread
From: Artem Shinkarov @ 2010-11-03 13:23 UTC (permalink / raw)
  To: Nathan Froyd
  Cc: Richard Henderson, Richard Guenther, gcc-patches, Joseph S. Myers

[-- Attachment #1: Type: text/plain, Size: 1460 bytes --]

Oops. Thanks for that, also removed some debugging info. Tested and
bootstrapped.

Can someone approve this, cause there are patches waiting that depend
on this one.



Thanks,
Artem.


On Wed, Nov 3, 2010 at 11:59 AM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> On Wed, Nov 03, 2010 at 11:45:26AM +0000, Artem Shinkarov wrote:
>> On Tue, Nov 2, 2010 at 6:57 PM, Richard Henderson <rth@redhat.com> wrote:
>> > Do not bury assignments inside conditionals.
>>
>> All right, here we go.
>>
>> Index: gcc/tree-vect-generic.c
>> ===================================================================
>> --- gcc/tree-vect-generic.c   (revision 166126)
>> +++ gcc/tree-vect-generic.c   (working copy)
>> @@ -284,6 +284,60 @@ expand_vector_addition (gimple_stmt_iter
>>                                   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.
>> +   Function sets ELEMENT with the first element of the vector
>> +   or NULL_TREE if comparison failed.  */
>> +static bool uniform_vector_p (tree vec, tree *element)
>> +{
>> ...
>> +      for (t = els, i = 0; t; t = TREE_CHAIN (t), i++)
>> +        eq = operand_equal_p (first, TREE_VALUE(t), 0);
>> +        if (!eq)
>> +          break;
>
> When unburying assignments, please make sure that the new code has the
> same semantics as the old.
>
> -Nathan
>

[-- Attachment #2: vec-scal-opt.c.v4.diff --]
[-- Type: text/x-diff, Size: 7605 bytes --]

Index: gcc/testsuite/gcc.dg/vec-scal-opt2.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt2.c	(revision 0)
@@ -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: gcc/testsuite/gcc.dg/vec-scal-opt.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt.c	(revision 0)
@@ -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" } } */
Index: gcc/testsuite/gcc.dg/vec-scal-opt1.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt1.c	(revision 0)
@@ -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" } } */
Index: gcc/tree-vect-generic.c
===================================================================
--- gcc/tree-vect-generic.c	(revision 166126)
+++ gcc/tree-vect-generic.c	(working copy)
@@ -284,6 +284,62 @@ expand_vector_addition (gimple_stmt_iter
 				    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.
+   Function sets ELEMENT with the first element of the vector
+   or NULL_TREE if comparison failed.  */
+static bool uniform_vector_p (tree vec, tree *element)
+{
+  tree first, t, els;
+  bool eq = true;
+  unsigned HOST_WIDE_INT i;
+
+  *element = NULL_TREE;
+
+  if (vec == NULL_TREE)
+    return false;
+
+  if (TREE_CODE (vec) == VECTOR_CST)
+    {
+      els = TREE_VECTOR_CST_ELTS (vec);
+      first = TREE_VALUE (els);
+      els = TREE_CHAIN (els);
+
+      for (t = els, i = 0; t; t = TREE_CHAIN (t), i++)
+        {
+          eq = operand_equal_p (first, TREE_VALUE(t), 0);
+          if (!eq)
+            break;
+        }
+
+      *element = first;
+      return eq && (i == TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec))-1);
+    }
+
+  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;
+            }
+          eq = (first == t);
+          if (!eq)
+            break;
+        }
+      
+      *element = first;
+      return eq && (i == TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec)));
+      
+    }
+  
+  return false;
+}
+
 static tree
 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
 			 gimple assign, enum tree_code code)
@@ -392,7 +448,7 @@ expand_vector_operations_1 (gimple_stmt_
   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 +490,45 @@ expand_vector_operations_1 (gimple_stmt_
       || 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, var = NULL_TREE;
+          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 && (var = rhs2))
+                  ||
+                  (TREE_CODE (rhs2) == SSA_NAME 
+                   && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
+                   && gimple_assign_single_p (def_stmt)
+                   && (var = gimple_assign_rhs1 (def_stmt))))
+              && uniform_vector_p (var, &first))
+                {
+                  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);
Index: gcc/passes.c
===================================================================
--- gcc/passes.c	(revision 166126)
+++ gcc/passes.c	(working copy)
@@ -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.,

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fold vector to scalar optimization
  2010-11-03 13:23           ` Artem Shinkarov
@ 2010-11-03 16:26             ` Richard Henderson
  2010-11-03 18:20               ` Artem Shinkarov
  0 siblings, 1 reply; 12+ messages in thread
From: Richard Henderson @ 2010-11-03 16:26 UTC (permalink / raw)
  To: Artem Shinkarov
  Cc: Nathan Froyd, Richard Guenther, gcc-patches, Joseph S. Myers

> +          if (vector_scalar_shift 
> +              && ((TREE_CODE (rhs2) == VECTOR_CST && (var = rhs2))
> +                  ||
> +                  (TREE_CODE (rhs2) == SSA_NAME 
> +                   && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
> +                   && gimple_assign_single_p (def_stmt)
> +                   && (var = gimple_assign_rhs1 (def_stmt))))
> +              && uniform_vector_p (var, &first))
> +                {
> +                  gimple_assign_set_rhs2 (stmt, first);
> +                  update_stmt (stmt);
> +                  rhs2 = first;
> +                }

Fix the indentation on the { } block and the patch is ok.


r~

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fold vector to scalar optimization
  2010-11-03 16:26             ` Richard Henderson
@ 2010-11-03 18:20               ` Artem Shinkarov
  2010-11-03 21:09                 ` Richard Guenther
  0 siblings, 1 reply; 12+ messages in thread
From: Artem Shinkarov @ 2010-11-03 18:20 UTC (permalink / raw)
  To: Richard Henderson
  Cc: Nathan Froyd, Richard Guenther, gcc-patches, Joseph S. Myers

[-- Attachment #1: Type: text/plain, Size: 1170 bytes --]

ChangeLog:

2010-11-01  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>

    gcc/
    * passes.c (init_optimization_passes): Move veclower after SSA.
    * tree-vect-generic.c (expand_vector_operations_1): Handle conversion.

    gcc/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.


On Wed, Nov 3, 2010 at 4:25 PM, Richard Henderson <rth@redhat.com> wrote:
>> +          if (vector_scalar_shift
>> +              && ((TREE_CODE (rhs2) == VECTOR_CST && (var = rhs2))
>> +                  ||
>> +                  (TREE_CODE (rhs2) == SSA_NAME
>> +                   && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
>> +                   && gimple_assign_single_p (def_stmt)
>> +                   && (var = gimple_assign_rhs1 (def_stmt))))
>> +              && uniform_vector_p (var, &first))
>> +                {
>> +                  gimple_assign_set_rhs2 (stmt, first);
>> +                  update_stmt (stmt);
>> +                  rhs2 = first;
>> +                }
>
> Fix the indentation on the { } block and the patch is ok.
>
>
> r~
>

[-- Attachment #2: vec-scal-opt.c.v5.diff --]
[-- Type: text/x-diff, Size: 7583 bytes --]

Index: gcc/testsuite/gcc.dg/vec-scal-opt2.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt2.c	(revision 0)
@@ -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: gcc/testsuite/gcc.dg/vec-scal-opt.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt.c	(revision 0)
@@ -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" } } */
Index: gcc/testsuite/gcc.dg/vec-scal-opt1.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt1.c	(revision 0)
@@ -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" } } */
Index: gcc/tree-vect-generic.c
===================================================================
--- gcc/tree-vect-generic.c	(revision 166249)
+++ gcc/tree-vect-generic.c	(working copy)
@@ -284,6 +284,62 @@ expand_vector_addition (gimple_stmt_iter
 				    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.
+   Function sets ELEMENT with the first element of the vector
+   or NULL_TREE if comparison failed.  */
+static bool uniform_vector_p (tree vec, tree *element)
+{
+  tree first, t, els;
+  bool eq = true;
+  unsigned HOST_WIDE_INT i;
+
+  *element = NULL_TREE;
+
+  if (vec == NULL_TREE)
+    return false;
+
+  if (TREE_CODE (vec) == VECTOR_CST)
+    {
+      els = TREE_VECTOR_CST_ELTS (vec);
+      first = TREE_VALUE (els);
+      els = TREE_CHAIN (els);
+
+      for (t = els, i = 0; t; t = TREE_CHAIN (t), i++)
+        {
+          eq = operand_equal_p (first, TREE_VALUE(t), 0);
+          if (!eq)
+            break;
+        }
+
+      *element = first;
+      return eq && (i == TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec))-1);
+    }
+
+  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;
+            }
+          eq = (first == t);
+          if (!eq)
+            break;
+        }
+      
+      *element = first;
+      return eq && (i == TYPE_VECTOR_SUBPARTS (TREE_TYPE (vec)));
+      
+    }
+  
+  return false;
+}
+
 static tree
 expand_vector_operation (gimple_stmt_iterator *gsi, tree type, tree compute_type,
 			 gimple assign, enum tree_code code)
@@ -392,7 +448,7 @@ expand_vector_operations_1 (gimple_stmt_
   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 +490,45 @@ expand_vector_operations_1 (gimple_stmt_
       || 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, var = NULL_TREE;
+          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 && (var = rhs2))
+                  ||
+                  (TREE_CODE (rhs2) == SSA_NAME 
+                   && (def_stmt = SSA_NAME_DEF_STMT (rhs2))
+                   && gimple_assign_single_p (def_stmt)
+                   && (var = gimple_assign_rhs1 (def_stmt))))
+              && uniform_vector_p (var, &first))
+            {
+              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);
Index: gcc/passes.c
===================================================================
--- gcc/passes.c	(revision 166249)
+++ gcc/passes.c	(working copy)
@@ -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.,

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fold vector to scalar optimization
  2010-11-03 18:20               ` Artem Shinkarov
@ 2010-11-03 21:09                 ` Richard Guenther
  2010-11-05 11:34                   ` Ramana Radhakrishnan
  0 siblings, 1 reply; 12+ messages in thread
From: Richard Guenther @ 2010-11-03 21:09 UTC (permalink / raw)
  To: Artem Shinkarov
  Cc: Richard Henderson, Nathan Froyd, gcc-patches, Joseph S. Myers

[-- Attachment #1: Type: text/plain, Size: 1084 bytes --]

On Wed, Nov 3, 2010 at 7:11 PM, Artem Shinkarov
<artyom.shinkaroff@gmail.com> wrote:
> ChangeLog:
>
> 2010-11-01  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
>
>    gcc/
>    * passes.c (init_optimization_passes): Move veclower after SSA.
>    * tree-vect-generic.c (expand_vector_operations_1): Handle conversion.
>
>    gcc/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.

I am retesting the following variant which I slightly changed and will commit it
after that succeeded.

Richard.

2010-11-03  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.

        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.

[-- Attachment #2: vec-scal-opt.c.v5.diff --]
[-- Type: text/x-patch, Size: 8291 bytes --]

2010-11-03  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.

	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.

Index: gcc/testsuite/gcc.dg/vec-scal-opt2.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt2.c	(revision 0)
@@ -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: gcc/testsuite/gcc.dg/vec-scal-opt.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt.c	(revision 0)
@@ -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" } } */
Index: gcc/testsuite/gcc.dg/vec-scal-opt1.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt1.c	(revision 0)
@@ -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" } } */
Index: gcc/passes.c
===================================================================
--- gcc/passes.c	(revision 166249)
+++ gcc/passes.c	(working copy)
@@ -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: gcc/tree-vect-generic.c
===================================================================
*** gcc/tree-vect-generic.c	(revision 166275)
--- gcc/tree-vect-generic.c	(working copy)
*************** expand_vector_addition (gimple_stmt_iter
*** 284,289 ****
--- 284,339 ----
  				    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;
+   bool eq = true;
+   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)
*************** expand_vector_operations_1 (gimple_stmt_
*** 392,398 ****
    tree lhs, rhs1, rhs2 = NULL, type, compute_type;
    enum tree_code code;
    enum machine_mode compute_mode;
!   optab op;
    enum gimple_rhs_class rhs_class;
    tree new_rhs;
  
--- 442,448 ----
    tree lhs, rhs1, rhs2 = NULL, type, compute_type;
    enum tree_code code;
    enum machine_mode compute_mode;
!   optab op = NULL;
    enum gimple_rhs_class rhs_class;
    tree new_rhs;
  
*************** expand_vector_operations_1 (gimple_stmt_
*** 434,451 ****
        || code == LROTATE_EXPR
        || code == RROTATE_EXPR)
      {
!       /* If the 2nd argument is vector, we need a vector/vector shift */
        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);
! 	}
      }
    else
      op = optab_for_tree_code (code, type, optab_default);
--- 484,527 ----
        || code == LROTATE_EXPR
        || code == RROTATE_EXPR)
      {
!       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))))
!         {
!           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 (var)) != NULL_TREE)
! 		  || (TREE_CODE (rhs2) == SSA_NAME 
! 		      && (def_stmt = SSA_NAME_DEF_STMT (rhs2)) != NULL_TREE
! 		      && 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);

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: Fold vector to scalar optimization
  2010-11-03 21:09                 ` Richard Guenther
@ 2010-11-05 11:34                   ` Ramana Radhakrishnan
  0 siblings, 0 replies; 12+ messages in thread
From: Ramana Radhakrishnan @ 2010-11-05 11:34 UTC (permalink / raw)
  To: Richard Guenther
  Cc: Artem Shinkarov, Richard Henderson, Nathan Froyd, gcc-patches,
	Joseph S. Myers

On Wed, Nov 3, 2010 at 9:04 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Wed, Nov 3, 2010 at 7:11 PM, Artem Shinkarov
> <artyom.shinkaroff@gmail.com> wrote:
>> ChangeLog:
>>
>> 2010-11-01  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
>>
>>    gcc/
>>    * passes.c (init_optimization_passes): Move veclower after SSA.
>>    * tree-vect-generic.c (expand_vector_operations_1): Handle conversion.
>>
>>    gcc/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.
>
> I am retesting the following variant which I slightly changed and will commit it
> after that succeeded.


This caused http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46312 .

Ramana

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Fold vector to scalar optimization
@ 2010-06-18 16:25 Artem Shinkarov
  0 siblings, 0 replies; 12+ messages in thread
From: Artem Shinkarov @ 2010-06-18 16:25 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1055 bytes --]

This patch was inspired by the previous patch I was working on
http://gcc.gnu.org/ml/gcc-patches/2010-06/msg01511.html and it should
be commited to the trunk only when vector shifting patch would be
commited. In other case the tests would not work.

The patch itself converts an operation "vector1 >> vector2" to
"vector1 >> scalar" if all the elements of the vector2 are the same.
At the moment the patch would not catch chains of variable assignmenrs
like:

b = x;
a = b;
c = a;
vec1 >> {x,a,b,c}

because the vector lowering is happening too early, though the
optimization could be moved down later.

ChangeLog:

2010-06-18  Artem Shinkarov <artyom.shinakroff@gmail.com>

      * passes.c (init_optimization_passes): Move veclower after SSA.
      * tree-vect-generic.c (expand_vector_operations_1): Handle conversion.

      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.


bootstrapped and tested on x86_64_unknown-linux

OK?



-- 
Artem Shinkarov

[-- Attachment #2: vec-scal-opt.diff --]
[-- Type: text/x-diff, Size: 6362 bytes --]

Index: gcc/passes.c
===================================================================
--- gcc/passes.c	(revision 160943)
+++ gcc/passes.c	(working copy)
@@ -737,7 +737,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);
@@ -765,6 +764,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: gcc/tree-vect-generic.c
===================================================================
--- gcc/tree-vect-generic.c	(revision 160943)
+++ gcc/tree-vect-generic.c	(working copy)
@@ -436,8 +436,72 @@ expand_vector_operations_1 (gimple_stmt_
     {
       /* If the 2nd argument is vector, we need a vector/vector shift */
       if (VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2))))
-	op = optab_for_tree_code (code, type, optab_vector);
-      else
+        {
+          /* Chack 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 (TREE_CODE (rhs2) == SSA_NAME
+              && TREE_CODE (TREE_TYPE (rhs2)) == VECTOR_TYPE)
+            {
+              gimple def_stmt;
+              def_stmt = SSA_NAME_DEF_STMT (rhs2);
+
+              if (gimple_assign_single_p (def_stmt))
+                {
+                  tree var = gimple_assign_rhs1 (def_stmt);
+
+                  /* Check for {cst,cst,cst,...} case.  */
+                  if (TREE_CODE (var) == VECTOR_CST)
+                    {
+                      tree first, t, els = TREE_VECTOR_CST_ELTS (var);
+                      bool eq = true;
+                      
+                      first = TREE_VALUE (els);
+                      els = TREE_CHAIN (els);
+
+                      for (t = els; t; t = TREE_CHAIN (t))
+                        if (!(eq = operand_equal_p (first, TREE_VALUE(t), 0)))
+                          break;
+
+                      if (eq) /* All the elements are the same.  */
+                        {
+                          gimple_assign_set_rhs2 (stmt, first);
+                          update_stmt (stmt);
+                          rhs2 = first;
+                        }
+                    }
+                  /* Check for {x,x,x,...} case.  */
+                  else if (TREE_CODE (var) == CONSTRUCTOR)
+                    {
+                      tree first, t;
+                      bool eq = true;
+                      unsigned HOST_WIDE_INT i;
+
+                      FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (var), i, t)
+                        {
+                          if (i == 0)
+                            {
+                              first = t;
+                              continue;
+                            }
+                          if (!(eq = (first == t)))
+                            break;
+                        }
+                      
+                      if (eq) /* All the elements are the same.  */
+                        {
+                          gimple_assign_set_rhs2 (stmt, first);
+                          update_stmt (stmt);
+                          rhs2 = first;
+                        }
+                    }
+                }
+            }
+          else    
+            op = optab_for_tree_code (code, type, optab_vector);
+        }
+
+      if (!VECTOR_MODE_P (TYPE_MODE (TREE_TYPE (rhs2))))
 	{
 	  /* Try for a vector/scalar shift, and if we don't have one, see if we
 	     have a vector/vector shift */
Index: gcc/testsuite/gcc.dg/vec-scal-opt1.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt1.c	(revision 0)
@@ -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,2,3,4,5,6,7};
+   vector(8, short) r1;
+
+   r1 = v0 >> (vector(8, short)){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" } } */
Index: gcc/testsuite/gcc.dg/vec-scal-opt2.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt2.c	(revision 0)
@@ -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,2,3,4,5,6,7};
+   vector(8, short) v1 = {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: gcc/testsuite/gcc.dg/vec-scal-opt.c
===================================================================
--- gcc/testsuite/gcc.dg/vec-scal-opt.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vec-scal-opt.c	(revision 0)
@@ -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,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" } } */

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2010-11-05 11:24 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-11-01 20:21 Fold vector to scalar optimization Artem Shinkarov
2010-11-02 11:04 ` Richard Guenther
2010-11-02 16:20   ` Artem Shinkarov
2010-11-02 18:58     ` Richard Henderson
2010-11-03 11:47       ` Artem Shinkarov
2010-11-03 12:18         ` Nathan Froyd
2010-11-03 13:23           ` Artem Shinkarov
2010-11-03 16:26             ` Richard Henderson
2010-11-03 18:20               ` Artem Shinkarov
2010-11-03 21:09                 ` Richard Guenther
2010-11-05 11:34                   ` Ramana Radhakrishnan
  -- strict thread matches above, loose matches on Subject: below --
2010-06-18 16:25 Artem Shinkarov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).