public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* Vector shifting patch
@ 2010-06-15 16:02 Artem Shinkarov
  2010-06-15 17:03 ` Andrew Pinski
  0 siblings, 1 reply; 35+ messages in thread
From: Artem Shinkarov @ 2010-06-15 16:02 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Guenther

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

This is a reworked Andrew Pinski's vector shifting patch. This is done
in terms of GSoC 2010 project.

The C part is separated from C++ part and is submitted as a separate patch.
OpenCL standard allows vector <op> scalar, scalar <op> vector
operations, for op = +,-,*,/,%. In that case scalar is converted to
the vector. Cannot see any reason why we would not want to support
these type of operations for shifting. So this is added to the patch
as well.

ChangeLog:

2010-06-14  Artem Shinkarov <artyom.shinakroff@gmail.com>
      Andrew Pinski <pinskia@gmail.com>

      * c-family/tree.h (build_vector_from_val): Declare.
      * c-family/tree.c (build_vector_from_val): New function.
      * c-typeck.c (build_binary_op): Handle vector shifting.

      testsuite/
      * gcc.c-torture/execute/vector-shift.c: Likewise.
      * gcc.c-torture/execute/vector-shift1.c: New testcase.

      doc/
      * extend.texi: Document vector shifting.

bootstrapped and tested on x86_64_unknown-linux

OK?

-- 
Artem Shinkarov

[-- Attachment #2: vectorshift.c.v2.diff --]
[-- Type: text/x-diff, Size: 9692 bytes --]

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 160565)
+++ gcc/doc/extend.texi	(working copy)
@@ -6119,7 +6119,7 @@ produce code that uses 4 @code{SIs}.
 
 The types defined in this manner can be used with a subset of normal C
 operations.  Currently, GCC will allow using the following operators
-on these types: @code{+, -, *, /, unary minus, ^, |, &, ~, %}@.
+on these types: @code{+, -, *, /, unary minus, ^, |, &, ~, %, <<, >>}@.
 
 The operations behave like C++ @code{valarrays}.  Addition is defined as
 the addition of the corresponding elements of the operands.  For
@@ -6135,6 +6135,22 @@ v4si a, b, c;
 c = a + b;
 @end smallexample
 
+Shifting operators @code{<<, >>} support integer vector operands doing
+element-wise shifting.  Additionally one of the operands can be a
+scalar integer in which case the scalar is converted to the type used
+by the vector operand and each element of this new vector is the
+scalar's value.  Consider the following code.
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a, b, c;
+int i = 1;
+
+b = a >> 1;     /* b = a >> {1,1,1,1}; */
+c = 1 << a;     /* c = {1,1,1,1} << a; */
+@end smallexample
+
 Subtraction, multiplication, division, and the logical operations
 operate in a similar manner.  Likewise, the result of using the unary
 minus or complement operators on a vector type is a vector whose
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 160565)
+++ gcc/tree.c	(working copy)
@@ -1312,6 +1312,23 @@ build_vector_from_ctor (tree type, VEC(c
   return build_vector (type, nreverse (list));
 }
 
+/* Build a vector of type VECTYPE where all the elements are SCs.  */
+tree
+build_vector_from_val (const tree sc, const tree vectype) 
+{
+  tree t = NULL_TREE;
+  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
+
+  gcc_assert (sc == error_mark_node
+              || TREE_TYPE (sc) == TREE_TYPE (vectype));
+
+  for (i = 0; i < nunits; ++i)
+    t = tree_cons (NULL_TREE, sc, t);
+
+  return build_vector (vectype, t);
+}
+
+
 /* Return a new CONSTRUCTOR node whose type is TYPE and whose values
    are in the VEC pointed to by VALS.  */
 tree
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 160565)
+++ gcc/tree.h	(working copy)
@@ -4020,6 +4020,7 @@ extern tree build_int_cst_type (tree, HO
 extern tree build_int_cst_wide (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
 extern tree build_vector (tree, tree);
 extern tree build_vector_from_ctor (tree, VEC(constructor_elt,gc) *);
+extern tree build_vector_from_val (const tree, const tree);
 extern tree build_constructor (tree, VEC(constructor_elt,gc) *);
 extern tree build_constructor_single (tree, tree, tree);
 extern tree build_constructor_from_list (tree, tree);
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
@@ -0,0 +1,47 @@
+
+#define vector __attribute__((vector_size(sizeof(int)*4) ))
+
+static vector int allones = {1, 1, 1, 1};
+static vector int allzeros = {0, 0, 0, 0};
+static vector int numbers = {0, 1, 2, 3};
+static vector int numbersleftshiftallones = {0, 2, 4, 6};
+static vector int numbersrightshiftallones = {0, 0, 1, 1};
+
+
+static vector unsigned int uallones = {1, 1, 1, 1};
+static vector unsigned int uallzeros = {0, 0, 0, 0};
+static vector unsigned int unumbers = {0, 1, 2, 3};
+static vector unsigned int unumbersleftshiftallones = {0, 2, 4, 6};
+static vector unsigned int unumbersrightshiftallones = {0, 0, 1, 1};
+
+#define TEST(result, expected) \
+do { \
+  typeof(result) result1 = result; \
+  if(sizeof (result1) != sizeof (expected)) \
+    __builtin_abort (); \
+  if (__builtin_memcmp (&result1, &expected, sizeof(result1)) != 0) \
+    __builtin_abort (); \
+}while (0);
+
+int main(void)
+{
+  vector int result;
+  TEST ((numbers << allzeros), numbers);
+  TEST ((numbers >> allzeros), numbers);
+  TEST((numbers << allones), numbersleftshiftallones);
+  TEST((numbers >> allones), numbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((numbers << allones) >> allones, numbers);
+  
+  
+  
+  TEST ((unumbers << uallzeros), unumbers);
+  TEST ((unumbers >> uallzeros), unumbers);
+  TEST((unumbers << uallones), unumbersleftshiftallones);
+  TEST((unumbers >> uallones), unumbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((unumbers << uallones) >> uallones, unumbers);
+  
+}
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
@@ -0,0 +1,16 @@
+#define vector __attribute__((vector_size(16) ))
+
+int main (int argc, char *argv[]) {
+  vector short v0 = {argc,2,3,4,5,6,7};
+  vector short v1 = {2,2,2,2,2,2,2};
+  vector short r1,r2,r3,r4;
+  int i = 8;
+
+  r1 = v0 << 1;
+  r2 = 1 << v0;
+
+  r3 = v0 << v1;
+  r4 = v0 >> v1;
+
+  return 0;
+}
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 160565)
+++ gcc/c-typeck.c	(working copy)
@@ -9373,6 +9373,32 @@ build_binary_op (location_t location, en
 
   objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
 
+  /* For most of binary operations in case we have 'vector <op> scalar'
+     or 'scalar <op> vector', we convert a scalar to a vector. For shifts 
+     truncating the shift amount is ok. For constants we just check the 
+     boundaries.  */
+  if ((code0 == VECTOR_TYPE || code1 == VECTOR_TYPE)
+      && (code0 != code1))
+    {
+      switch (code)
+        {
+          case RSHIFT_EXPR:
+          case LSHIFT_EXPR:
+            if (code0 == INTEGER_TYPE)
+              {
+                tree sc = save_expr (op0);
+                sc = convert (TREE_TYPE (type1), sc);
+                op0 = build_vector_from_val (sc, type1);
+                orig_type0 = type0 = TREE_TYPE (op0);
+                code0 = TREE_CODE (type0);
+              }
+            break;
+
+          default:
+            break;
+        }
+    }
+
   switch (code)
     {
     case PLUS_EXPR:
@@ -9534,7 +9560,21 @@ build_binary_op (location_t location, en
 	 Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9561,9 +9601,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
@@ -9571,7 +9612,21 @@ build_binary_op (location_t location, en
       break;
 
     case LSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9593,9 +9648,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;

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

* Re: Vector shifting patch
  2010-06-15 16:02 Vector shifting patch Artem Shinkarov
@ 2010-06-15 17:03 ` Andrew Pinski
  2010-06-16 11:41   ` Richard Guenther
  0 siblings, 1 reply; 35+ messages in thread
From: Andrew Pinski @ 2010-06-15 17:03 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: gcc-patches, Richard Guenther

On Tue, Jun 15, 2010 at 8:17 AM, Artem Shinkarov
<artyom.shinkaroff@gmail.com> wrote:
> This is a reworked Andrew Pinski's vector shifting patch. This is done
> in terms of GSoC 2010 project.
>
> The C part is separated from C++ part and is submitted as a separate patch.
> OpenCL standard allows vector <op> scalar, scalar <op> vector
> operations, for op = +,-,*,/,%. In that case scalar is converted to
> the vector. Cannot see any reason why we would not want to support
> these type of operations for shifting. So this is added to the patch
> as well.

You add a test to test for vector of floats that should be rejected.

+                sc = convert (TREE_TYPE (type1), sc);
+                op0 = build_vector_from_val (sc, type1);

Why don't you push the convert down into the build_vector_from_val.

+  gcc_assert (sc == error_mark_node
+              || TREE_TYPE (sc) == TREE_TYPE (vectype));

I think there could be a case where sc is error_mark_node which case
you should just return error_mark_node..
An example is:
#define vector __attribute__((vector_size(4*sizeof(int) )))
void g(void)
{
  vector int t;
  t <<= d; /* { dg-error "undeclared" }  */
}
--- CUT ---
How does your patch handle the case where <<= is used and the left
hand side is an integer type like:

#define vector __attribute__((vector_size(4*sizeof(int) )))
void g(void)
{
  vector int t;
  int d;
  d <<= t; /* { dg-error "" }  */
}

--- CUT ---
+typedef int v4si __attribute__ ((vector_size (16)));
I think that would be better if you do this:
+typedef int v4si __attribute__ ((vector_size (4*sizeof(int) )));

So that it is really v4 and I would name it v4int rather than saying
the internal GCC mode.

Some more from Joseph S. Myers' review of my patch which is why it was
not applied yet:

Do I understand correctly that it is also intended that the vectors must
have the same width and number of elements (but possibly different
signedness)?

If so, the testcases should cover this (errors for different width, errors
for different number of elements, allowing different signedness, errors if
either vector is floating point).

The tests should also verify that signed shift operations where the sign
bit is involved act as documented in implement-c.texi for individual
elements, and should test unsigned shift operations where the result
differs from that of signed shift (right shifting values with the top bit
set).  It would also be good to run tests for different base types and
vector lengths (after all, the conversion to scalar code could generate
things such as shifts on types smaller than int that wouldn't arise
directly in normal C code, so it may not be obvious that it's well-tested
whether such operations on char or short work correctly at present,
although certainly valid GIMPLE), and to test shift count vectors that do
not have all counts equal.

--- CUT ---

Thanks,
Andrew Pinski

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

* Re: Vector shifting patch
  2010-06-15 17:03 ` Andrew Pinski
@ 2010-06-16 11:41   ` Richard Guenther
  2010-06-18 14:04     ` Artem Shinkarov
  0 siblings, 1 reply; 35+ messages in thread
From: Richard Guenther @ 2010-06-16 11:41 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: Artem Shinkarov, gcc-patches

On Tue, Jun 15, 2010 at 6:33 PM, Andrew Pinski <pinskia@gmail.com> wrote:
> On Tue, Jun 15, 2010 at 8:17 AM, Artem Shinkarov
> <artyom.shinkaroff@gmail.com> wrote:
>> This is a reworked Andrew Pinski's vector shifting patch. This is done
>> in terms of GSoC 2010 project.
>>
>> The C part is separated from C++ part and is submitted as a separate patch.
>> OpenCL standard allows vector <op> scalar, scalar <op> vector
>> operations, for op = +,-,*,/,%. In that case scalar is converted to
>> the vector. Cannot see any reason why we would not want to support
>> these type of operations for shifting. So this is added to the patch
>> as well.
>
> You add a test to test for vector of floats that should be rejected.
>
> +                sc = convert (TREE_TYPE (type1), sc);
> +                op0 = build_vector_from_val (sc, type1);
>
> Why don't you push the convert down into the build_vector_from_val.

I asked him not to, convert shouldn't be called from generic
tree routines (I'd like to use build_vector_from_val from the
vectorizer as well).

> +  gcc_assert (sc == error_mark_node
> +              || TREE_TYPE (sc) == TREE_TYPE (vectype));
>
> I think there could be a case where sc is error_mark_node which case
> you should just return error_mark_node..
> An example is:
> #define vector __attribute__((vector_size(4*sizeof(int) )))
> void g(void)
> {
>  vector int t;
>  t <<= d; /* { dg-error "undeclared" }  */
> }
> --- CUT ---

True, that's a good suggestion.

> How does your patch handle the case where <<= is used and the left
> hand side is an integer type like:
>
> #define vector __attribute__((vector_size(4*sizeof(int) )))
> void g(void)
> {
>  vector int t;
>  int d;
>  d <<= t; /* { dg-error "" }  */
> }
>
> --- CUT ---
> +typedef int v4si __attribute__ ((vector_size (16)));
> I think that would be better if you do this:
> +typedef int v4si __attribute__ ((vector_size (4*sizeof(int) )));
>
> So that it is really v4 and I would name it v4int rather than saying
> the internal GCC mode.
>
> Some more from Joseph S. Myers' review of my patch which is why it was
> not applied yet:
>
> Do I understand correctly that it is also intended that the vectors must
> have the same width and number of elements (but possibly different
> signedness)?

I think we can allow arbitrary integer types as long as the vectors
have the same number of elements.  At least if the Cell or OpenCL
spec do not put other restrictions on the element types.

> If so, the testcases should cover this (errors for different width, errors
> for different number of elements, allowing different signedness, errors if
> either vector is floating point).

That would be indeed nice to have.

> The tests should also verify that signed shift operations where the sign
> bit is involved act as documented in implement-c.texi for individual
> elements, and should test unsigned shift operations where the result
> differs from that of signed shift (right shifting values with the top bit
> set).

It might be the case that if the operation  maps to hardware instructions
the vector hardware behaves differently, so I suppose implement-c.texi
should be adjusted accordingly (or, as those operations are not
standard C, the vector extension documentation should be amended
that the implementation might not follow implement-c.texi?)

>  It would also be good to run tests for different base types and
> vector lengths (after all, the conversion to scalar code could generate
> things such as shifts on types smaller than int that wouldn't arise
> directly in normal C code, so it may not be obvious that it's well-tested
> whether such operations on char or short work correctly at present,
> although certainly valid GIMPLE), and to test shift count vectors that do
> not have all counts equal.

More exhaustive testsuite coverage would be indeed nice.

Richard.

> --- CUT ---
>
> Thanks,
> Andrew Pinski
>

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

* Re: Vector shifting patch
  2010-06-16 11:41   ` Richard Guenther
@ 2010-06-18 14:04     ` Artem Shinkarov
  2010-06-18 21:45       ` Andrew Pinski
  0 siblings, 1 reply; 35+ messages in thread
From: Artem Shinkarov @ 2010-06-18 14:04 UTC (permalink / raw)
  To: Richard Guenther; +Cc: Andrew Pinski, gcc-patches

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

Thank you everyone for comments. Here is a new version of the patch
which considers all the comments.

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

     * tree.h (build_vector_from_val): Declare.
     * tree.c (build_vector_from_val): New function.
     * c-typeck.c (build_binary_op): Handle vector shifting.

     testsuite/
     * gcc.c-torture/execute/vector-shift.c: Likewise.
     * gcc.c-torture/execute/vector-shift1.c: New testcase.
     * gcc.c-torture/execute/vector-shift1.c: New testcase.
     * gcc.dg/vector-shift.c: New testcase.
     * gcc.dg/vector-shift1.c: New testcase.
     * gcc.dg/vector-shift2.c: New testcase.

     doc/
     * extend.texi: Document vector shifting.

bootstrapped and tested on x86_64_unknown-linux

OK?

[-- Attachment #2: vectorshift.c.v4.diff --]
[-- Type: text/x-diff, Size: 15002 bytes --]

Index: gcc/testsuite/gcc.c-torture/execute/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
@@ -0,0 +1,17 @@
+#define vector __attribute__((vector_size(8*sizeof(short))))
+
+int main (int argc, char *argv[]) {
+  vector short v0 = {argc,2,3,4,5,6,7};
+  vector short v1 = {2,2,2,2,2,2,2};
+  vector short r1,r2,r3,r4;
+  int i = 8;
+
+  r1 = v0 << 1;
+  r2 = 1 << v0;
+
+  r3 = v0 << v1;
+  r4 = v0 >> v1;
+
+  return 0;
+}
+
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
@@ -0,0 +1,60 @@
+/* dg-do run */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uint unsigned int
+
+int main (int argc, char *argv[]) {
+    vector(4, uint) vuint  = { 1,  2,  3,  4};
+    vector(4,  int) vint0  = { 1,  1,  1,  1};
+    vector(4,  int) vint1  = {-1, -1, -1, -1};
+
+    vector(4,  int) i1, i2, i3;
+    vector(4, uint) u1, u2, u3;
+
+    i1 = vint1<< vint0;
+    
+    if (vidx(int, i1, 0) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 1) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 2) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 3) != ((int)-1 << (int)1))
+        __builtin_abort ();
+
+    u1 = vuint << vint0;
+
+    if (vidx(int, u1, 0) != ((uint)1  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 1) != ((uint)2  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 2) != ((uint)3  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 3) != ((uint)4  << (int)1))
+        __builtin_abort ();
+
+    
+    i2 = vint1 >> vuint;
+
+    if (vidx(int, i2, 0) != ((int)-1  >> (uint)1))
+        __builtin_abort ();
+    if (vidx(int, i2, 1) != ((int)-1  >> (uint)2))
+        __builtin_abort ();
+    if (vidx(int, i2, 2) != ((int)-1  >> (uint)3))
+        __builtin_abort ();
+    if (vidx(int, i2, 3) != ((int)-1  >> (uint)4))
+        __builtin_abort ();
+
+
+    vint1 >>= vuint;
+    
+    vuint <<= vint0;
+    vuint <<= vint1;
+
+
+    return 0;
+}
+
+
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
@@ -0,0 +1,47 @@
+
+#define vector __attribute__((vector_size(sizeof(int)*4) ))
+
+static vector int allones = {1, 1, 1, 1};
+static vector int allzeros = {0, 0, 0, 0};
+static vector int numbers = {0, 1, 2, 3};
+static vector int numbersleftshiftallones = {0, 2, 4, 6};
+static vector int numbersrightshiftallones = {0, 0, 1, 1};
+
+
+static vector unsigned int uallones = {1, 1, 1, 1};
+static vector unsigned int uallzeros = {0, 0, 0, 0};
+static vector unsigned int unumbers = {0, 1, 2, 3};
+static vector unsigned int unumbersleftshiftallones = {0, 2, 4, 6};
+static vector unsigned int unumbersrightshiftallones = {0, 0, 1, 1};
+
+#define TEST(result, expected) \
+do { \
+  typeof(result) result1 = result; \
+  if(sizeof (result1) != sizeof (expected)) \
+    __builtin_abort (); \
+  if (__builtin_memcmp (&result1, &expected, sizeof(result1)) != 0) \
+    __builtin_abort (); \
+}while (0);
+
+int main(void)
+{
+  vector int result;
+  TEST ((numbers << allzeros), numbers);
+  TEST ((numbers >> allzeros), numbers);
+  TEST((numbers << allones), numbersleftshiftallones);
+  TEST((numbers >> allones), numbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((numbers << allones) >> allones, numbers);
+  
+  
+  
+  TEST ((unumbers << uallzeros), unumbers);
+  TEST ((unumbers >> uallzeros), unumbers);
+  TEST((unumbers << uallones), unumbersleftshiftallones);
+  TEST((unumbers >> uallones), unumbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((unumbers << uallones) >> uallones, unumbers);
+  
+}
Index: gcc/testsuite/gcc.dg/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4, float) vfloat0 = {1., 2., 3., 4.};
+    vector(4, float) vfloat1 = {1., 2., 3., 4.};
+    
+    vector(4,   int) vint   = {1,  1,  1,  1 };
+    
+    vint <<= vfloat0;  /* { dg-error "nvalid operands to binary <<" } */
+    vfloat0 >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    vfloat0 <<= vfloat1;  /* { dg-error "nvalid operands to binary <<" } */
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+/* { dg-options "-fno-var-tracking-assignments" } */
+
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uchar unsigned char
+
+#define ch14 1,2,3,4
+#define ch1  1,1,1,1
+#define chm1 -1,-1,-1,-1
+
+int main (int argc, char *argv[]) {
+    vector(16, uchar) vuchar  = { ch14, ch14, ch14, ch14};
+    vector(16,  char) vchar0  = { ch1, ch1, ch1, ch1};
+    vector(16,  char) vchar1  = { chm1, chm1, chm1, chm1};
+
+    vector(16,  char) i1, i2, i3;
+    vector(16, uchar) u1, u2, u3;
+
+    i1 = vchar1<< vchar0;
+    
+    if (vidx(char, i1, 0) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 1) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 2) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 3) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    u1 = vuchar << vchar0;
+
+    if (vidx(char, u1, 0) != ((uchar)1  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 1) != ((uchar)2  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 2) != ((uchar)3  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 3) != ((uchar)4  << (char)1))
+        __builtin_abort ();
+
+    
+    i2 = vchar1 >> vuchar;
+
+    if (vidx(char, i2, 0) != ((char)-1  >> (uchar)1))
+        __builtin_abort ();
+    if (vidx(char, i2, 1) != ((char)-1  >> (uchar)2))
+        __builtin_abort ();
+    if (vidx(char, i2, 2) != ((char)-1  >> (uchar)3))
+        __builtin_abort ();
+    if (vidx(char, i2, 3) != ((char)-1  >> (uchar)4))
+        __builtin_abort ();
+    
+    vchar1 >>= vuchar;
+    vuchar <<= vchar0;
+    vuchar <<= vchar1;
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4,char) vchar = {1,2,3,4};
+    vector(4, int) vint  = {1,1,1,1};
+    
+    vint <<= vchar;  /* { dg-error "nvalid operands to binary <<" } */
+    vchar >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    return 0;
+}
+
+
+
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 160943)
+++ gcc/c-typeck.c	(working copy)
@@ -9374,6 +9374,30 @@ build_binary_op (location_t location, en
 
   objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
 
+  /* For 'vector <shift> scalar' or 'scalar <shift> vector', we convert 
+     a scalar to a vector. Truncating the shift amount is ok.  */
+  if ((code0 == VECTOR_TYPE || code1 == VECTOR_TYPE)
+      && (code0 != code1))
+    {
+      switch (code)
+        {
+          case RSHIFT_EXPR:
+          case LSHIFT_EXPR:
+            if (code0 == INTEGER_TYPE)
+              {
+                tree sc = save_expr (op0);
+                sc = convert (TREE_TYPE (type1), sc);
+                op0 = build_vector_from_val (sc, type1);
+                orig_type0 = type0 = TREE_TYPE (op0);
+                code0 = TREE_CODE (type0);
+              }
+            break;
+
+          default:
+            break;
+        }
+    }
+
   switch (code)
     {
     case PLUS_EXPR:
@@ -9535,7 +9559,21 @@ build_binary_op (location_t location, en
 	 Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9562,9 +9600,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
@@ -9572,7 +9611,21 @@ build_binary_op (location_t location, en
       break;
 
     case LSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9594,9 +9647,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 160943)
+++ gcc/tree.c	(working copy)
@@ -1312,6 +1312,25 @@ build_vector_from_ctor (tree type, VEC(c
   return build_vector (type, nreverse (list));
 }
 
+/* Build a vector of type VECTYPE where all the elements are SCs.  */
+tree
+build_vector_from_val (const tree sc, const tree vectype) 
+{
+  tree t = NULL_TREE;
+  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
+
+  if (sc == error_mark_node)
+    return sc;
+
+  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
+
+  for (i = 0; i < nunits; ++i)
+    t = tree_cons (NULL_TREE, sc, t);
+
+  return build_vector (vectype, t);
+}
+
+
 /* Return a new CONSTRUCTOR node whose type is TYPE and whose values
    are in the VEC pointed to by VALS.  */
 tree
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 160943)
+++ gcc/tree.h	(working copy)
@@ -4028,6 +4028,7 @@ extern tree build_int_cst_type (tree, HO
 extern tree build_int_cst_wide (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
 extern tree build_vector (tree, tree);
 extern tree build_vector_from_ctor (tree, VEC(constructor_elt,gc) *);
+extern tree build_vector_from_val (const tree, const tree);
 extern tree build_constructor (tree, VEC(constructor_elt,gc) *);
 extern tree build_constructor_single (tree, tree, tree);
 extern tree build_constructor_from_list (tree, tree);
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 160943)
+++ gcc/doc/extend.texi	(working copy)
@@ -6119,7 +6119,7 @@ produce code that uses 4 @code{SIs}.
 
 The types defined in this manner can be used with a subset of normal C
 operations.  Currently, GCC will allow using the following operators
-on these types: @code{+, -, *, /, unary minus, ^, |, &, ~, %}@.
+on these types: @code{+, -, *, /, unary minus, ^, |, &, ~, %, <<, >>}@.
 
 The operations behave like C++ @code{valarrays}.  Addition is defined as
 the addition of the corresponding elements of the operands.  For
@@ -6135,6 +6135,22 @@ v4si a, b, c;
 c = a + b;
 @end smallexample
 
+Shifting operators @code{<<, >>} support integer vector operands doing
+element-wise shifting.  Additionally one of the operands can be a
+scalar integer in which case the scalar is converted to the type used
+by the vector operand and each element of this new vector is the
+scalar's value.  Consider the following code.
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a, b, c;
+int i = 1;
+
+b = a >> 1;     /* b = a >> {1,1,1,1}; */
+c = 1 << a;     /* c = {1,1,1,1} << a; */
+@end smallexample
+
 Subtraction, multiplication, division, and the logical operations
 operate in a similar manner.  Likewise, the result of using the unary
 minus or complement operators on a vector type is a vector whose

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

* Re: Vector shifting patch
  2010-06-18 14:04     ` Artem Shinkarov
@ 2010-06-18 21:45       ` Andrew Pinski
  2010-06-21 11:08         ` Artem Shinkarov
  0 siblings, 1 reply; 35+ messages in thread
From: Andrew Pinski @ 2010-06-18 21:45 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: Richard Guenther, gcc-patches

On Fri, Jun 18, 2010 at 5:32 AM, Artem Shinkarov
<artyom.shinkaroff@gmail.com> wrote:
> Thank you everyone for comments. Here is a new version of the patch
> which considers all the comments.

Hmm, Maybe I am missing something but I don't see a test that tests
what happens when one of the side of the shifters is an undefined
variable.  That test should be there as you changed
build_vector_from_val to fix that.

Thanks,
Andrew Pinski

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

* Re: Vector shifting patch
  2010-06-18 21:45       ` Andrew Pinski
@ 2010-06-21 11:08         ` Artem Shinkarov
  2010-10-25 17:04           ` Artem Shinkarov
  0 siblings, 1 reply; 35+ messages in thread
From: Artem Shinkarov @ 2010-06-21 11:08 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: Richard Guenther, gcc-patches

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

On Fri, Jun 18, 2010 at 7:26 PM, Andrew Pinski <pinskia@gmail.com> wrote:
> On Fri, Jun 18, 2010 at 5:32 AM, Artem Shinkarov
> <artyom.shinkaroff@gmail.com> wrote:
>> Thank you everyone for comments. Here is a new version of the patch
>> which considers all the comments.
>
> Hmm, Maybe I am missing something but I don't see a test that tests
> what happens when one of the side of the shifters is an undefined
> variable.  That test should be there as you changed
> build_vector_from_val to fix that.
>
> Thanks,
> Andrew Pinski
>

Yes, indeed, you are right. Sorry for that.

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

    * tree.h (build_vector_from_val): Declare.
    * tree.c (build_vector_from_val): New function.
    * c-typeck.c (build_binary_op): Handle vector shifting.

    testsuite/
    * gcc.c-torture/execute/vector-shift.c: Likewise.
    * gcc.c-torture/execute/vector-shift1.c: New testcase.
    * gcc.c-torture/execute/vector-shift2.c: New testcase.
    * gcc.dg/vector-shift.c: New testcase.
    * gcc.dg/vector-shift1.c: New testcase.
    * gcc.dg/vector-shift2.c: New testcase.
    * gcc.dg/vector-shift3.c: New testcase.
    * gcc.dg/vector-shift4.c: New testcase.


-- 
Artem Shinkarov

[-- Attachment #2: vectorshift.c.v5.diff --]
[-- Type: text/x-diff, Size: 16111 bytes --]

Index: gcc/testsuite/gcc.dg/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4, float) vfloat0 = {1., 2., 3., 4.};
+    vector(4, float) vfloat1 = {1., 2., 3., 4.};
+    
+    vector(4,   int) vint   = {1,  1,  1,  1 };
+    
+    vint <<= vfloat0;  /* { dg-error "nvalid operands to binary <<" } */
+    vfloat0 >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    vfloat0 <<= vfloat1;  /* { dg-error "nvalid operands to binary <<" } */
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+/* { dg-options "-fno-var-tracking-assignments" } */
+
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uchar unsigned char
+
+#define ch14 1,2,3,4
+#define ch1  1,1,1,1
+#define chm1 -1,-1,-1,-1
+
+int main (int argc, char *argv[]) {
+    vector(16, uchar) vuchar  = { ch14, ch14, ch14, ch14};
+    vector(16,  char) vchar0  = { ch1, ch1, ch1, ch1};
+    vector(16,  char) vchar1  = { chm1, chm1, chm1, chm1};
+
+    vector(16,  char) i1, i2, i3;
+    vector(16, uchar) u1, u2, u3;
+
+    i1 = vchar1<< vchar0;
+    
+    if (vidx(char, i1, 0) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 1) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 2) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 3) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    u1 = vuchar << vchar0;
+
+    if (vidx(char, u1, 0) != ((uchar)1  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 1) != ((uchar)2  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 2) != ((uchar)3  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 3) != ((uchar)4  << (char)1))
+        __builtin_abort ();
+
+    
+    i2 = vchar1 >> vuchar;
+
+    if (vidx(char, i2, 0) != ((char)-1  >> (uchar)1))
+        __builtin_abort ();
+    if (vidx(char, i2, 1) != ((char)-1  >> (uchar)2))
+        __builtin_abort ();
+    if (vidx(char, i2, 2) != ((char)-1  >> (uchar)3))
+        __builtin_abort ();
+    if (vidx(char, i2, 3) != ((char)-1  >> (uchar)4))
+        __builtin_abort ();
+    
+    vchar1 >>= vuchar;
+    vuchar <<= vchar0;
+    vuchar <<= vchar1;
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift3.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift3.c	(revision 0)
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+
+#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};
+    short sc;
+
+    
+    scalar1 <<= v0; /* { dg-error ".*scalar1.*undeclared" } */
+   
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift4.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift4.c	(revision 0)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+#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};
+    short sc;
+
+    v0 >>= scalar0; /* { dg-error ".*scalar0.*undeclared" } */
+    
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4,char) vchar = {1,2,3,4};
+    vector(4, int) vint  = {1,1,1,1};
+    
+    vint <<= vchar;  /* { dg-error "nvalid operands to binary <<" } */
+    vchar >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    return 0;
+}
+
+
+
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
@@ -0,0 +1,17 @@
+#define vector __attribute__((vector_size(8*sizeof(short))))
+
+int main (int argc, char *argv[]) {
+  vector short v0 = {argc,2,3,4,5,6,7};
+  vector short v1 = {2,2,2,2,2,2,2};
+  vector short r1,r2,r3,r4;
+  int i = 8;
+
+  r1 = v0 << 1;
+  r2 = 1 << v0;
+
+  r3 = v0 << v1;
+  r4 = v0 >> v1;
+
+  return 0;
+}
+
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
@@ -0,0 +1,60 @@
+/* dg-do run */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uint unsigned int
+
+int main (int argc, char *argv[]) {
+    vector(4, uint) vuint  = { 1,  2,  3,  4};
+    vector(4,  int) vint0  = { 1,  1,  1,  1};
+    vector(4,  int) vint1  = {-1, -1, -1, -1};
+
+    vector(4,  int) i1, i2, i3;
+    vector(4, uint) u1, u2, u3;
+
+    i1 = vint1<< vint0;
+    
+    if (vidx(int, i1, 0) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 1) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 2) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 3) != ((int)-1 << (int)1))
+        __builtin_abort ();
+
+    u1 = vuint << vint0;
+
+    if (vidx(int, u1, 0) != ((uint)1  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 1) != ((uint)2  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 2) != ((uint)3  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 3) != ((uint)4  << (int)1))
+        __builtin_abort ();
+
+    
+    i2 = vint1 >> vuint;
+
+    if (vidx(int, i2, 0) != ((int)-1  >> (uint)1))
+        __builtin_abort ();
+    if (vidx(int, i2, 1) != ((int)-1  >> (uint)2))
+        __builtin_abort ();
+    if (vidx(int, i2, 2) != ((int)-1  >> (uint)3))
+        __builtin_abort ();
+    if (vidx(int, i2, 3) != ((int)-1  >> (uint)4))
+        __builtin_abort ();
+
+
+    vint1 >>= vuint;
+    
+    vuint <<= vint0;
+    vuint <<= vint1;
+
+
+    return 0;
+}
+
+
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
@@ -0,0 +1,47 @@
+
+#define vector __attribute__((vector_size(sizeof(int)*4) ))
+
+static vector int allones = {1, 1, 1, 1};
+static vector int allzeros = {0, 0, 0, 0};
+static vector int numbers = {0, 1, 2, 3};
+static vector int numbersleftshiftallones = {0, 2, 4, 6};
+static vector int numbersrightshiftallones = {0, 0, 1, 1};
+
+
+static vector unsigned int uallones = {1, 1, 1, 1};
+static vector unsigned int uallzeros = {0, 0, 0, 0};
+static vector unsigned int unumbers = {0, 1, 2, 3};
+static vector unsigned int unumbersleftshiftallones = {0, 2, 4, 6};
+static vector unsigned int unumbersrightshiftallones = {0, 0, 1, 1};
+
+#define TEST(result, expected) \
+do { \
+  typeof(result) result1 = result; \
+  if(sizeof (result1) != sizeof (expected)) \
+    __builtin_abort (); \
+  if (__builtin_memcmp (&result1, &expected, sizeof(result1)) != 0) \
+    __builtin_abort (); \
+}while (0);
+
+int main(void)
+{
+  vector int result;
+  TEST ((numbers << allzeros), numbers);
+  TEST ((numbers >> allzeros), numbers);
+  TEST((numbers << allones), numbersleftshiftallones);
+  TEST((numbers >> allones), numbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((numbers << allones) >> allones, numbers);
+  
+  
+  
+  TEST ((unumbers << uallzeros), unumbers);
+  TEST ((unumbers >> uallzeros), unumbers);
+  TEST((unumbers << uallones), unumbersleftshiftallones);
+  TEST((unumbers >> uallones), unumbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((unumbers << uallones) >> uallones, unumbers);
+  
+}
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 160943)
+++ gcc/c-typeck.c	(working copy)
@@ -9374,6 +9374,30 @@ build_binary_op (location_t location, en
 
   objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
 
+  /* For 'vector <shift> scalar' or 'scalar <shift> vector', we convert 
+     a scalar to a vector. Truncating the shift amount is ok.  */
+  if ((code0 == VECTOR_TYPE || code1 == VECTOR_TYPE)
+      && (code0 != code1))
+    {
+      switch (code)
+        {
+          case RSHIFT_EXPR:
+          case LSHIFT_EXPR:
+            if (code0 == INTEGER_TYPE)
+              {
+                tree sc = save_expr (op0);
+                sc = convert (TREE_TYPE (type1), sc);
+                op0 = build_vector_from_val (sc, type1);
+                orig_type0 = type0 = TREE_TYPE (op0);
+                code0 = TREE_CODE (type0);
+              }
+            break;
+
+          default:
+            break;
+        }
+    }
+
   switch (code)
     {
     case PLUS_EXPR:
@@ -9535,7 +9559,21 @@ build_binary_op (location_t location, en
 	 Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9562,9 +9600,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
@@ -9572,7 +9611,21 @@ build_binary_op (location_t location, en
       break;
 
     case LSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9594,9 +9647,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 160943)
+++ gcc/tree.h	(working copy)
@@ -4028,6 +4028,7 @@ extern tree build_int_cst_type (tree, HO
 extern tree build_int_cst_wide (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
 extern tree build_vector (tree, tree);
 extern tree build_vector_from_ctor (tree, VEC(constructor_elt,gc) *);
+extern tree build_vector_from_val (const tree, const tree);
 extern tree build_constructor (tree, VEC(constructor_elt,gc) *);
 extern tree build_constructor_single (tree, tree, tree);
 extern tree build_constructor_from_list (tree, tree);
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 160943)
+++ gcc/tree.c	(working copy)
@@ -1312,6 +1312,25 @@ build_vector_from_ctor (tree type, VEC(c
   return build_vector (type, nreverse (list));
 }
 
+/* Build a vector of type VECTYPE where all the elements are SCs.  */
+tree
+build_vector_from_val (const tree sc, const tree vectype) 
+{
+  tree t = NULL_TREE;
+  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
+
+  if (sc == error_mark_node)
+    return sc;
+
+  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
+
+  for (i = 0; i < nunits; ++i)
+    t = tree_cons (NULL_TREE, sc, t);
+
+  return build_vector (vectype, t);
+}
+
+
 /* Return a new CONSTRUCTOR node whose type is TYPE and whose values
    are in the VEC pointed to by VALS.  */
 tree
Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 160943)
+++ gcc/doc/extend.texi	(working copy)
@@ -6119,7 +6119,7 @@ produce code that uses 4 @code{SIs}.
 
 The types defined in this manner can be used with a subset of normal C
 operations.  Currently, GCC will allow using the following operators
-on these types: @code{+, -, *, /, unary minus, ^, |, &, ~, %}@.
+on these types: @code{+, -, *, /, unary minus, ^, |, &, ~, %, <<, >>}@.
 
 The operations behave like C++ @code{valarrays}.  Addition is defined as
 the addition of the corresponding elements of the operands.  For
@@ -6135,6 +6135,22 @@ v4si a, b, c;
 c = a + b;
 @end smallexample
 
+Shifting operators @code{<<, >>} support integer vector operands doing
+element-wise shifting.  Additionally one of the operands can be a
+scalar integer in which case the scalar is converted to the type used
+by the vector operand and each element of this new vector is the
+scalar's value.  Consider the following code.
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a, b, c;
+int i = 1;
+
+b = a >> 1;     /* b = a >> {1,1,1,1}; */
+c = 1 << a;     /* c = {1,1,1,1} << a; */
+@end smallexample
+
 Subtraction, multiplication, division, and the logical operations
 operate in a similar manner.  Likewise, the result of using the unary
 minus or complement operators on a vector type is a vector whose

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

* Re: Vector shifting patch
  2010-06-21 11:08         ` Artem Shinkarov
@ 2010-10-25 17:04           ` Artem Shinkarov
  2010-10-25 18:36             ` Nathan Froyd
  0 siblings, 1 reply; 35+ messages in thread
From: Artem Shinkarov @ 2010-10-25 17:04 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Guenther, Joseph S. Myers

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

I'm continuing to submit my vector patches. Now it is vector shifting patch.

This patch allows integer-type vector shifts. The operation is defined
as following:
{a0, a1, ..., an} >> {b0, b1, ..., bn} == {a0 >> b0, a1 >> b1, ..., an >> bn}.
Operations "vec >> scal" and "scal >> vec" are supported as well, in
that case scalar is expanded to the vector of scalars according to the
type of the other operand.

ChangeLog:

2010-10-25  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
   Andrew Pinski <pinskia@gmail.com>

   gcc/
   * tree.h (build_vector_from_val): Declare.
   * tree.c (build_vector_from_val): New function.
   * c-typeck.c (build_binary_op): Handle vector shifting.

   gcc/testsuite/
   * gcc.c-torture/execute/vector-shift.c: Likewise.
   * gcc.c-torture/execute/vector-shift1.c: New testcase.
   * gcc.c-torture/execute/vector-shift2.c: New testcase.
   * gcc.dg/vector-shift.c: New testcase.
   * gcc.dg/vector-shift1.c: New testcase.
   * gcc.dg/vector-shift2.c: New testcase.
   * gcc.dg/vector-shift3.c: New testcase.
   * gcc.dg/vector-shift4.c: New testcase.

bootstrapped and tested on x86_64_unknown-linux

OK?

On Mon, Jun 21, 2010 at 10:55 AM, Artem Shinkarov
<artyom.shinkaroff@gmail.com> wrote:
> On Fri, Jun 18, 2010 at 7:26 PM, Andrew Pinski <pinskia@gmail.com> wrote:
>> On Fri, Jun 18, 2010 at 5:32 AM, Artem Shinkarov
>> <artyom.shinkaroff@gmail.com> wrote:
>>> Thank you everyone for comments. Here is a new version of the patch
>>> which considers all the comments.
>>
>> Hmm, Maybe I am missing something but I don't see a test that tests
>> what happens when one of the side of the shifters is an undefined
>> variable.  That test should be there as you changed
>> build_vector_from_val to fix that.
>>
>> Thanks,
>> Andrew Pinski
>>
>
> Yes, indeed, you are right. Sorry for that.
>
> 2010-06-18  Artem Shinkarov <artyom.shinakroff@gmail.com>
>    Andrew Pinski <pinskia@gmail.com>
>
>    * tree.h (build_vector_from_val): Declare.
>    * tree.c (build_vector_from_val): New function.
>    * c-typeck.c (build_binary_op): Handle vector shifting.
>
>    testsuite/
>    * gcc.c-torture/execute/vector-shift.c: Likewise.
>    * gcc.c-torture/execute/vector-shift1.c: New testcase.
>    * gcc.c-torture/execute/vector-shift2.c: New testcase.
>    * gcc.dg/vector-shift.c: New testcase.
>    * gcc.dg/vector-shift1.c: New testcase.
>    * gcc.dg/vector-shift2.c: New testcase.
>    * gcc.dg/vector-shift3.c: New testcase.
>    * gcc.dg/vector-shift4.c: New testcase.
>
>
> --
> Artem Shinkarov
>

[-- Attachment #2: vectorshift.c.v6.diff --]
[-- Type: text/x-diff, Size: 15858 bytes --]

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 165913)
+++ gcc/doc/extend.texi	(working copy)
@@ -6309,6 +6309,23 @@ v4si a, b, c;
 c = a + b;
 @end smallexample
 
+In C it is possible to use shifting operators @code{<<, >>} on integer-type
+vectors. The operation is defined as following: @code{@{a0, a1, ..., an@} >> @{b0, b1,
+..., bn@} == @{a0 >> b0, a1 >> b1, ..., an >> bn@}}@.  Additionally one of the
+operands can be a scalar integer in which case the scalar is converted to the
+type used by the vector operand and each element of this new vector is the
+scalar's value.  Consider the following code.
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a, b, c;
+int i = 1;
+
+b = a >> 1;     /* b = a >> @{1,1,1,1@}; */
+c = 1 << a;     /* c = @{1,1,1,1@} << a; */
+@end smallexample
+
 Subtraction, multiplication, division, and the logical operations
 operate in a similar manner.  Likewise, the result of using the unary
 minus or complement operators on a vector type is a vector whose
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 165913)
+++ gcc/tree.c	(working copy)
@@ -1366,6 +1366,27 @@ build_vector_from_ctor (tree type, VEC(c
   return build_vector (type, nreverse (list));
 }
 
+/* Build a vector of type VECTYPE where all the elements are SCs.  */
+tree
+build_vector_from_val (const tree sc, const tree vectype) 
+{
+  tree t = NULL_TREE;
+  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
+
+  if (sc == error_mark_node)
+    return sc;
+
+  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
+
+  for (i = 0; i < nunits; ++i)
+    t = tree_cons (NULL_TREE, sc, t);
+
+  if (CONSTANT_CLASS_P (sc))
+    return build_vector (vectype, t);
+  else 
+    return build_constructor_from_list (vectype, t);
+}
+
 /* Return a new CONSTRUCTOR node whose type is TYPE and whose values
    are in the VEC pointed to by VALS.  */
 tree
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 165913)
+++ gcc/tree.h	(working copy)
@@ -4034,6 +4034,7 @@ extern tree build_int_cst_type (tree, HO
 extern tree build_int_cst_wide (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
 extern tree build_vector (tree, tree);
 extern tree build_vector_from_ctor (tree, VEC(constructor_elt,gc) *);
+extern tree build_vector_from_val (const tree, const tree);
 extern tree build_constructor (tree, VEC(constructor_elt,gc) *);
 extern tree build_constructor_single (tree, tree, tree);
 extern tree build_constructor_from_list (tree, tree);
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
@@ -0,0 +1,60 @@
+/* dg-do run */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uint unsigned int
+
+int main (int argc, char *argv[]) {
+    vector(4, uint) vuint  = { 1,  2,  3,  4};
+    vector(4,  int) vint0  = { 1,  1,  1,  1};
+    vector(4,  int) vint1  = {-1, -1, -1, -1};
+
+    vector(4,  int) i1, i2, i3;
+    vector(4, uint) u1, u2, u3;
+
+    i1 = vint1<< vint0;
+    
+    if (vidx(int, i1, 0) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 1) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 2) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 3) != ((int)-1 << (int)1))
+        __builtin_abort ();
+
+    u1 = vuint << vint0;
+
+    if (vidx(int, u1, 0) != ((uint)1  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 1) != ((uint)2  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 2) != ((uint)3  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 3) != ((uint)4  << (int)1))
+        __builtin_abort ();
+
+    
+    i2 = vint1 >> vuint;
+
+    if (vidx(int, i2, 0) != ((int)-1  >> (uint)1))
+        __builtin_abort ();
+    if (vidx(int, i2, 1) != ((int)-1  >> (uint)2))
+        __builtin_abort ();
+    if (vidx(int, i2, 2) != ((int)-1  >> (uint)3))
+        __builtin_abort ();
+    if (vidx(int, i2, 3) != ((int)-1  >> (uint)4))
+        __builtin_abort ();
+
+
+    vint1 >>= vuint;
+    
+    vuint <<= vint0;
+    vuint <<= vint1;
+
+
+    return 0;
+}
+
+
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
@@ -0,0 +1,48 @@
+
+#define vector __attribute__((vector_size(sizeof(int)*4) ))
+
+static vector int allones = {1, 1, 1, 1};
+static vector int allzeros = {0, 0, 0, 0};
+static vector int numbers = {0, 1, 2, 3};
+static vector int numbersleftshiftallones = {0, 2, 4, 6};
+static vector int numbersrightshiftallones = {0, 0, 1, 1};
+
+
+static vector unsigned int uallones = {1, 1, 1, 1};
+static vector unsigned int uallzeros = {0, 0, 0, 0};
+static vector unsigned int unumbers = {0, 1, 2, 3};
+static vector unsigned int unumbersleftshiftallones = {0, 2, 4, 6};
+static vector unsigned int unumbersrightshiftallones = {0, 0, 1, 1};
+
+#define TEST(result, expected) \
+do { \
+  typeof(result) result1 = result; \
+  if(sizeof (result1) != sizeof (expected)) \
+    __builtin_abort (); \
+  if (__builtin_memcmp (&result1, &expected, sizeof(result1)) != 0) \
+    __builtin_abort (); \
+}while (0);
+
+int main(void)
+{
+  vector int result;
+  TEST ((numbers << allzeros), numbers);
+  TEST ((numbers >> allzeros), numbers);
+  TEST((numbers << allones), numbersleftshiftallones);
+  TEST((numbers >> allones), numbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((numbers << allones) >> allones, numbers);
+  
+  
+  
+  TEST ((unumbers << uallzeros), unumbers);
+  TEST ((unumbers >> uallzeros), unumbers);
+  TEST((unumbers << uallones), unumbersleftshiftallones);
+  TEST((unumbers >> uallones), unumbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((unumbers << uallones) >> uallones, unumbers);
+
+  return 0;  
+}
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
@@ -0,0 +1,17 @@
+#define vector __attribute__((vector_size(8*sizeof(short))))
+
+int main (int argc, char *argv[]) {
+  vector short v0 = {argc,2,3,4,5,6,7};
+  vector short v1 = {2,2,2,2,2,2,2};
+  vector short r1,r2,r3,r4;
+  int i = 8;
+
+  r1 = v0 << 1;
+  r2 = 1 << v0;
+
+  r3 = v0 << v1;
+  r4 = v0 >> v1;
+
+  return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift4.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift4.c	(revision 0)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+#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};
+    short sc;
+
+    v0 >>= scalar0; /* { dg-error ".*scalar0.*undeclared" } */
+    
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4,char) vchar = {1,2,3,4};
+    vector(4, int) vint  = {1,1,1,1};
+    
+    vint <<= vchar;  /* { dg-error "nvalid operands to binary <<" } */
+    vchar >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4, float) vfloat0 = {1., 2., 3., 4.};
+    vector(4, float) vfloat1 = {1., 2., 3., 4.};
+    
+    vector(4,   int) vint   = {1,  1,  1,  1 };
+    
+    vint <<= vfloat0;  /* { dg-error "nvalid operands to binary <<" } */
+    vfloat0 >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    vfloat0 <<= vfloat1;  /* { dg-error "nvalid operands to binary <<" } */
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+/* { dg-options "-fno-var-tracking-assignments" } */
+
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uchar unsigned char
+
+#define ch14 1,2,3,4
+#define ch1  1,1,1,1
+#define chm1 -1,-1,-1,-1
+
+int main (int argc, char *argv[]) {
+    vector(16, uchar) vuchar  = { ch14, ch14, ch14, ch14};
+    vector(16,  char) vchar0  = { ch1, ch1, ch1, ch1};
+    vector(16,  char) vchar1  = { chm1, chm1, chm1, chm1};
+
+    vector(16,  char) i1, i2, i3;
+    vector(16, uchar) u1, u2, u3;
+
+    i1 = vchar1<< vchar0;
+    
+    if (vidx(char, i1, 0) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 1) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 2) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 3) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    u1 = vuchar << vchar0;
+
+    if (vidx(char, u1, 0) != ((uchar)1  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 1) != ((uchar)2  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 2) != ((uchar)3  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 3) != ((uchar)4  << (char)1))
+        __builtin_abort ();
+
+    
+    i2 = vchar1 >> vuchar;
+
+    if (vidx(char, i2, 0) != ((char)-1  >> (uchar)1))
+        __builtin_abort ();
+    if (vidx(char, i2, 1) != ((char)-1  >> (uchar)2))
+        __builtin_abort ();
+    if (vidx(char, i2, 2) != ((char)-1  >> (uchar)3))
+        __builtin_abort ();
+    if (vidx(char, i2, 3) != ((char)-1  >> (uchar)4))
+        __builtin_abort ();
+    
+    vchar1 >>= vuchar;
+    vuchar <<= vchar0;
+    vuchar <<= vchar1;
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift3.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift3.c	(revision 0)
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+
+#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};
+    short sc;
+
+    
+    scalar1 <<= v0; /* { dg-error ".*scalar1.*undeclared" } */
+   
+    return 0;
+}
+
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 165913)
+++ gcc/c-typeck.c	(working copy)
@@ -9565,6 +9565,30 @@ build_binary_op (location_t location, en
 
   objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
 
+  /* For 'vector <shift> scalar' or 'scalar <shift> vector', we convert 
+     a scalar to a vector. Truncating the shift amount is ok.  */
+  if ((code0 == VECTOR_TYPE || code1 == VECTOR_TYPE)
+      && (code0 != code1))
+    {
+      switch (code)
+        {
+          case RSHIFT_EXPR:
+          case LSHIFT_EXPR:
+            if (code0 == INTEGER_TYPE)
+              {
+                tree sc = save_expr (op0);
+                sc = convert (TREE_TYPE (type1), sc);
+                op0 = build_vector_from_val (sc, type1);
+                orig_type0 = type0 = TREE_TYPE (op0);
+                code0 = TREE_CODE (type0);
+              }
+            break;
+
+          default:
+            break;
+        }
+    }
+
   switch (code)
     {
     case PLUS_EXPR:
@@ -9727,7 +9751,21 @@ build_binary_op (location_t location, en
 	 Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9754,9 +9792,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
@@ -9764,7 +9803,21 @@ build_binary_op (location_t location, en
       break;
 
     case LSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9786,9 +9839,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;

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

* Re: Vector shifting patch
  2010-10-25 17:04           ` Artem Shinkarov
@ 2010-10-25 18:36             ` Nathan Froyd
  2010-10-25 19:16               ` Artem Shinkarov
  0 siblings, 1 reply; 35+ messages in thread
From: Nathan Froyd @ 2010-10-25 18:36 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: gcc-patches, Richard Guenther, Joseph S. Myers

On Mon, Oct 25, 2010 at 03:42:47PM +0100, Artem Shinkarov wrote:
> I'm continuing to submit my vector patches. Now it is vector shifting
> patch.
>
> Index: gcc/tree.c
> ===================================================================
> --- gcc/tree.c	(revision 165913)
> +++ gcc/tree.c	(working copy)
> @@ -1366,6 +1366,27 @@ build_vector_from_ctor (tree type, VEC(c
>    return build_vector (type, nreverse (list));
>  }
>  
> +/* Build a vector of type VECTYPE where all the elements are SCs.  */
> +tree
> +build_vector_from_val (const tree sc, const tree vectype) 
> +{
> +  tree t = NULL_TREE;
> +  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
> +
> +  if (sc == error_mark_node)
> +    return sc;
> +
> +  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
> +
> +  for (i = 0; i < nunits; ++i)
> +    t = tree_cons (NULL_TREE, sc, t);
> +
> +  if (CONSTANT_CLASS_P (sc))
> +    return build_vector (vectype, t);
> +  else 
> +    return build_constructor_from_list (vectype, t);
> +}
> +

Would you mind rewriting this to use build_vector_from_ctor/build_constructor?
build_constructor_from_list is nearly eradicated from the tree and it'd
be nice to keep it that way.

-Nathan

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

* Re: Vector shifting patch
  2010-10-25 18:36             ` Nathan Froyd
@ 2010-10-25 19:16               ` Artem Shinkarov
  2010-10-25 19:41                 ` Artem Shinkarov
  2010-10-25 21:13                 ` Nathan Froyd
  0 siblings, 2 replies; 35+ messages in thread
From: Artem Shinkarov @ 2010-10-25 19:16 UTC (permalink / raw)
  To: Nathan Froyd; +Cc: gcc-patches, Richard Guenther, Joseph S. Myers

Ok, I can do that.

On Mon, Oct 25, 2010 at 3:47 PM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> On Mon, Oct 25, 2010 at 03:42:47PM +0100, Artem Shinkarov wrote:
>> I'm continuing to submit my vector patches. Now it is vector shifting
>> patch.
>>
>> Index: gcc/tree.c
>> ===================================================================
>> --- gcc/tree.c        (revision 165913)
>> +++ gcc/tree.c        (working copy)
>> @@ -1366,6 +1366,27 @@ build_vector_from_ctor (tree type, VEC(c
>>    return build_vector (type, nreverse (list));
>>  }
>>
>> +/* Build a vector of type VECTYPE where all the elements are SCs.  */
>> +tree
>> +build_vector_from_val (const tree sc, const tree vectype)
>> +{
>> +  tree t = NULL_TREE;
>> +  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
>> +
>> +  if (sc == error_mark_node)
>> +    return sc;
>> +
>> +  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
>> +
>> +  for (i = 0; i < nunits; ++i)
>> +    t = tree_cons (NULL_TREE, sc, t);
>> +
>> +  if (CONSTANT_CLASS_P (sc))
>> +    return build_vector (vectype, t);
>> +  else
>> +    return build_constructor_from_list (vectype, t);
>> +}
>> +
>
> Would you mind rewriting this to use build_vector_from_ctor/build_constructor?
> build_constructor_from_list is nearly eradicated from the tree and it'd
> be nice to keep it that way.
>
> -Nathan
>

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

* Re: Vector shifting patch
  2010-10-25 19:16               ` Artem Shinkarov
@ 2010-10-25 19:41                 ` Artem Shinkarov
  2010-10-25 21:13                 ` Nathan Froyd
  1 sibling, 0 replies; 35+ messages in thread
From: Artem Shinkarov @ 2010-10-25 19:41 UTC (permalink / raw)
  To: Nathan Froyd; +Cc: gcc-patches, Richard Guenther, Joseph S. Myers

Ok, I can do that.

On Mon, Oct 25, 2010 at 3:47 PM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> On Mon, Oct 25, 2010 at 03:42:47PM +0100, Artem Shinkarov wrote:
>> I'm continuing to submit my vector patches. Now it is vector shifting
>> patch.
>>
>> Index: gcc/tree.c
>> ===================================================================
>> --- gcc/tree.c        (revision 165913)
>> +++ gcc/tree.c        (working copy)
>> @@ -1366,6 +1366,27 @@ build_vector_from_ctor (tree type, VEC(c
>>    return build_vector (type, nreverse (list));
>>  }
>>
>> +/* Build a vector of type VECTYPE where all the elements are SCs.  */
>> +tree
>> +build_vector_from_val (const tree sc, const tree vectype)
>> +{
>> +  tree t = NULL_TREE;
>> +  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
>> +
>> +  if (sc == error_mark_node)
>> +    return sc;
>> +
>> +  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
>> +
>> +  for (i = 0; i < nunits; ++i)
>> +    t = tree_cons (NULL_TREE, sc, t);
>> +
>> +  if (CONSTANT_CLASS_P (sc))
>> +    return build_vector (vectype, t);
>> +  else
>> +    return build_constructor_from_list (vectype, t);
>> +}
>> +
>
> Would you mind rewriting this to use build_vector_from_ctor/build_constructor?
> build_constructor_from_list is nearly eradicated from the tree and it'd
> be nice to keep it that way.
>
> -Nathan
>

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

* Re: Vector shifting patch
  2010-10-25 21:13                 ` Nathan Froyd
@ 2010-10-25 20:16                   ` Artem Shinkarov
  2010-10-25 20:33                     ` Nathan Froyd
  0 siblings, 1 reply; 35+ messages in thread
From: Artem Shinkarov @ 2010-10-25 20:16 UTC (permalink / raw)
  To: Nathan Froyd; +Cc: gcc-patches, Richard Guenther, Joseph S. Myers

Does it look better now:

tree
build_vector_from_val (const tree sc, const tree vectype)
{
  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
  VEC(constructor_elt, gc) *v;

  if (sc == error_mark_node)
    return sc;

  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));

  v = VEC_alloc (constructor_elt, gc, nunits);
  for (i = 0; i < nunits; ++i)
    CONSTRUCTOR_APPEND_ELT (v, size_int (i), sc);

  if (CONSTANT_CLASS_P (sc))
    return build_vector_from_ctor (vectype, v);
  else
    return build_constructor (vectype, v);
}

(I'm bootstrapping the compiler now but it seems to work).


On Mon, Oct 25, 2010 at 4:07 PM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> On Mon, Oct 25, 2010 at 03:54:36PM +0100, Artem Shinkarov wrote:
>> On Mon, Oct 25, 2010 at 3:47 PM, Nathan Froyd <froydnj@codesourcery.com> wrote:
>> > Would you mind rewriting this to use build_vector_from_ctor/build_constructor?
>> > build_constructor_from_list is nearly eradicated from the tree and it'd
>> > be nice to keep it that way.
>>
>> Ok, I can do that.
>
> Thanks!  On the plus side, your new build_vector_from_val can be used in
> several places, providing a nice cleanup.  (To be clear: I'm not asking
> you to do that cleanup.)

I'm happy to make it better, just give me a hint. :)

>
> -Nathan
>

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

* Re: Vector shifting patch
  2010-10-25 20:16                   ` Artem Shinkarov
@ 2010-10-25 20:33                     ` Nathan Froyd
  2010-10-26 10:45                       ` Artem Shinkarov
  0 siblings, 1 reply; 35+ messages in thread
From: Nathan Froyd @ 2010-10-25 20:33 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: gcc-patches, Richard Guenther, Joseph S. Myers

On Mon, Oct 25, 2010 at 04:21:47PM +0100, Artem Shinkarov wrote:
> Does it look better now:
> 
> tree
> build_vector_from_val (const tree sc, const tree vectype)
> {
>   int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
>   VEC(constructor_elt, gc) *v;
> 
>   if (sc == error_mark_node)
>     return sc;
> 
>   gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
> 
>   v = VEC_alloc (constructor_elt, gc, nunits);
>   for (i = 0; i < nunits; ++i)
>     CONSTRUCTOR_APPEND_ELT (v, size_int (i), sc);
                                 ^^^^^^^^^^^^

You can just pass NULL_TREE here and the Right Thing will happen.

I think the logic looks fine.  For consistency's sake, it would probably
be good to have the argument order reversed, i.e.:

tree
build_vector_from_val (const_tree vectype, const_tree sc)

as that would more closely match the existing build_vector* functions.

Please also note that you want const_tree instead of 'const tree' (note
underscore).  If there are other instances of that in your patch, you'll
want to fix those too.

-Nathan

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

* Re: Vector shifting patch
  2010-10-25 19:16               ` Artem Shinkarov
  2010-10-25 19:41                 ` Artem Shinkarov
@ 2010-10-25 21:13                 ` Nathan Froyd
  2010-10-25 20:16                   ` Artem Shinkarov
  1 sibling, 1 reply; 35+ messages in thread
From: Nathan Froyd @ 2010-10-25 21:13 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: gcc-patches, Richard Guenther, Joseph S. Myers

On Mon, Oct 25, 2010 at 03:54:36PM +0100, Artem Shinkarov wrote:
> On Mon, Oct 25, 2010 at 3:47 PM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> > Would you mind rewriting this to use build_vector_from_ctor/build_constructor?
> > build_constructor_from_list is nearly eradicated from the tree and it'd
> > be nice to keep it that way.
>
> Ok, I can do that.

Thanks!  On the plus side, your new build_vector_from_val can be used in
several places, providing a nice cleanup.  (To be clear: I'm not asking
you to do that cleanup.)

-Nathan

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

* Re: Vector shifting patch
  2010-10-26 10:45                       ` Artem Shinkarov
@ 2010-10-26  1:16                         ` Joseph S. Myers
  2010-10-26 13:11                           ` Artem Shinkarov
  2010-10-26 17:45                         ` Joseph S. Myers
  2010-10-27 14:16                         ` Nathan Froyd
  2 siblings, 1 reply; 35+ messages in thread
From: Joseph S. Myers @ 2010-10-26  1:16 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: Nathan Froyd, gcc-patches, Richard Guenther

On Mon, 25 Oct 2010, Artem Shinkarov wrote:

> Here is a version with improved build_vector_from val.

I notice this message (Date: Mon, 25 Oct 2010 18:15:40 +0100) hasn't 
appeared on gcc-patches yet although I received a personal copy.  I don't 
know whether this is a problem with your mail system or gcc.gnu.org, but 
could you make sure it reaches the list?

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: Vector shifting patch
  2010-10-25 20:33                     ` Nathan Froyd
@ 2010-10-26 10:45                       ` Artem Shinkarov
  2010-10-26  1:16                         ` Joseph S. Myers
                                           ` (2 more replies)
  0 siblings, 3 replies; 35+ messages in thread
From: Artem Shinkarov @ 2010-10-26 10:45 UTC (permalink / raw)
  To: Nathan Froyd; +Cc: gcc-patches, Richard Guenther, Joseph S. Myers

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

Here is a version with improved build_vector_from val.

ChangeLog:

2010-10-25  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
  Andrew Pinski <pinskia@gmail.com>

  gcc/
  * tree.h (build_vector_from_val): Declare.
  * tree.c (build_vector_from_val): New function.
  * c-typeck.c (build_binary_op): Handle vector shifting.

  gcc/testsuite/
  * gcc.c-torture/execute/vector-shift.c: Likewise.
  * gcc.c-torture/execute/vector-shift1.c: New testcase.
  * gcc.c-torture/execute/vector-shift2.c: New testcase.
  * gcc.dg/vector-shift.c: New testcase.
  * gcc.dg/vector-shift1.c: New testcase.
  * gcc.dg/vector-shift2.c: New testcase.
  * gcc.dg/vector-shift3.c: New testcase.
  * gcc.dg/vector-shift4.c: New testcase.

bootstrapped and tested on x86_64_unknown-linux

OK?


On Mon, Oct 25, 2010 at 4:27 PM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> On Mon, Oct 25, 2010 at 04:21:47PM +0100, Artem Shinkarov wrote:
>> Does it look better now:
>>
>> tree
>> build_vector_from_val (const tree sc, const tree vectype)
>> {
>>   int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
>>   VEC(constructor_elt, gc) *v;
>>
>>   if (sc == error_mark_node)
>>     return sc;
>>
>>   gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
>>
>>   v = VEC_alloc (constructor_elt, gc, nunits);
>>   for (i = 0; i < nunits; ++i)
>>     CONSTRUCTOR_APPEND_ELT (v, size_int (i), sc);
>                                 ^^^^^^^^^^^^
>
> You can just pass NULL_TREE here and the Right Thing will happen.
>
> I think the logic looks fine.  For consistency's sake, it would probably
> be good to have the argument order reversed, i.e.:
>
> tree
> build_vector_from_val (const_tree vectype, const_tree sc)
>
> as that would more closely match the existing build_vector* functions.
>
> Please also note that you want const_tree instead of 'const tree' (note
> underscore).  If there are other instances of that in your patch, you'll
> want to fix those too.
>
> -Nathan
>

[-- Attachment #2: vectorshift.c.v7.diff --]
[-- Type: text/x-diff, Size: 15910 bytes --]

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 165913)
+++ gcc/doc/extend.texi	(working copy)
@@ -6309,6 +6309,23 @@ v4si a, b, c;
 c = a + b;
 @end smallexample
 
+In C it is possible to use shifting operators @code{<<, >>} on integer-type
+vectors. The operation is defined as following: @code{@{a0, a1, ..., an@} >> @{b0, b1,
+..., bn@} == @{a0 >> b0, a1 >> b1, ..., an >> bn@}}@.  Additionally one of the
+operands can be a scalar integer in which case the scalar is converted to the
+type used by the vector operand and each element of this new vector is the
+scalar's value.  Consider the following code.
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a, b, c;
+int i = 1;
+
+b = a >> 1;     /* b = a >> @{1,1,1,1@}; */
+c = 1 << a;     /* c = @{1,1,1,1@} << a; */
+@end smallexample
+
 Subtraction, multiplication, division, and the logical operations
 operate in a similar manner.  Likewise, the result of using the unary
 minus or complement operators on a vector type is a vector whose
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 165913)
+++ gcc/tree.c	(working copy)
@@ -1366,6 +1366,28 @@ build_vector_from_ctor (tree type, VEC(c
   return build_vector (type, nreverse (list));
 }
 
+/* Build a vector of type VECTYPE where all the elements are SCs.  */
+tree
+build_vector_from_val (tree vectype, tree sc) 
+{
+  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
+  VEC(constructor_elt, gc) *v = NULL;
+
+  if (sc == error_mark_node)
+    return sc;
+
+  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
+
+  v = VEC_alloc (constructor_elt, gc, nunits);
+  for (i = 0; i < nunits; ++i)
+    CONSTRUCTOR_APPEND_ELT (v, size_int (i), sc);
+
+  if (CONSTANT_CLASS_P (sc))
+    return build_vector_from_ctor (vectype, v);
+  else 
+    return build_constructor (vectype, v);
+}
+
 /* Return a new CONSTRUCTOR node whose type is TYPE and whose values
    are in the VEC pointed to by VALS.  */
 tree
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 165913)
+++ gcc/tree.h	(working copy)
@@ -4034,6 +4034,7 @@ extern tree build_int_cst_type (tree, HO
 extern tree build_int_cst_wide (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
 extern tree build_vector (tree, tree);
 extern tree build_vector_from_ctor (tree, VEC(constructor_elt,gc) *);
+extern tree build_vector_from_val (tree, tree);
 extern tree build_constructor (tree, VEC(constructor_elt,gc) *);
 extern tree build_constructor_single (tree, tree, tree);
 extern tree build_constructor_from_list (tree, tree);
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
@@ -0,0 +1,60 @@
+/* dg-do run */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uint unsigned int
+
+int main (int argc, char *argv[]) {
+    vector(4, uint) vuint  = { 1,  2,  3,  4};
+    vector(4,  int) vint0  = { 1,  1,  1,  1};
+    vector(4,  int) vint1  = {-1, -1, -1, -1};
+
+    vector(4,  int) i1, i2, i3;
+    vector(4, uint) u1, u2, u3;
+
+    i1 = vint1<< vint0;
+    
+    if (vidx(int, i1, 0) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 1) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 2) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 3) != ((int)-1 << (int)1))
+        __builtin_abort ();
+
+    u1 = vuint << vint0;
+
+    if (vidx(int, u1, 0) != ((uint)1  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 1) != ((uint)2  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 2) != ((uint)3  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 3) != ((uint)4  << (int)1))
+        __builtin_abort ();
+
+    
+    i2 = vint1 >> vuint;
+
+    if (vidx(int, i2, 0) != ((int)-1  >> (uint)1))
+        __builtin_abort ();
+    if (vidx(int, i2, 1) != ((int)-1  >> (uint)2))
+        __builtin_abort ();
+    if (vidx(int, i2, 2) != ((int)-1  >> (uint)3))
+        __builtin_abort ();
+    if (vidx(int, i2, 3) != ((int)-1  >> (uint)4))
+        __builtin_abort ();
+
+
+    vint1 >>= vuint;
+    
+    vuint <<= vint0;
+    vuint <<= vint1;
+
+
+    return 0;
+}
+
+
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
@@ -0,0 +1,48 @@
+
+#define vector __attribute__((vector_size(sizeof(int)*4) ))
+
+static vector int allones = {1, 1, 1, 1};
+static vector int allzeros = {0, 0, 0, 0};
+static vector int numbers = {0, 1, 2, 3};
+static vector int numbersleftshiftallones = {0, 2, 4, 6};
+static vector int numbersrightshiftallones = {0, 0, 1, 1};
+
+
+static vector unsigned int uallones = {1, 1, 1, 1};
+static vector unsigned int uallzeros = {0, 0, 0, 0};
+static vector unsigned int unumbers = {0, 1, 2, 3};
+static vector unsigned int unumbersleftshiftallones = {0, 2, 4, 6};
+static vector unsigned int unumbersrightshiftallones = {0, 0, 1, 1};
+
+#define TEST(result, expected) \
+do { \
+  typeof(result) result1 = result; \
+  if(sizeof (result1) != sizeof (expected)) \
+    __builtin_abort (); \
+  if (__builtin_memcmp (&result1, &expected, sizeof(result1)) != 0) \
+    __builtin_abort (); \
+}while (0);
+
+int main(void)
+{
+  vector int result;
+  TEST ((numbers << allzeros), numbers);
+  TEST ((numbers >> allzeros), numbers);
+  TEST((numbers << allones), numbersleftshiftallones);
+  TEST((numbers >> allones), numbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((numbers << allones) >> allones, numbers);
+  
+  
+  
+  TEST ((unumbers << uallzeros), unumbers);
+  TEST ((unumbers >> uallzeros), unumbers);
+  TEST((unumbers << uallones), unumbersleftshiftallones);
+  TEST((unumbers >> uallones), unumbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((unumbers << uallones) >> uallones, unumbers);
+
+  return 0;  
+}
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
@@ -0,0 +1,17 @@
+#define vector __attribute__((vector_size(8*sizeof(short))))
+
+int main (int argc, char *argv[]) {
+  vector short v0 = {argc,2,3,4,5,6,7};
+  vector short v1 = {2,2,2,2,2,2,2};
+  vector short r1,r2,r3,r4;
+  int i = 8;
+
+  r1 = v0 << 1;
+  r2 = 1 << v0;
+
+  r3 = v0 << v1;
+  r4 = v0 >> v1;
+
+  return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift4.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift4.c	(revision 0)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+#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};
+    short sc;
+
+    v0 >>= scalar0; /* { dg-error ".*scalar0.*undeclared" } */
+    
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4,char) vchar = {1,2,3,4};
+    vector(4, int) vint  = {1,1,1,1};
+    
+    vint <<= vchar;  /* { dg-error "nvalid operands to binary <<" } */
+    vchar >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4, float) vfloat0 = {1., 2., 3., 4.};
+    vector(4, float) vfloat1 = {1., 2., 3., 4.};
+    
+    vector(4,   int) vint   = {1,  1,  1,  1 };
+    
+    vint <<= vfloat0;  /* { dg-error "nvalid operands to binary <<" } */
+    vfloat0 >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    vfloat0 <<= vfloat1;  /* { dg-error "nvalid operands to binary <<" } */
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+/* { dg-options "-fno-var-tracking-assignments" } */
+
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uchar unsigned char
+
+#define ch14 1,2,3,4
+#define ch1  1,1,1,1
+#define chm1 -1,-1,-1,-1
+
+int main (int argc, char *argv[]) {
+    vector(16, uchar) vuchar  = { ch14, ch14, ch14, ch14};
+    vector(16,  char) vchar0  = { ch1, ch1, ch1, ch1};
+    vector(16,  char) vchar1  = { chm1, chm1, chm1, chm1};
+
+    vector(16,  char) i1, i2, i3;
+    vector(16, uchar) u1, u2, u3;
+
+    i1 = vchar1<< vchar0;
+    
+    if (vidx(char, i1, 0) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 1) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 2) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 3) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    u1 = vuchar << vchar0;
+
+    if (vidx(char, u1, 0) != ((uchar)1  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 1) != ((uchar)2  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 2) != ((uchar)3  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 3) != ((uchar)4  << (char)1))
+        __builtin_abort ();
+
+    
+    i2 = vchar1 >> vuchar;
+
+    if (vidx(char, i2, 0) != ((char)-1  >> (uchar)1))
+        __builtin_abort ();
+    if (vidx(char, i2, 1) != ((char)-1  >> (uchar)2))
+        __builtin_abort ();
+    if (vidx(char, i2, 2) != ((char)-1  >> (uchar)3))
+        __builtin_abort ();
+    if (vidx(char, i2, 3) != ((char)-1  >> (uchar)4))
+        __builtin_abort ();
+    
+    vchar1 >>= vuchar;
+    vuchar <<= vchar0;
+    vuchar <<= vchar1;
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift3.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift3.c	(revision 0)
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+
+#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};
+    short sc;
+
+    
+    scalar1 <<= v0; /* { dg-error ".*scalar1.*undeclared" } */
+   
+    return 0;
+}
+
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 165913)
+++ gcc/c-typeck.c	(working copy)
@@ -9565,6 +9565,30 @@ build_binary_op (location_t location, en
 
   objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
 
+  /* For 'vector <shift> scalar' or 'scalar <shift> vector', we convert 
+     a scalar to a vector. Truncating the shift amount is ok.  */
+  if ((code0 == VECTOR_TYPE || code1 == VECTOR_TYPE)
+      && (code0 != code1))
+    {
+      switch (code)
+        {
+          case RSHIFT_EXPR:
+          case LSHIFT_EXPR:
+            if (code0 == INTEGER_TYPE)
+              {
+                tree sc = save_expr (op0);
+                sc = convert (TREE_TYPE (type1), sc);
+                op0 = build_vector_from_val (type1, sc);
+                orig_type0 = type0 = TREE_TYPE (op0);
+                code0 = TREE_CODE (type0);
+              }
+            break;
+
+          default:
+            break;
+        }
+    }
+
   switch (code)
     {
     case PLUS_EXPR:
@@ -9727,7 +9751,21 @@ build_binary_op (location_t location, en
 	 Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9754,9 +9792,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
@@ -9764,7 +9803,21 @@ build_binary_op (location_t location, en
       break;
 
     case LSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9786,9 +9839,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;

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

* Re: Vector shifting patch
  2010-10-26  1:16                         ` Joseph S. Myers
@ 2010-10-26 13:11                           ` Artem Shinkarov
  0 siblings, 0 replies; 35+ messages in thread
From: Artem Shinkarov @ 2010-10-26 13:11 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: Nathan Froyd, gcc-patches, Richard Guenther

Yes, you are right. Seems really strange to me.

gcc-patches@gcc.gnu.org was always in the CC.

And how Nathan then answered on my mail about build_vector_from_val
yesterday....

But I'll start a new thread on the patch mailinglist.



Artem.

On Mon, Oct 25, 2010 at 10:51 PM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> On Mon, 25 Oct 2010, Artem Shinkarov wrote:
>
>> Here is a version with improved build_vector_from val.
>
> I notice this message (Date: Mon, 25 Oct 2010 18:15:40 +0100) hasn't
> appeared on gcc-patches yet although I received a personal copy.  I don't
> know whether this is a problem with your mail system or gcc.gnu.org, but
> could you make sure it reaches the list?
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>

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

* Re: Vector shifting patch
  2010-10-26 10:45                       ` Artem Shinkarov
  2010-10-26  1:16                         ` Joseph S. Myers
@ 2010-10-26 17:45                         ` Joseph S. Myers
  2010-10-27 13:50                           ` Artem Shinkarov
  2010-10-27 14:16                         ` Nathan Froyd
  2 siblings, 1 reply; 35+ messages in thread
From: Joseph S. Myers @ 2010-10-26 17:45 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: Nathan Froyd, gcc-patches, Richard Guenther

On Mon, 25 Oct 2010, Artem Shinkarov wrote:

> Index: gcc/doc/extend.texi
> ===================================================================
> --- gcc/doc/extend.texi	(revision 165913)
> +++ gcc/doc/extend.texi	(working copy)
> @@ -6309,6 +6309,23 @@ v4si a, b, c;
>  c = a + b;
>  @end smallexample
>  
> +In C it is possible to use shifting operators @code{<<, >>} on integer-type
> +vectors. The operation is defined as following: @code{@{a0, a1, ..., an@} >> @{b0, b1,
> +..., bn@} == @{a0 >> b0, a1 >> b1, ..., an >> bn@}}@.  Additionally one of the

The "..." here should be @dots{} since it is not the literal C token 
"...".

> +operands can be a scalar integer in which case the scalar is converted to the
> +type used by the vector operand and each element of this new vector is the
> +scalar's value.  Consider the following code.

Most of my comments relate to the scalar case which seems more potentially 
problematic than the case where both operands are vectors.  But in the 
case where both operands are vectors I note you say nothing about 
permitted types of the two operands.  Are they required to be exactly the 
same?  Or can they differ in signedness?  In the width of elements of the 
vector?

In normal C without vectors, the types of the two operands of a shift are 
independent.  This would tend to suggest that this should be the case for 
vectors - they must have the same number of elements, but why constrain 
things further?  I didn't see any such constraint in the OpenCL 
specification, although I note that OpenCL doesn't permit scalar << vector 
or scalar >> vector.

Say one operand is a scalar.  There doesn't appear to be much coverage of 
this case in the testcases added.  If there is a scalar shift amount, 
where you say:

> +  /* For 'vector <shift> scalar' or 'scalar <shift> vector', we convert 
> +     a scalar to a vector. Truncating the shift amount is ok.  */

then indeed this truncation is OK, because the only times the value will 
be affected are cases where the shift amount would be out of range and 
there would be undefined behavior (in C).  But if you are shifting a 
scalar by a vector, say 0x12345678 << (vector unsigned char){1,1,1,1}, 
then converting the scalar to the type of the vector elements seems 
inappropriate and risky.  It would at least require the use of 
convert_and_check so appropriate warnings can be given, but it would seem 
better to disallow this case, as in OpenCL.  If allowed then you'd want 
the result to be a vector whose element type is the type of the LHS of the 
shift - but C promotions would prevent the LHS from having types such as 
char and short.

> +  if ((code0 == VECTOR_TYPE || code1 == VECTOR_TYPE)
> +      && (code0 != code1))
> +    {
> +      switch (code)
> +        {
> +          case RSHIFT_EXPR:
> +          case LSHIFT_EXPR:
> +            if (code0 == INTEGER_TYPE)
> +              {
> +                tree sc = save_expr (op0);
> +                sc = convert (TREE_TYPE (type1), sc);
> +                op0 = build_vector_from_val (type1, sc);
> +                orig_type0 = type0 = TREE_TYPE (op0);
> +                code0 = TREE_CODE (type0);
> +              }
> +            break;

If you do disallow such shifts this code could go away - but why are you 
allowing in this particular place only for scalars shifted by a vector 
amount and not for vectors shifted by a scalar amount?  Where is the code 
handling vectors shifted by scalars?

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: Vector shifting patch
  2010-10-26 17:45                         ` Joseph S. Myers
@ 2010-10-27 13:50                           ` Artem Shinkarov
  2010-10-27 14:17                             ` Joseph S. Myers
  0 siblings, 1 reply; 35+ messages in thread
From: Artem Shinkarov @ 2010-10-27 13:50 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: Nathan Froyd, gcc-patches, Richard Guenther

On Tue, Oct 26, 2010 at 4:15 PM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> On Mon, 25 Oct 2010, Artem Shinkarov wrote:
>
>> Index: gcc/doc/extend.texi
>> ===================================================================
>> --- gcc/doc/extend.texi       (revision 165913)
>> +++ gcc/doc/extend.texi       (working copy)
>> @@ -6309,6 +6309,23 @@ v4si a, b, c;
>>  c = a + b;
>>  @end smallexample
>>
>> +In C it is possible to use shifting operators @code{<<, >>} on integer-type
>> +vectors. The operation is defined as following: @code{@{a0, a1, ..., an@} >> @{b0, b1,
>> +..., bn@} == @{a0 >> b0, a1 >> b1, ..., an >> bn@}}@.  Additionally one of the
>
> The "..." here should be @dots{} since it is not the literal C token
> "...".

Thanks, fixed.

>
>> +operands can be a scalar integer in which case the scalar is converted to the
>> +type used by the vector operand and each element of this new vector is the
>> +scalar's value.  Consider the following code.
>
> Most of my comments relate to the scalar case which seems more potentially
> problematic than the case where both operands are vectors.  But in the
> case where both operands are vectors I note you say nothing about
> permitted types of the two operands.  Are they required to be exactly the
> same?  Or can they differ in signedness?  In the width of elements of the
> vector?

In case when both operands are vectors my patch requires that they are
both integer-typed and that the number of elements is the same. On the
other hand, the existing code c-typeck.c:(build_binary_op):10048

  if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
      && (!tree_int_cst_equal (TYPE_SIZE (type0), TYPE_SIZE (type1))
	  || !same_scalar_type_ignoring_signedness (TREE_TYPE (type0),
						    TREE_TYPE (type1))))
    {
      binary_op_error (location, code, type0, type1);
      return error_mark_node;
    }

requires that the base type of the vector has the same width.

>
> In normal C without vectors, the types of the two operands of a shift are
> independent.  This would tend to suggest that this should be the case for
> vectors - they must have the same number of elements, but why constrain
> things further?  I didn't see any such constraint in the OpenCL
> specification, although I note that OpenCL doesn't permit scalar << vector
> or scalar >> vector.

Again, I agree, but then we should do the same stuff for operations +,
-, *, /, ...
because we can have an expression in C like: <int> + <char> * <short>
and the type inference would do the job.
On the other hand if we allow that, then most likely most of our
vector operations will be expanded and would not reach the hardware.
And I think that one of the purpose of these vector extensions is to
build an interface for CPU SIMD instructions. So this is a sort of
political decision we want to make.

My thinking here was that we leave the patch as is, and if later we
will decide that we want to support vector(8) char <op> vector(8)
short, we would just remove the constraint and my patch would still
work.

>
> Say one operand is a scalar.  There doesn't appear to be much coverage of
> this case in the testcases added.  If there is a scalar shift amount,
> where you say:
>
>> +  /* For 'vector <shift> scalar' or 'scalar <shift> vector', we convert
>> +     a scalar to a vector. Truncating the shift amount is ok.  */
>
> then indeed this truncation is OK, because the only times the value will
> be affected are cases where the shift amount would be out of range and
> there would be undefined behavior (in C).  But if you are shifting a
> scalar by a vector, say 0x12345678 << (vector unsigned char){1,1,1,1},
> then converting the scalar to the type of the vector elements seems
> inappropriate and risky.  It would at least require the use of
> convert_and_check so appropriate warnings can be given, but it would seem
> better to disallow this case, as in OpenCL.  If allowed then you'd want
> the result to be a vector whose element type is the type of the LHS of the
> shift - but C promotions would prevent the LHS from having types such as
> char and short.

OpenCL allows scalar <op> vector for most of the arithmetic
operations, so I thought that it would be nice to have this for shifts
as well, considering the fact that vector shift where the second
operator is a scalar is ok.

I don't see how the conversion of the expression 0x12345678 <<
{1,1,1,1} in compile time is different from the conversion of the
expression:
vector int x = (vector int){0x12345678, 0x123456778, ...} << {1,1,1,1}
which is allowed. Ok, in that case we will get warnings if -Woferflow
is on.

But in the case:
long long x;
vecor(8) short v0 = {...};
v0 = (vector(8) short){x,x,...} << v0;
we would not get any warnings and we will have the same behaviour as in my case.
And of course I can use convert_and_check instead of just convert.

>
>> +  if ((code0 == VECTOR_TYPE || code1 == VECTOR_TYPE)
>> +      && (code0 != code1))
>> +    {
>> +      switch (code)
>> +        {
>> +          case RSHIFT_EXPR:
>> +          case LSHIFT_EXPR:
>> +            if (code0 == INTEGER_TYPE)
>> +              {
>> +                tree sc = save_expr (op0);
>> +                sc = convert (TREE_TYPE (type1), sc);
>> +                op0 = build_vector_from_val (type1, sc);
>> +                orig_type0 = type0 = TREE_TYPE (op0);
>> +                code0 = TREE_CODE (type0);
>> +              }
>> +            break;
>
> If you do disallow such shifts this code could go away - but why are you
> allowing in this particular place only for scalars shifted by a vector
> amount and not for vectors shifted by a scalar amount?  Where is the code
> handling vectors shifted by scalars?

The code is in the case  {RL}SHIFT_EXPR: branches. The thing is that
middleend happily accepts the expression vector >> scalar and vector
<< scalar. That is why I don't have to do anything there, just to
build that expression.

>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>

So who is taking the political decision about the binary operation on
vectors of different width?



-- 
Artem

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

* Re: Vector shifting patch
  2010-10-26 10:45                       ` Artem Shinkarov
  2010-10-26  1:16                         ` Joseph S. Myers
  2010-10-26 17:45                         ` Joseph S. Myers
@ 2010-10-27 14:16                         ` Nathan Froyd
  2 siblings, 0 replies; 35+ messages in thread
From: Nathan Froyd @ 2010-10-27 14:16 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: gcc-patches, Richard Guenther, Joseph S. Myers

On Mon, Oct 25, 2010 at 06:15:40PM +0100, Artem Shinkarov wrote:
> Index: gcc/tree.c
> ===================================================================
> --- gcc/tree.c	(revision 165913)
> +++ gcc/tree.c	(working copy)
> @@ -1366,6 +1366,28 @@ build_vector_from_ctor (tree type, VEC(c
>    return build_vector (type, nreverse (list));
>  }
>  
> +/* Build a vector of type VECTYPE where all the elements are SCs.  */
> +tree
> +build_vector_from_val (tree vectype, tree sc) 
> +{
> +  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
> +  VEC(constructor_elt, gc) *v = NULL;
> +
> +  if (sc == error_mark_node)
> +    return sc;
> +
> +  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
> +
> +  v = VEC_alloc (constructor_elt, gc, nunits);
> +  for (i = 0; i < nunits; ++i)
> +    CONSTRUCTOR_APPEND_ELT (v, size_int (i), sc);
                                  ^^^^^^^^^^^^

Passing this is not necessary and is wrong when you would need to call
build_constructor.  Please pass NULL_TREE here.

-Nathan

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

* Re: Vector shifting patch
  2010-10-27 13:50                           ` Artem Shinkarov
@ 2010-10-27 14:17                             ` Joseph S. Myers
  2010-10-27 16:16                               ` Artem Shinkarov
  0 siblings, 1 reply; 35+ messages in thread
From: Joseph S. Myers @ 2010-10-27 14:17 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: Nathan Froyd, gcc-patches, Richard Guenther

[-- Attachment #1: Type: TEXT/PLAIN, Size: 4121 bytes --]

On Wed, 27 Oct 2010, Artem Shinkarov wrote:

> > Most of my comments relate to the scalar case which seems more potentially
> > problematic than the case where both operands are vectors.  But in the
> > case where both operands are vectors I note you say nothing about
> > permitted types of the two operands.  Are they required to be exactly the
> > same?  Or can they differ in signedness?  In the width of elements of the
> > vector?
> 
> In case when both operands are vectors my patch requires that they are
> both integer-typed and that the number of elements is the same. On the
> other hand, the existing code c-typeck.c:(build_binary_op):10048
> 
>   if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
>       && (!tree_int_cst_equal (TYPE_SIZE (type0), TYPE_SIZE (type1))
> 	  || !same_scalar_type_ignoring_signedness (TREE_TYPE (type0),
> 						    TREE_TYPE (type1))))
>     {
>       binary_op_error (location, code, type0, type1);
>       return error_mark_node;
>     }
> 
> requires that the base type of the vector has the same width.

But shouldn't the documentation make this explicit for shifts?

There's a general statement in the documentation already that both length 
and signedness must match - but you're describing shifts specially so it 
may not be clear what general statements apply to them.  And why is your 
paragraph about shifts going in between an example for addition, and a 
statement that "Subtraction, multiplication, division, and the logical 
operations operate in a similar manner." - that is, in a similar manner to 
addition?  The effect would seem to be to change the meaning of "similar" 
to refer to shifts rather than addition.  That doesn't seem to be a good 
idea.  Work out what the documentation should look like for the extension 
as a coherent whole, and it might be clearer what if any new statement 
about types is needed.

> > In normal C without vectors, the types of the two operands of a shift are
> > independent.  This would tend to suggest that this should be the case for
> > vectors - they must have the same number of elements, but why constrain
> > things further?  I didn't see any such constraint in the OpenCL
> > specification, although I note that OpenCL doesn't permit scalar << vector
> > or scalar >> vector.
> 
> Again, I agree, but then we should do the same stuff for operations +,
> -, *, /, ...
> because we can have an expression in C like: <int> + <char> * <short>
> and the type inference would do the job.

In C, the integer promotions apply to operands of both + and <<.  For 
vector operations they are deliberately excluded - you can operate on 
vector char, but not directly on char.

However, in C the *usual arithmetic conversions* (a superset of the 
integer promotions) apply for + but not <<; there is no requirement to 
form a common type as there is for arithmetic operations.  So the general 
vector rules appear to be being expanded to say:

* no integer promotions

* no usual arithmetic conversions

* must have a common type for vectors (without such promotions / 
conversions) even for shifts when ISO C doesn't require a common type for 
scalars

> OpenCL allows scalar <op> vector for most of the arithmetic
> operations, so I thought that it would be nice to have this for shifts
> as well, considering the fact that vector shift where the second
> operator is a scalar is ok.
> 
> I don't see how the conversion of the expression 0x12345678 <<
> {1,1,1,1} in compile time is different from the conversion of the
> expression:
> vector int x = (vector int){0x12345678, 0x123456778, ...} << {1,1,1,1}
> which is allowed. Ok, in that case we will get warnings if -Woferflow
> is on.

The point I had was when the shift amount was vector char - so if you 
convert the LHS to the type of the RHS then you have (vector char){0x78, 
0x78, 0x78, 0x78}.  Truncating a scalar like that seems a further step 
beyond the rules listed above, and it doesn't seem a particularly 
desirable step to me.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: Vector shifting patch
  2010-10-27 14:17                             ` Joseph S. Myers
@ 2010-10-27 16:16                               ` Artem Shinkarov
  2010-10-27 18:30                                 ` Joseph S. Myers
  0 siblings, 1 reply; 35+ messages in thread
From: Artem Shinkarov @ 2010-10-27 16:16 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: Nathan Froyd, gcc-patches, Richard Guenther

On Wed, Oct 27, 2010 at 1:21 PM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> On Wed, 27 Oct 2010, Artem Shinkarov wrote:
>
>> > Most of my comments relate to the scalar case which seems more potentially
>> > problematic than the case where both operands are vectors.  But in the
>> > case where both operands are vectors I note you say nothing about
>> > permitted types of the two operands.  Are they required to be exactly the
>> > same?  Or can they differ in signedness?  In the width of elements of the
>> > vector?
>>
>> In case when both operands are vectors my patch requires that they are
>> both integer-typed and that the number of elements is the same. On the
>> other hand, the existing code c-typeck.c:(build_binary_op):10048
>>
>>   if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
>>       && (!tree_int_cst_equal (TYPE_SIZE (type0), TYPE_SIZE (type1))
>>         || !same_scalar_type_ignoring_signedness (TREE_TYPE (type0),
>>                                                   TREE_TYPE (type1))))
>>     {
>>       binary_op_error (location, code, type0, type1);
>>       return error_mark_node;
>>     }
>>
>> requires that the base type of the vector has the same width.
>
> But shouldn't the documentation make this explicit for shifts?
>
> There's a general statement in the documentation already that both length
> and signedness must match - but you're describing shifts specially so it
> may not be clear what general statements apply to them.  And why is your
> paragraph about shifts going in between an example for addition, and a
> statement that "Subtraction, multiplication, division, and the logical
> operations operate in a similar manner." - that is, in a similar manner to
> addition?  The effect would seem to be to change the meaning of "similar"
> to refer to shifts rather than addition.  That doesn't seem to be a good
> idea.  Work out what the documentation should look like for the extension
> as a coherent whole, and it might be clearer what if any new statement
> about types is needed.

Oh yes, of course you are right, this paragraph must be one paragraph
lower. Now it looks like this:

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 165913)
+++ gcc/doc/extend.texi	(working copy)
@@ -6315,6 +6315,27 @@ minus or complement operators on a vecto
 elements are the negative or complemented values of the corresponding
 elements in the operand.

+In C it is possible to use shifting operators @code{<<, >>} on integer-type
+vectors. The operation is defined as following: @code{@{a0, a1, @dots{},
+an@} >> @{b0, b1, @dots{}, bn@} == @{a0 >> b0, a1 >> b1, @dots{}, an >>
+bn@}}@. Vector operands must have the same number of elements.
+Additionally one of the operands can be a scalar integer in which case the
+scalar is converted to the type used by the vector operand (with possible
+truncation) and each element of this new vector is the scalar's value.
+Consider the following code.
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a, b, c;
+int i = 1;
+
+b = a >> 1;     /* b = a >> @{1,1,1,1@}; */
+c = 1 << a;     /* c = @{1,1,1,1@} << a; */
+@end smallexample
+
+
+
 In C vectors can be subscripted as if the vector were an array with
 the same number of elements and base type.  Out of bound accesses
 invoke undefined behavior at runtime.  Warnings for out of bound

>
>> > In normal C without vectors, the types of the two operands of a shift are
>> > independent.  This would tend to suggest that this should be the case for
>> > vectors - they must have the same number of elements, but why constrain
>> > things further?  I didn't see any such constraint in the OpenCL
>> > specification, although I note that OpenCL doesn't permit scalar << vector
>> > or scalar >> vector.
>>
>> Again, I agree, but then we should do the same stuff for operations +,
>> -, *, /, ...
>> because we can have an expression in C like: <int> + <char> * <short>
>> and the type inference would do the job.
>
> In C, the integer promotions apply to operands of both + and <<.  For
> vector operations they are deliberately excluded - you can operate on
> vector char, but not directly on char.
>
> However, in C the *usual arithmetic conversions* (a superset of the
> integer promotions) apply for + but not <<; there is no requirement to
> form a common type as there is for arithmetic operations.  So the general
> vector rules appear to be being expanded to say:
>
> * no integer promotions
>
> * no usual arithmetic conversions
>
> * must have a common type for vectors (without such promotions /
> conversions) even for shifts when ISO C doesn't require a common type for
> scalars
>
>> OpenCL allows scalar <op> vector for most of the arithmetic
>> operations, so I thought that it would be nice to have this for shifts
>> as well, considering the fact that vector shift where the second
>> operator is a scalar is ok.
>>
>> I don't see how the conversion of the expression 0x12345678 <<
>> {1,1,1,1} in compile time is different from the conversion of the
>> expression:
>> vector int x = (vector int){0x12345678, 0x123456778, ...} << {1,1,1,1}
>> which is allowed. Ok, in that case we will get warnings if -Woferflow
>> is on.
>
> The point I had was when the shift amount was vector char - so if you
> convert the LHS to the type of the RHS then you have (vector char){0x78,
> 0x78, 0x78, 0x78}.  Truncating a scalar like that seems a further step
> beyond the rules listed above, and it doesn't seem a particularly
> desirable step to me.
>

Ok, I do understand your concern, but my following patch
(http://gcc.gnu.org/ml/gcc-patches/2010-08/msg01075.html) implements
scalar <op> vector and vector <op> scalar for op in {+, -, /, ...}. In
that patch for integer types I use the function int_fits_type_p before
I allow scalar to vector conversion. And it would be strange to allow
scalar <op> vector everywhere except shifting operators.

Would it be ok, if I'll use the same int_fits_type_p checking if scalr
fits in the vector type and if not then I'll throw an error. And I'll
add this statement in the documentation.

What do you think about it?



Artem.

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

* Re: Vector shifting patch
  2010-10-27 16:16                               ` Artem Shinkarov
@ 2010-10-27 18:30                                 ` Joseph S. Myers
  2010-10-27 18:41                                   ` Artem Shinkarov
  0 siblings, 1 reply; 35+ messages in thread
From: Joseph S. Myers @ 2010-10-27 18:30 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: Nathan Froyd, gcc-patches, Richard Guenther

On Wed, 27 Oct 2010, Artem Shinkarov wrote:

> Ok, I do understand your concern, but my following patch
> (http://gcc.gnu.org/ml/gcc-patches/2010-08/msg01075.html) implements
> scalar <op> vector and vector <op> scalar for op in {+, -, /, ...}. In
> that patch for integer types I use the function int_fits_type_p before
> I allow scalar to vector conversion. And it would be strange to allow
> scalar <op> vector everywhere except shifting operators.
> 
> Would it be ok, if I'll use the same int_fits_type_p checking if scalr
> fits in the vector type and if not then I'll throw an error. And I'll
> add this statement in the documentation.

That seems safer - but if other operations between scalars and vectors 
aren't supported until a subsequent patch, that clearly indicates that you 
should not be including mixed scalar/vector shifts in this patch - you 
should make this patch only accept vector/vector shifts.  Mixed shifts can 
then go in the patch adding other mixed operations, and be reviewed in the 
context of the full documentation and set of testcases for that patch.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: Vector shifting patch
  2010-10-27 18:30                                 ` Joseph S. Myers
@ 2010-10-27 18:41                                   ` Artem Shinkarov
  2010-10-28  5:53                                     ` Joseph S. Myers
  2010-10-29 18:06                                     ` H.J. Lu
  0 siblings, 2 replies; 35+ messages in thread
From: Artem Shinkarov @ 2010-10-27 18:41 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: Nathan Froyd, gcc-patches, Richard Guenther

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

Ok, then here are vector shifts only.

ChangeLog:

2010-10-25  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
 Andrew Pinski <pinskia@gmail.com>

 gcc/
 * tree.h (build_vector_from_val): Declare.
 * tree.c (build_vector_from_val): New function.
 * c-typeck.c (build_binary_op): Handle vector shifting.
 * doc/extend.texi: Description of the vector shifting operation.

 gcc/testsuite/
 * gcc.c-torture/execute/vector-shift.c: Likewise.
 * gcc.c-torture/execute/vector-shift1.c: New testcase.
 * gcc.c-torture/execute/vector-shift2.c: New testcase.
 * gcc.dg/vector-shift.c: New testcase.
 * gcc.dg/vector-shift1.c: New testcase.
 * gcc.dg/vector-shift2.c: New testcase.
 * gcc.dg/vector-shift3.c: New testcase.

bootstrapped and tested on x86_64_unknown-linux


Artem.

On Wed, Oct 27, 2010 at 5:50 PM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> On Wed, 27 Oct 2010, Artem Shinkarov wrote:
>
>> Ok, I do understand your concern, but my following patch
>> (http://gcc.gnu.org/ml/gcc-patches/2010-08/msg01075.html) implements
>> scalar <op> vector and vector <op> scalar for op in {+, -, /, ...}. In
>> that patch for integer types I use the function int_fits_type_p before
>> I allow scalar to vector conversion. And it would be strange to allow
>> scalar <op> vector everywhere except shifting operators.
>>
>> Would it be ok, if I'll use the same int_fits_type_p checking if scalr
>> fits in the vector type and if not then I'll throw an error. And I'll
>> add this statement in the documentation.
>
> That seems safer - but if other operations between scalars and vectors
> aren't supported until a subsequent patch, that clearly indicates that you
> should not be including mixed scalar/vector shifts in this patch - you
> should make this patch only accept vector/vector shifts.  Mixed shifts can
> then go in the patch adding other mixed operations, and be reviewed in the
> context of the full documentation and set of testcases for that patch.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>

[-- Attachment #2: vectorshift.c.v8.diff --]
[-- Type: text/x-diff, Size: 14572 bytes --]

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 165913)
+++ gcc/doc/extend.texi	(working copy)
@@ -6315,6 +6315,25 @@ minus or complement operators on a vecto
 elements are the negative or complemented values of the corresponding
 elements in the operand.
 
+In C it is possible to use shifting operators @code{<<, >>} on integer-type
+vectors. The operation is defined as following: @code{@{a0, a1, @dots{},
+an@} >> @{b0, b1, @dots{}, bn@} == @{a0 >> b0, a1 >> b1, @dots{}, an >>
+bn@}}@. Vector operands must have the same number of elements.
+Additionally second operands can be a scalar integer in which case the
+scalar is converted to the type used by the vector operand (with possible
+truncation) and each element of this new vector is the scalar's value.
+Consider the following code.
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a, b;
+
+b = a >> 1;     /* b = a >> @{1,1,1,1@}; */
+@end smallexample
+
+
+
 In C vectors can be subscripted as if the vector were an array with
 the same number of elements and base type.  Out of bound accesses
 invoke undefined behavior at runtime.  Warnings for out of bound
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 165913)
+++ gcc/tree.c	(working copy)
@@ -1366,6 +1366,28 @@ build_vector_from_ctor (tree type, VEC(c
   return build_vector (type, nreverse (list));
 }
 
+/* Build a vector of type VECTYPE where all the elements are SCs.  */
+tree
+build_vector_from_val (tree vectype, tree sc) 
+{
+  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
+  VEC(constructor_elt, gc) *v = NULL;
+
+  if (sc == error_mark_node)
+    return sc;
+
+  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
+
+  v = VEC_alloc (constructor_elt, gc, nunits);
+  for (i = 0; i < nunits; ++i)
+    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, sc);
+
+  if (CONSTANT_CLASS_P (sc))
+    return build_vector_from_ctor (vectype, v);
+  else 
+    return build_constructor (vectype, v);
+}
+
 /* Return a new CONSTRUCTOR node whose type is TYPE and whose values
    are in the VEC pointed to by VALS.  */
 tree
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 165913)
+++ gcc/tree.h	(working copy)
@@ -4034,6 +4034,7 @@ extern tree build_int_cst_type (tree, HO
 extern tree build_int_cst_wide (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
 extern tree build_vector (tree, tree);
 extern tree build_vector_from_ctor (tree, VEC(constructor_elt,gc) *);
+extern tree build_vector_from_val (tree, tree);
 extern tree build_constructor (tree, VEC(constructor_elt,gc) *);
 extern tree build_constructor_single (tree, tree, tree);
 extern tree build_constructor_from_list (tree, tree);
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
@@ -0,0 +1,60 @@
+/* dg-do run */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uint unsigned int
+
+int main (int argc, char *argv[]) {
+    vector(4, uint) vuint  = { 1,  2,  3,  4};
+    vector(4,  int) vint0  = { 1,  1,  1,  1};
+    vector(4,  int) vint1  = {-1, -1, -1, -1};
+
+    vector(4,  int) i1, i2, i3;
+    vector(4, uint) u1, u2, u3;
+
+    i1 = vint1<< vint0;
+    
+    if (vidx(int, i1, 0) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 1) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 2) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 3) != ((int)-1 << (int)1))
+        __builtin_abort ();
+
+    u1 = vuint << vint0;
+
+    if (vidx(int, u1, 0) != ((uint)1  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 1) != ((uint)2  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 2) != ((uint)3  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 3) != ((uint)4  << (int)1))
+        __builtin_abort ();
+
+    
+    i2 = vint1 >> vuint;
+
+    if (vidx(int, i2, 0) != ((int)-1  >> (uint)1))
+        __builtin_abort ();
+    if (vidx(int, i2, 1) != ((int)-1  >> (uint)2))
+        __builtin_abort ();
+    if (vidx(int, i2, 2) != ((int)-1  >> (uint)3))
+        __builtin_abort ();
+    if (vidx(int, i2, 3) != ((int)-1  >> (uint)4))
+        __builtin_abort ();
+
+
+    vint1 >>= vuint;
+    
+    vuint <<= vint0;
+    vuint <<= vint1;
+
+
+    return 0;
+}
+
+
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
@@ -0,0 +1,48 @@
+
+#define vector __attribute__((vector_size(sizeof(int)*4) ))
+
+static vector int allones = {1, 1, 1, 1};
+static vector int allzeros = {0, 0, 0, 0};
+static vector int numbers = {0, 1, 2, 3};
+static vector int numbersleftshiftallones = {0, 2, 4, 6};
+static vector int numbersrightshiftallones = {0, 0, 1, 1};
+
+
+static vector unsigned int uallones = {1, 1, 1, 1};
+static vector unsigned int uallzeros = {0, 0, 0, 0};
+static vector unsigned int unumbers = {0, 1, 2, 3};
+static vector unsigned int unumbersleftshiftallones = {0, 2, 4, 6};
+static vector unsigned int unumbersrightshiftallones = {0, 0, 1, 1};
+
+#define TEST(result, expected) \
+do { \
+  typeof(result) result1 = result; \
+  if(sizeof (result1) != sizeof (expected)) \
+    __builtin_abort (); \
+  if (__builtin_memcmp (&result1, &expected, sizeof(result1)) != 0) \
+    __builtin_abort (); \
+}while (0);
+
+int main(void)
+{
+  vector int result;
+  TEST ((numbers << allzeros), numbers);
+  TEST ((numbers >> allzeros), numbers);
+  TEST((numbers << allones), numbersleftshiftallones);
+  TEST((numbers >> allones), numbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((numbers << allones) >> allones, numbers);
+  
+  
+  
+  TEST ((unumbers << uallzeros), unumbers);
+  TEST ((unumbers >> uallzeros), unumbers);
+  TEST((unumbers << uallones), unumbersleftshiftallones);
+  TEST((unumbers >> uallones), unumbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((unumbers << uallones) >> uallones, unumbers);
+
+  return 0;  
+}
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
@@ -0,0 +1,17 @@
+#define vector __attribute__((vector_size(8*sizeof(short))))
+
+int main (int argc, char *argv[]) {
+  vector short v0 = {argc,2,3,4,5,6,7};
+  vector short v1 = {2,2,2,2,2,2,2};
+  vector short r1,r2,r3,r4;
+  int i = 8;
+
+  r1 = v0 << 1;
+  r2 = v0 >> 1;
+
+  r3 = v0 << v1;
+  r4 = v0 >> v1;
+
+  return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4,char) vchar = {1,2,3,4};
+    vector(4, int) vint  = {1,1,1,1};
+    
+    vint <<= vchar;  /* { dg-error "nvalid operands to binary <<" } */
+    vchar >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4, float) vfloat0 = {1., 2., 3., 4.};
+    vector(4, float) vfloat1 = {1., 2., 3., 4.};
+    
+    vector(4,   int) vint   = {1,  1,  1,  1 };
+    
+    vint <<= vfloat0;  /* { dg-error "nvalid operands to binary <<" } */
+    vfloat0 >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    vfloat0 <<= vfloat1;  /* { dg-error "nvalid operands to binary <<" } */
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+/* { dg-options "-fno-var-tracking-assignments" } */
+
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uchar unsigned char
+
+#define ch14 1,2,3,4
+#define ch1  1,1,1,1
+#define chm1 -1,-1,-1,-1
+
+int main (int argc, char *argv[]) {
+    vector(16, uchar) vuchar  = { ch14, ch14, ch14, ch14};
+    vector(16,  char) vchar0  = { ch1, ch1, ch1, ch1};
+    vector(16,  char) vchar1  = { chm1, chm1, chm1, chm1};
+
+    vector(16,  char) i1, i2, i3;
+    vector(16, uchar) u1, u2, u3;
+
+    i1 = vchar1<< vchar0;
+    
+    if (vidx(char, i1, 0) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 1) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 2) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 3) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    u1 = vuchar << vchar0;
+
+    if (vidx(char, u1, 0) != ((uchar)1  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 1) != ((uchar)2  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 2) != ((uchar)3  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 3) != ((uchar)4  << (char)1))
+        __builtin_abort ();
+
+    
+    i2 = vchar1 >> vuchar;
+
+    if (vidx(char, i2, 0) != ((char)-1  >> (uchar)1))
+        __builtin_abort ();
+    if (vidx(char, i2, 1) != ((char)-1  >> (uchar)2))
+        __builtin_abort ();
+    if (vidx(char, i2, 2) != ((char)-1  >> (uchar)3))
+        __builtin_abort ();
+    if (vidx(char, i2, 3) != ((char)-1  >> (uchar)4))
+        __builtin_abort ();
+    
+    vchar1 >>= vuchar;
+    vuchar <<= vchar0;
+    vuchar <<= vchar1;
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift3.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift3.c	(revision 0)
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+
+#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};
+    short sc;
+
+    
+    scalar1 <<= v0; /* { dg-error ".*scalar1.*undeclared" } */
+   
+    return 0;
+}
+
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 165913)
+++ gcc/c-typeck.c	(working copy)
@@ -9727,7 +9727,21 @@ build_binary_op (location_t location, en
 	 Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9754,9 +9768,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
@@ -9764,7 +9779,21 @@ build_binary_op (location_t location, en
       break;
 
     case LSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9786,9 +9815,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;

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

* Re: Vector shifting patch
  2010-10-27 18:41                                   ` Artem Shinkarov
@ 2010-10-28  5:53                                     ` Joseph S. Myers
  2010-10-28 13:00                                       ` Artem Shinkarov
  2010-10-29 18:06                                     ` H.J. Lu
  1 sibling, 1 reply; 35+ messages in thread
From: Joseph S. Myers @ 2010-10-28  5:53 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: Nathan Froyd, gcc-patches, Richard Guenther

On Wed, 27 Oct 2010, Artem Shinkarov wrote:

> Ok, then here are vector shifts only.

This version is getting closer:

> +In C it is possible to use shifting operators @code{<<, >>} on integer-type

The comma should be outside @code: @code{<<}, @code{>>}.

> Index: gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
> ===================================================================
> --- gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
> +++ gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
> @@ -0,0 +1,60 @@
> +/* dg-do run */

dg- directives have no effect in gcc.c-torture/execute, and if they were 
to have an effect they'd need to be properly marked up: { dg-do run }.

> Index: gcc/testsuite/gcc.dg/vector-shift2.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
> +++ gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
> @@ -0,0 +1,61 @@
> +/* { dg-do run } */
> +/* { dg-options "-fno-var-tracking-assignments" } */

Why this option?  It seems to have no relation to the test.

Apart from that the C front-end changes seem OK.

-- 
Joseph S. Myers
joseph@codesourcery.com

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

* Re: Vector shifting patch
  2010-10-28  5:53                                     ` Joseph S. Myers
@ 2010-10-28 13:00                                       ` Artem Shinkarov
  2010-10-29 15:50                                         ` Richard Guenther
  0 siblings, 1 reply; 35+ messages in thread
From: Artem Shinkarov @ 2010-10-28 13:00 UTC (permalink / raw)
  To: Joseph S. Myers; +Cc: Nathan Froyd, gcc-patches, Richard Guenther

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

On Wed, Oct 27, 2010 at 10:14 PM, Joseph S. Myers
<joseph@codesourcery.com> wrote:
> On Wed, 27 Oct 2010, Artem Shinkarov wrote:
>
>> Ok, then here are vector shifts only.
>
> This version is getting closer:
>
>> +In C it is possible to use shifting operators @code{<<, >>} on integer-type
>
> The comma should be outside @code: @code{<<}, @code{>>}.

Fixed.

>
>> Index: gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
>> ===================================================================
>> --- gcc/testsuite/gcc.c-torture/execute/vector-shift2.c       (revision 0)
>> +++ gcc/testsuite/gcc.c-torture/execute/vector-shift2.c       (revision 0)
>> @@ -0,0 +1,60 @@
>> +/* dg-do run */
>
> dg- directives have no effect in gcc.c-torture/execute, and if they were
> to have an effect they'd need to be properly marked up: { dg-do run }.

Fixed. That was the copying issue.

>
>> Index: gcc/testsuite/gcc.dg/vector-shift2.c
>> ===================================================================
>> --- gcc/testsuite/gcc.dg/vector-shift2.c      (revision 0)
>> +++ gcc/testsuite/gcc.dg/vector-shift2.c      (revision 0)
>> @@ -0,0 +1,61 @@
>> +/* { dg-do run } */
>> +/* { dg-options "-fno-var-tracking-assignments" } */
>
> Why this option?  It seems to have no relation to the test.

This option is because of the bug:
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44569

If you compile the code from gcc/testsuite/gcc.dg/vector-shift2.c with
combination "-g -O3" then you will have a compiler internal error. But
this error has nothing to do with this patch.

>
> Apart from that the C front-end changes seem OK.
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>

Richard, could you please submit the patch?



Artem.

[-- Attachment #2: vectorshift.c.v8.diff --]
[-- Type: text/x-diff, Size: 14560 bytes --]

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 165913)
+++ gcc/doc/extend.texi	(working copy)
@@ -6315,6 +6315,24 @@ minus or complement operators on a vecto
 elements are the negative or complemented values of the corresponding
 elements in the operand.
 
+In C it is possible to use shifting operators @code{<<}, @code{>>} on
+integer-type vectors. The operation is defined as following: @code{@{a0,
+a1, @dots{}, an@} >> @{b0, b1, @dots{}, bn@} == @{a0 >> b0, a1 >> b1,
+@dots{}, an >> bn@}}@. Vector operands must have the same number of
+elements.  Additionally second operands can be a scalar integer in which
+case the scalar is converted to the type used by the vector operand (with
+possible truncation) and each element of this new vector is the scalar's
+value.
+Consider the following code.
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a, b;
+
+b = a >> 1;     /* b = a >> @{1,1,1,1@}; */
+@end smallexample
+
 In C vectors can be subscripted as if the vector were an array with
 the same number of elements and base type.  Out of bound accesses
 invoke undefined behavior at runtime.  Warnings for out of bound
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 165913)
+++ gcc/tree.c	(working copy)
@@ -1366,6 +1366,28 @@ build_vector_from_ctor (tree type, VEC(c
   return build_vector (type, nreverse (list));
 }
 
+/* Build a vector of type VECTYPE where all the elements are SCs.  */
+tree
+build_vector_from_val (tree vectype, tree sc) 
+{
+  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
+  VEC(constructor_elt, gc) *v = NULL;
+
+  if (sc == error_mark_node)
+    return sc;
+
+  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
+
+  v = VEC_alloc (constructor_elt, gc, nunits);
+  for (i = 0; i < nunits; ++i)
+    CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, sc);
+
+  if (CONSTANT_CLASS_P (sc))
+    return build_vector_from_ctor (vectype, v);
+  else 
+    return build_constructor (vectype, v);
+}
+
 /* Return a new CONSTRUCTOR node whose type is TYPE and whose values
    are in the VEC pointed to by VALS.  */
 tree
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 165913)
+++ gcc/tree.h	(working copy)
@@ -4034,6 +4034,7 @@ extern tree build_int_cst_type (tree, HO
 extern tree build_int_cst_wide (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
 extern tree build_vector (tree, tree);
 extern tree build_vector_from_ctor (tree, VEC(constructor_elt,gc) *);
+extern tree build_vector_from_val (tree, tree);
 extern tree build_constructor (tree, VEC(constructor_elt,gc) *);
 extern tree build_constructor_single (tree, tree, tree);
 extern tree build_constructor_from_list (tree, tree);
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
@@ -0,0 +1,59 @@
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uint unsigned int
+
+int main (int argc, char *argv[]) {
+    vector(4, uint) vuint  = { 1,  2,  3,  4};
+    vector(4,  int) vint0  = { 1,  1,  1,  1};
+    vector(4,  int) vint1  = {-1, -1, -1, -1};
+
+    vector(4,  int) i1, i2, i3;
+    vector(4, uint) u1, u2, u3;
+
+    i1 = vint1<< vint0;
+    
+    if (vidx(int, i1, 0) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 1) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 2) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 3) != ((int)-1 << (int)1))
+        __builtin_abort ();
+
+    u1 = vuint << vint0;
+
+    if (vidx(int, u1, 0) != ((uint)1  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 1) != ((uint)2  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 2) != ((uint)3  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 3) != ((uint)4  << (int)1))
+        __builtin_abort ();
+
+    
+    i2 = vint1 >> vuint;
+
+    if (vidx(int, i2, 0) != ((int)-1  >> (uint)1))
+        __builtin_abort ();
+    if (vidx(int, i2, 1) != ((int)-1  >> (uint)2))
+        __builtin_abort ();
+    if (vidx(int, i2, 2) != ((int)-1  >> (uint)3))
+        __builtin_abort ();
+    if (vidx(int, i2, 3) != ((int)-1  >> (uint)4))
+        __builtin_abort ();
+
+
+    vint1 >>= vuint;
+    
+    vuint <<= vint0;
+    vuint <<= vint1;
+
+
+    return 0;
+}
+
+
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
@@ -0,0 +1,48 @@
+
+#define vector __attribute__((vector_size(sizeof(int)*4) ))
+
+static vector int allones = {1, 1, 1, 1};
+static vector int allzeros = {0, 0, 0, 0};
+static vector int numbers = {0, 1, 2, 3};
+static vector int numbersleftshiftallones = {0, 2, 4, 6};
+static vector int numbersrightshiftallones = {0, 0, 1, 1};
+
+
+static vector unsigned int uallones = {1, 1, 1, 1};
+static vector unsigned int uallzeros = {0, 0, 0, 0};
+static vector unsigned int unumbers = {0, 1, 2, 3};
+static vector unsigned int unumbersleftshiftallones = {0, 2, 4, 6};
+static vector unsigned int unumbersrightshiftallones = {0, 0, 1, 1};
+
+#define TEST(result, expected) \
+do { \
+  typeof(result) result1 = result; \
+  if(sizeof (result1) != sizeof (expected)) \
+    __builtin_abort (); \
+  if (__builtin_memcmp (&result1, &expected, sizeof(result1)) != 0) \
+    __builtin_abort (); \
+}while (0);
+
+int main(void)
+{
+  vector int result;
+  TEST ((numbers << allzeros), numbers);
+  TEST ((numbers >> allzeros), numbers);
+  TEST((numbers << allones), numbersleftshiftallones);
+  TEST((numbers >> allones), numbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((numbers << allones) >> allones, numbers);
+  
+  
+  
+  TEST ((unumbers << uallzeros), unumbers);
+  TEST ((unumbers >> uallzeros), unumbers);
+  TEST((unumbers << uallones), unumbersleftshiftallones);
+  TEST((unumbers >> uallones), unumbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((unumbers << uallones) >> uallones, unumbers);
+
+  return 0;  
+}
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
@@ -0,0 +1,17 @@
+#define vector __attribute__((vector_size(8*sizeof(short))))
+
+int main (int argc, char *argv[]) {
+  vector short v0 = {argc,2,3,4,5,6,7};
+  vector short v1 = {2,2,2,2,2,2,2};
+  vector short r1,r2,r3,r4;
+  int i = 8;
+
+  r1 = v0 << 1;
+  r2 = v0 >> 1;
+
+  r3 = v0 << v1;
+  r4 = v0 >> v1;
+
+  return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4,char) vchar = {1,2,3,4};
+    vector(4, int) vint  = {1,1,1,1};
+    
+    vint <<= vchar;  /* { dg-error "nvalid operands to binary <<" } */
+    vchar >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4, float) vfloat0 = {1., 2., 3., 4.};
+    vector(4, float) vfloat1 = {1., 2., 3., 4.};
+    
+    vector(4,   int) vint   = {1,  1,  1,  1 };
+    
+    vint <<= vfloat0;  /* { dg-error "nvalid operands to binary <<" } */
+    vfloat0 >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    vfloat0 <<= vfloat1;  /* { dg-error "nvalid operands to binary <<" } */
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+/* { dg-options "-fno-var-tracking-assignments" } */
+
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uchar unsigned char
+
+#define ch14 1,2,3,4
+#define ch1  1,1,1,1
+#define chm1 -1,-1,-1,-1
+
+int main (int argc, char *argv[]) {
+    vector(16, uchar) vuchar  = { ch14, ch14, ch14, ch14};
+    vector(16,  char) vchar0  = { ch1, ch1, ch1, ch1};
+    vector(16,  char) vchar1  = { chm1, chm1, chm1, chm1};
+
+    vector(16,  char) i1, i2, i3;
+    vector(16, uchar) u1, u2, u3;
+
+    i1 = vchar1<< vchar0;
+    
+    if (vidx(char, i1, 0) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 1) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 2) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 3) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    u1 = vuchar << vchar0;
+
+    if (vidx(char, u1, 0) != ((uchar)1  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 1) != ((uchar)2  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 2) != ((uchar)3  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 3) != ((uchar)4  << (char)1))
+        __builtin_abort ();
+
+    
+    i2 = vchar1 >> vuchar;
+
+    if (vidx(char, i2, 0) != ((char)-1  >> (uchar)1))
+        __builtin_abort ();
+    if (vidx(char, i2, 1) != ((char)-1  >> (uchar)2))
+        __builtin_abort ();
+    if (vidx(char, i2, 2) != ((char)-1  >> (uchar)3))
+        __builtin_abort ();
+    if (vidx(char, i2, 3) != ((char)-1  >> (uchar)4))
+        __builtin_abort ();
+    
+    vchar1 >>= vuchar;
+    vuchar <<= vchar0;
+    vuchar <<= vchar1;
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift3.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift3.c	(revision 0)
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+
+#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};
+    short sc;
+
+    
+    scalar1 <<= v0; /* { dg-error ".*scalar1.*undeclared" } */
+   
+    return 0;
+}
+
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 165913)
+++ gcc/c-typeck.c	(working copy)
@@ -9727,7 +9727,21 @@ build_binary_op (location_t location, en
 	 Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9754,9 +9768,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
@@ -9764,7 +9779,21 @@ build_binary_op (location_t location, en
       break;
 
     case LSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9786,9 +9815,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;

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

* Re: Vector shifting patch
  2010-10-28 13:00                                       ` Artem Shinkarov
@ 2010-10-29 15:50                                         ` Richard Guenther
  0 siblings, 0 replies; 35+ messages in thread
From: Richard Guenther @ 2010-10-29 15:50 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: Joseph S. Myers, Nathan Froyd, gcc-patches

On Thu, Oct 28, 2010 at 12:22 PM, Artem Shinkarov
<artyom.shinkaroff@gmail.com> wrote:
> On Wed, Oct 27, 2010 at 10:14 PM, Joseph S. Myers
> <joseph@codesourcery.com> wrote:
>> On Wed, 27 Oct 2010, Artem Shinkarov wrote:
>>
>>> Ok, then here are vector shifts only.
>>
>> This version is getting closer:
>>
>>> +In C it is possible to use shifting operators @code{<<, >>} on integer-type
>>
>> The comma should be outside @code: @code{<<}, @code{>>}.
>
> Fixed.
>
>>
>>> Index: gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
>>> ===================================================================
>>> --- gcc/testsuite/gcc.c-torture/execute/vector-shift2.c       (revision 0)
>>> +++ gcc/testsuite/gcc.c-torture/execute/vector-shift2.c       (revision 0)
>>> @@ -0,0 +1,60 @@
>>> +/* dg-do run */
>>
>> dg- directives have no effect in gcc.c-torture/execute, and if they were
>> to have an effect they'd need to be properly marked up: { dg-do run }.
>
> Fixed. That was the copying issue.
>
>>
>>> Index: gcc/testsuite/gcc.dg/vector-shift2.c
>>> ===================================================================
>>> --- gcc/testsuite/gcc.dg/vector-shift2.c      (revision 0)
>>> +++ gcc/testsuite/gcc.dg/vector-shift2.c      (revision 0)
>>> @@ -0,0 +1,61 @@
>>> +/* { dg-do run } */
>>> +/* { dg-options "-fno-var-tracking-assignments" } */
>>
>> Why this option?  It seems to have no relation to the test.
>
> This option is because of the bug:
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44569
>
> If you compile the code from gcc/testsuite/gcc.dg/vector-shift2.c with
> combination "-g -O3" then you will have a compiler internal error. But
> this error has nothing to do with this patch.
>
>>
>> Apart from that the C front-end changes seem OK.
>>
>> --
>> Joseph S. Myers
>> joseph@codesourcery.com
>>
>
> Richard, could you please submit the patch?

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied as rev. 166061.

I had to fix gcc.dg/simd-1b.c which was testing for error on a now valid
vector - vector shift.  I also removed the -fno-var-tracking-assignments flag
and moved the testcase to the torture.

As of mixed shifts I think vector <<>> scalar is an obvious thing to support
as we do have both direct middle-end and target support for these.  For
scalar <<>> vector shifts we can't really allow truncation for scalar.
 So I think
with mixed scalar vector operations we have a third thing similar to
C integer promotions and C usual arithmetic conversions, namely vector
promotion rules which basically would say that for mixed scalar, vector
operands this promotion promotes the scalar to a vector with the same
number of elements as the other vector.  Now the question is whether
(and where) we would need to enforce that the resulting vector mode
is of the same size.  Considering

char c;
int i;
c << (vector int){1, 2, 3, 4};

which either would produce v4qi << v4si giving a v4qi result or
v4si << v4si giving a v4si result.  I _think_ the former makes more
sense from a language point of view (but is not nice to the target
support code which would prefer a v4si result).

I think we should deal with scalar <<>> vector and vector <<>> scalar
separately.

Richard.

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

* Re: Vector shifting patch
  2010-10-27 18:41                                   ` Artem Shinkarov
  2010-10-28  5:53                                     ` Joseph S. Myers
@ 2010-10-29 18:06                                     ` H.J. Lu
  1 sibling, 0 replies; 35+ messages in thread
From: H.J. Lu @ 2010-10-29 18:06 UTC (permalink / raw)
  To: Artem Shinkarov
  Cc: Joseph S. Myers, Nathan Froyd, gcc-patches, Richard Guenther

On Wed, Oct 27, 2010 at 10:43 AM, Artem Shinkarov
<artyom.shinkaroff@gmail.com> wrote:
> Ok, then here are vector shifts only.
>
> ChangeLog:
>
> 2010-10-25  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
>  Andrew Pinski <pinskia@gmail.com>
>
>  gcc/
>  * tree.h (build_vector_from_val): Declare.
>  * tree.c (build_vector_from_val): New function.
>  * c-typeck.c (build_binary_op): Handle vector shifting.
>  * doc/extend.texi: Description of the vector shifting operation.
>
>  gcc/testsuite/
>  * gcc.c-torture/execute/vector-shift.c: Likewise.
>  * gcc.c-torture/execute/vector-shift1.c: New testcase.
>  * gcc.c-torture/execute/vector-shift2.c: New testcase.
>  * gcc.dg/vector-shift.c: New testcase.
>  * gcc.dg/vector-shift1.c: New testcase.
>  * gcc.dg/vector-shift2.c: New testcase.
>  * gcc.dg/vector-shift3.c: New testcase.
>
> bootstrapped and tested on x86_64_unknown-linux
>
>

This caused:

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=46227


H.J.

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

* Re: Vector shifting patch
  2010-10-29 19:03   ` H.J. Lu
@ 2010-10-30  7:45     ` Richard Guenther
  0 siblings, 0 replies; 35+ messages in thread
From: Richard Guenther @ 2010-10-30  7:45 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Artem Shinkarov, Dominique Dhumieres, gcc-patches

On Fri, Oct 29, 2010 at 7:09 PM, H.J. Lu <hjl.tools@gmail.com> wrote:
> On Fri, Oct 29, 2010 at 9:39 AM, Artem Shinkarov
> <artyom.shinkaroff@gmail.com> wrote:
>> I don't know why Richard removed -fno-var-tracking-assignments
>> the bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44569
>> is still there, and this option is required to prevent this error.
>>
>> I cannot commit to svn, but the solution is to add a
>> /* { dg-options "-fno-var-tracking-assignments" } */
>>
>> in vector-shift2.c
>>
>>
>
> That is NOT a fix.

There is already a bug about this which is why I removed this workaround
in the first place.  We should really address this bug.

Richard.

> --
> H.J.
>

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

* Re: Vector shifting patch
  2010-10-29 18:12 ` Artem Shinkarov
  2010-10-29 18:14   ` Andrew Pinski
  2010-10-29 18:27   ` Dominique Dhumieres
@ 2010-10-29 19:03   ` H.J. Lu
  2010-10-30  7:45     ` Richard Guenther
  2 siblings, 1 reply; 35+ messages in thread
From: H.J. Lu @ 2010-10-29 19:03 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: Dominique Dhumieres, gcc-patches, richard.guenther

On Fri, Oct 29, 2010 at 9:39 AM, Artem Shinkarov
<artyom.shinkaroff@gmail.com> wrote:
> I don't know why Richard removed -fno-var-tracking-assignments
> the bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44569
> is still there, and this option is required to prevent this error.
>
> I cannot commit to svn, but the solution is to add a
> /* { dg-options "-fno-var-tracking-assignments" } */
>
> in vector-shift2.c
>
>

That is NOT a fix.

-- 
H.J.

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

* Re: Vector shifting patch
  2010-10-29 18:14   ` Andrew Pinski
@ 2010-10-29 18:41     ` Artem Shinkarov
  0 siblings, 0 replies; 35+ messages in thread
From: Artem Shinkarov @ 2010-10-29 18:41 UTC (permalink / raw)
  To: Andrew Pinski; +Cc: Dominique Dhumieres, gcc-patches, richard.guenther

On Fri, Oct 29, 2010 at 5:44 PM, Andrew Pinski <pinskia@gmail.com> wrote:
> On Fri, Oct 29, 2010 at 9:39 AM, Artem Shinkarov
> <artyom.shinkaroff@gmail.com> wrote:
>> I don't know why Richard removed -fno-var-tracking-assignments
>> the bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44569
>> is still there, and this option is required to prevent this error.
>>
>> I cannot commit to svn, but the solution is to add a
>> /* { dg-options "-fno-var-tracking-assignments" } */
>
> Or even better fix the bug.  It should not be hard :).
>

I have no experience in that part of the compiler at all. I could try
to fix it but I'll need some guidance there.

For the moment I propose to add  /* { dg-options
"-fno-var-tracking-assignments" } */ in the vector-shift2.c

If you could provide me some help, let's take this offline.


Thanks,
Artem.

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

* Re: Vector shifting patch
  2010-10-29 18:12 ` Artem Shinkarov
  2010-10-29 18:14   ` Andrew Pinski
@ 2010-10-29 18:27   ` Dominique Dhumieres
  2010-10-29 19:03   ` H.J. Lu
  2 siblings, 0 replies; 35+ messages in thread
From: Dominique Dhumieres @ 2010-10-29 18:27 UTC (permalink / raw)
  To: dominiq, artyom.shinkaroff; +Cc: richard.guenther, gcc-patches

> I cannot commit to svn, but the solution is to add a
> /* { dg-options "-fno-var-tracking-assignments" } */
> in vector-shift2.c

This fixes the test, thanks

Dominique

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

* Re: Vector shifting patch
  2010-10-29 18:12 ` Artem Shinkarov
@ 2010-10-29 18:14   ` Andrew Pinski
  2010-10-29 18:41     ` Artem Shinkarov
  2010-10-29 18:27   ` Dominique Dhumieres
  2010-10-29 19:03   ` H.J. Lu
  2 siblings, 1 reply; 35+ messages in thread
From: Andrew Pinski @ 2010-10-29 18:14 UTC (permalink / raw)
  To: Artem Shinkarov; +Cc: Dominique Dhumieres, gcc-patches, richard.guenther

On Fri, Oct 29, 2010 at 9:39 AM, Artem Shinkarov
<artyom.shinkaroff@gmail.com> wrote:
> I don't know why Richard removed -fno-var-tracking-assignments
> the bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44569
> is still there, and this option is required to prevent this error.
>
> I cannot commit to svn, but the solution is to add a
> /* { dg-options "-fno-var-tracking-assignments" } */

Or even better fix the bug.  It should not be hard :).

-- Pinski

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

* Re: Vector shifting patch
  2010-10-29 17:42 Dominique Dhumieres
@ 2010-10-29 18:12 ` Artem Shinkarov
  2010-10-29 18:14   ` Andrew Pinski
                     ` (2 more replies)
  0 siblings, 3 replies; 35+ messages in thread
From: Artem Shinkarov @ 2010-10-29 18:12 UTC (permalink / raw)
  To: Dominique Dhumieres; +Cc: gcc-patches, richard.guenther

I don't know why Richard removed -fno-var-tracking-assignments
the bug http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44569
is still there, and this option is required to prevent this error.

I cannot commit to svn, but the solution is to add a
/* { dg-options "-fno-var-tracking-assignments" } */

in vector-shift2.c


Artem.


On Fri, Oct 29, 2010 at 5:29 PM, Dominique Dhumieres <dominiq@lps.ens.fr> wrote:
> On x86_64-apple-darwin10.4.0, compiling gcc.dg/torture/vector-shift2.c
> with -O3 -g gives an ICE:
>
> [macbook] f90/bug% gcc46 /opt/gcc/work/gcc/testsuite/gcc.dg/torture/vector-shift2.c  -O3 -g
> /opt/gcc/work/gcc/testsuite/gcc.dg/torture/vector-shift2.c: In function 'main':
> /opt/gcc/work/gcc/testsuite/gcc.dg/torture/vector-shift2.c:59:1: internal compiler error: in simplify_subreg, at simplify-rtx.c:5217
>
> with both -m32 and -m64.
>
> TIA
>
> Dominique
>

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

* Re: Vector shifting patch
@ 2010-10-29 17:42 Dominique Dhumieres
  2010-10-29 18:12 ` Artem Shinkarov
  0 siblings, 1 reply; 35+ messages in thread
From: Dominique Dhumieres @ 2010-10-29 17:42 UTC (permalink / raw)
  To: gcc-patches; +Cc: artyom.shinkaroff, richard.guenther

On x86_64-apple-darwin10.4.0, compiling gcc.dg/torture/vector-shift2.c 
with -O3 -g gives an ICE:

[macbook] f90/bug% gcc46 /opt/gcc/work/gcc/testsuite/gcc.dg/torture/vector-shift2.c  -O3 -g
/opt/gcc/work/gcc/testsuite/gcc.dg/torture/vector-shift2.c: In function 'main':
/opt/gcc/work/gcc/testsuite/gcc.dg/torture/vector-shift2.c:59:1: internal compiler error: in simplify_subreg, at simplify-rtx.c:5217

with both -m32 and -m64.

TIA

Dominique

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

* Vector shifting patch
@ 2010-10-26 13:13 Artem Shinkarov
  0 siblings, 0 replies; 35+ messages in thread
From: Artem Shinkarov @ 2010-10-26 13:13 UTC (permalink / raw)
  To: gcc-patches; +Cc: Joseph S. Myers, Richard Guenther

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

I am continuing my vector patch submission. Now it is a vector shift patch.
(yesterday my messages had not reached the gcc-patches mailing list)


This patch allows integer-type vector shifts. The operation is defined
as following:
{a0, a1, ..., an} >> {b0, b1, ..., bn} == {a0 >> b0, a1 >> b1, ..., an >> bn}.
Operations "vec >> scal" and "scal >> vec" are supported as well, in
that case scalar is expanded to the vector of scalars according to the
type of the other operand.


ChangeLog:

2010-10-25  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
 Andrew Pinski <pinskia@gmail.com>

 gcc/
 * tree.h (build_vector_from_val): Declare.
 * tree.c (build_vector_from_val): New function.
 * c-typeck.c (build_binary_op): Handle vector shifting.

 gcc/testsuite/
 * gcc.c-torture/execute/vector-shift.c: Likewise.
 * gcc.c-torture/execute/vector-shift1.c: New testcase.
 * gcc.c-torture/execute/vector-shift2.c: New testcase.
 * gcc.dg/vector-shift.c: New testcase.
 * gcc.dg/vector-shift1.c: New testcase.
 * gcc.dg/vector-shift2.c: New testcase.
 * gcc.dg/vector-shift3.c: New testcase.
 * gcc.dg/vector-shift4.c: New testcase.

bootstrapped and tested on x86_64_unknown-linux

OK?

[-- Attachment #2: vectorshift.c.v7.diff --]
[-- Type: text/x-diff, Size: 15910 bytes --]

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 165913)
+++ gcc/doc/extend.texi	(working copy)
@@ -6309,6 +6309,23 @@ v4si a, b, c;
 c = a + b;
 @end smallexample
 
+In C it is possible to use shifting operators @code{<<, >>} on integer-type
+vectors. The operation is defined as following: @code{@{a0, a1, ..., an@} >> @{b0, b1,
+..., bn@} == @{a0 >> b0, a1 >> b1, ..., an >> bn@}}@.  Additionally one of the
+operands can be a scalar integer in which case the scalar is converted to the
+type used by the vector operand and each element of this new vector is the
+scalar's value.  Consider the following code.
+
+@smallexample
+typedef int v4si __attribute__ ((vector_size (16)));
+
+v4si a, b, c;
+int i = 1;
+
+b = a >> 1;     /* b = a >> @{1,1,1,1@}; */
+c = 1 << a;     /* c = @{1,1,1,1@} << a; */
+@end smallexample
+
 Subtraction, multiplication, division, and the logical operations
 operate in a similar manner.  Likewise, the result of using the unary
 minus or complement operators on a vector type is a vector whose
Index: gcc/tree.c
===================================================================
--- gcc/tree.c	(revision 165913)
+++ gcc/tree.c	(working copy)
@@ -1366,6 +1366,28 @@ build_vector_from_ctor (tree type, VEC(c
   return build_vector (type, nreverse (list));
 }
 
+/* Build a vector of type VECTYPE where all the elements are SCs.  */
+tree
+build_vector_from_val (tree vectype, tree sc) 
+{
+  int i, nunits = TYPE_VECTOR_SUBPARTS (vectype);
+  VEC(constructor_elt, gc) *v = NULL;
+
+  if (sc == error_mark_node)
+    return sc;
+
+  gcc_assert (TREE_TYPE (sc) == TREE_TYPE (vectype));
+
+  v = VEC_alloc (constructor_elt, gc, nunits);
+  for (i = 0; i < nunits; ++i)
+    CONSTRUCTOR_APPEND_ELT (v, size_int (i), sc);
+
+  if (CONSTANT_CLASS_P (sc))
+    return build_vector_from_ctor (vectype, v);
+  else 
+    return build_constructor (vectype, v);
+}
+
 /* Return a new CONSTRUCTOR node whose type is TYPE and whose values
    are in the VEC pointed to by VALS.  */
 tree
Index: gcc/tree.h
===================================================================
--- gcc/tree.h	(revision 165913)
+++ gcc/tree.h	(working copy)
@@ -4034,6 +4034,7 @@ extern tree build_int_cst_type (tree, HO
 extern tree build_int_cst_wide (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT);
 extern tree build_vector (tree, tree);
 extern tree build_vector_from_ctor (tree, VEC(constructor_elt,gc) *);
+extern tree build_vector_from_val (tree, tree);
 extern tree build_constructor (tree, VEC(constructor_elt,gc) *);
 extern tree build_constructor_single (tree, tree, tree);
 extern tree build_constructor_from_list (tree, tree);
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift2.c	(revision 0)
@@ -0,0 +1,60 @@
+/* dg-do run */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uint unsigned int
+
+int main (int argc, char *argv[]) {
+    vector(4, uint) vuint  = { 1,  2,  3,  4};
+    vector(4,  int) vint0  = { 1,  1,  1,  1};
+    vector(4,  int) vint1  = {-1, -1, -1, -1};
+
+    vector(4,  int) i1, i2, i3;
+    vector(4, uint) u1, u2, u3;
+
+    i1 = vint1<< vint0;
+    
+    if (vidx(int, i1, 0) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 1) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 2) != ((int)-1 << (int)1))
+        __builtin_abort ();
+    if (vidx(int, i1, 3) != ((int)-1 << (int)1))
+        __builtin_abort ();
+
+    u1 = vuint << vint0;
+
+    if (vidx(int, u1, 0) != ((uint)1  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 1) != ((uint)2  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 2) != ((uint)3  << (int)1))
+        __builtin_abort ();
+    if (vidx(int, u1, 3) != ((uint)4  << (int)1))
+        __builtin_abort ();
+
+    
+    i2 = vint1 >> vuint;
+
+    if (vidx(int, i2, 0) != ((int)-1  >> (uint)1))
+        __builtin_abort ();
+    if (vidx(int, i2, 1) != ((int)-1  >> (uint)2))
+        __builtin_abort ();
+    if (vidx(int, i2, 2) != ((int)-1  >> (uint)3))
+        __builtin_abort ();
+    if (vidx(int, i2, 3) != ((int)-1  >> (uint)4))
+        __builtin_abort ();
+
+
+    vint1 >>= vuint;
+    
+    vuint <<= vint0;
+    vuint <<= vint1;
+
+
+    return 0;
+}
+
+
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift.c	(revision 0)
@@ -0,0 +1,48 @@
+
+#define vector __attribute__((vector_size(sizeof(int)*4) ))
+
+static vector int allones = {1, 1, 1, 1};
+static vector int allzeros = {0, 0, 0, 0};
+static vector int numbers = {0, 1, 2, 3};
+static vector int numbersleftshiftallones = {0, 2, 4, 6};
+static vector int numbersrightshiftallones = {0, 0, 1, 1};
+
+
+static vector unsigned int uallones = {1, 1, 1, 1};
+static vector unsigned int uallzeros = {0, 0, 0, 0};
+static vector unsigned int unumbers = {0, 1, 2, 3};
+static vector unsigned int unumbersleftshiftallones = {0, 2, 4, 6};
+static vector unsigned int unumbersrightshiftallones = {0, 0, 1, 1};
+
+#define TEST(result, expected) \
+do { \
+  typeof(result) result1 = result; \
+  if(sizeof (result1) != sizeof (expected)) \
+    __builtin_abort (); \
+  if (__builtin_memcmp (&result1, &expected, sizeof(result1)) != 0) \
+    __builtin_abort (); \
+}while (0);
+
+int main(void)
+{
+  vector int result;
+  TEST ((numbers << allzeros), numbers);
+  TEST ((numbers >> allzeros), numbers);
+  TEST((numbers << allones), numbersleftshiftallones);
+  TEST((numbers >> allones), numbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((numbers << allones) >> allones, numbers);
+  
+  
+  
+  TEST ((unumbers << uallzeros), unumbers);
+  TEST ((unumbers >> uallzeros), unumbers);
+  TEST((unumbers << uallones), unumbersleftshiftallones);
+  TEST((unumbers >> uallones), unumbersrightshiftallones);
+  /* Test left shift followed by a right shift, numbers should be back as
+     numbers are all small numbers and no lose of precision happens.   */
+  TEST((unumbers << uallones) >> uallones, unumbers);
+
+  return 0;  
+}
Index: gcc/testsuite/gcc.c-torture/execute/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-shift1.c	(revision 0)
@@ -0,0 +1,17 @@
+#define vector __attribute__((vector_size(8*sizeof(short))))
+
+int main (int argc, char *argv[]) {
+  vector short v0 = {argc,2,3,4,5,6,7};
+  vector short v1 = {2,2,2,2,2,2,2};
+  vector short r1,r2,r3,r4;
+  int i = 8;
+
+  r1 = v0 << 1;
+  r2 = 1 << v0;
+
+  r3 = v0 << v1;
+  r4 = v0 >> v1;
+
+  return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift4.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift4.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift4.c	(revision 0)
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+#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};
+    short sc;
+
+    v0 >>= scalar0; /* { dg-error ".*scalar0.*undeclared" } */
+    
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift.c	(revision 0)
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4,char) vchar = {1,2,3,4};
+    vector(4, int) vint  = {1,1,1,1};
+    
+    vint <<= vchar;  /* { dg-error "nvalid operands to binary <<" } */
+    vchar >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift1.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift1.c	(revision 0)
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+int main (int argc, char *argv[]) {
+    vector(4, float) vfloat0 = {1., 2., 3., 4.};
+    vector(4, float) vfloat1 = {1., 2., 3., 4.};
+    
+    vector(4,   int) vint   = {1,  1,  1,  1 };
+    
+    vint <<= vfloat0;  /* { dg-error "nvalid operands to binary <<" } */
+    vfloat0 >>= vint;  /* { dg-error "nvalid operands to binary >>" } */
+
+    vfloat0 <<= vfloat1;  /* { dg-error "nvalid operands to binary <<" } */
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift2.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift2.c	(revision 0)
@@ -0,0 +1,61 @@
+/* { dg-do run } */
+/* { dg-options "-fno-var-tracking-assignments" } */
+
+#define vector(elcount, type)  \
+__attribute__((vector_size((elcount)*sizeof(type)))) type
+
+#define vidx(type, vec, idx) (*((type *) &(vec) + idx))
+#define uchar unsigned char
+
+#define ch14 1,2,3,4
+#define ch1  1,1,1,1
+#define chm1 -1,-1,-1,-1
+
+int main (int argc, char *argv[]) {
+    vector(16, uchar) vuchar  = { ch14, ch14, ch14, ch14};
+    vector(16,  char) vchar0  = { ch1, ch1, ch1, ch1};
+    vector(16,  char) vchar1  = { chm1, chm1, chm1, chm1};
+
+    vector(16,  char) i1, i2, i3;
+    vector(16, uchar) u1, u2, u3;
+
+    i1 = vchar1<< vchar0;
+    
+    if (vidx(char, i1, 0) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 1) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 2) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    if (vidx(char, i1, 3) != ((char)-1 << (char)1))
+        __builtin_abort ();
+    u1 = vuchar << vchar0;
+
+    if (vidx(char, u1, 0) != ((uchar)1  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 1) != ((uchar)2  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 2) != ((uchar)3  << (char)1))
+        __builtin_abort ();
+    if (vidx(char, u1, 3) != ((uchar)4  << (char)1))
+        __builtin_abort ();
+
+    
+    i2 = vchar1 >> vuchar;
+
+    if (vidx(char, i2, 0) != ((char)-1  >> (uchar)1))
+        __builtin_abort ();
+    if (vidx(char, i2, 1) != ((char)-1  >> (uchar)2))
+        __builtin_abort ();
+    if (vidx(char, i2, 2) != ((char)-1  >> (uchar)3))
+        __builtin_abort ();
+    if (vidx(char, i2, 3) != ((char)-1  >> (uchar)4))
+        __builtin_abort ();
+    
+    vchar1 >>= vuchar;
+    vuchar <<= vchar0;
+    vuchar <<= vchar1;
+
+    return 0;
+}
+
Index: gcc/testsuite/gcc.dg/vector-shift3.c
===================================================================
--- gcc/testsuite/gcc.dg/vector-shift3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/vector-shift3.c	(revision 0)
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+
+#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};
+    short sc;
+
+    
+    scalar1 <<= v0; /* { dg-error ".*scalar1.*undeclared" } */
+   
+    return 0;
+}
+
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 165913)
+++ gcc/c-typeck.c	(working copy)
@@ -9565,6 +9565,30 @@ build_binary_op (location_t location, en
 
   objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
 
+  /* For 'vector <shift> scalar' or 'scalar <shift> vector', we convert 
+     a scalar to a vector. Truncating the shift amount is ok.  */
+  if ((code0 == VECTOR_TYPE || code1 == VECTOR_TYPE)
+      && (code0 != code1))
+    {
+      switch (code)
+        {
+          case RSHIFT_EXPR:
+          case LSHIFT_EXPR:
+            if (code0 == INTEGER_TYPE)
+              {
+                tree sc = save_expr (op0);
+                sc = convert (TREE_TYPE (type1), sc);
+                op0 = build_vector_from_val (type1, sc);
+                orig_type0 = type0 = TREE_TYPE (op0);
+                code0 = TREE_CODE (type0);
+              }
+            break;
+
+          default:
+            break;
+        }
+    }
+
   switch (code)
     {
     case PLUS_EXPR:
@@ -9727,7 +9751,21 @@ build_binary_op (location_t location, en
 	 Also set SHORT_SHIFT if shifting rightward.  */
 
     case RSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9754,9 +9792,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
@@ -9764,7 +9803,21 @@ build_binary_op (location_t location, en
       break;
 
     case LSHIFT_EXPR:
-      if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
+          && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
+	{
+	  result_type = type0;
+	  converted = 1;
+	}
+      else if ((code0 == INTEGER_TYPE || code0 == FIXED_POINT_TYPE)
 	  && code1 == INTEGER_TYPE)
 	{
 	  if (TREE_CODE (op1) == INTEGER_CST)
@@ -9786,9 +9839,10 @@ build_binary_op (location_t location, en
 
 	  /* Use the type of the value to be shifted.  */
 	  result_type = type0;
-	  /* Convert the shift-count to an integer, regardless of size
-	     of value being shifted.  */
-	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
+	  /* Convert the non vector shift-count to an integer, regardless
+	     of size of value being shifted.  */
+	  if (TREE_CODE (TREE_TYPE (op1)) != VECTOR_TYPE
+	      && TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = convert (integer_type_node, op1);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;

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

end of thread, other threads:[~2010-10-29 23:08 UTC | newest]

Thread overview: 35+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-06-15 16:02 Vector shifting patch Artem Shinkarov
2010-06-15 17:03 ` Andrew Pinski
2010-06-16 11:41   ` Richard Guenther
2010-06-18 14:04     ` Artem Shinkarov
2010-06-18 21:45       ` Andrew Pinski
2010-06-21 11:08         ` Artem Shinkarov
2010-10-25 17:04           ` Artem Shinkarov
2010-10-25 18:36             ` Nathan Froyd
2010-10-25 19:16               ` Artem Shinkarov
2010-10-25 19:41                 ` Artem Shinkarov
2010-10-25 21:13                 ` Nathan Froyd
2010-10-25 20:16                   ` Artem Shinkarov
2010-10-25 20:33                     ` Nathan Froyd
2010-10-26 10:45                       ` Artem Shinkarov
2010-10-26  1:16                         ` Joseph S. Myers
2010-10-26 13:11                           ` Artem Shinkarov
2010-10-26 17:45                         ` Joseph S. Myers
2010-10-27 13:50                           ` Artem Shinkarov
2010-10-27 14:17                             ` Joseph S. Myers
2010-10-27 16:16                               ` Artem Shinkarov
2010-10-27 18:30                                 ` Joseph S. Myers
2010-10-27 18:41                                   ` Artem Shinkarov
2010-10-28  5:53                                     ` Joseph S. Myers
2010-10-28 13:00                                       ` Artem Shinkarov
2010-10-29 15:50                                         ` Richard Guenther
2010-10-29 18:06                                     ` H.J. Lu
2010-10-27 14:16                         ` Nathan Froyd
2010-10-26 13:13 Artem Shinkarov
2010-10-29 17:42 Dominique Dhumieres
2010-10-29 18:12 ` Artem Shinkarov
2010-10-29 18:14   ` Andrew Pinski
2010-10-29 18:41     ` Artem Shinkarov
2010-10-29 18:27   ` Dominique Dhumieres
2010-10-29 19:03   ` H.J. Lu
2010-10-30  7:45     ` Richard Guenther

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