]> gcc.gnu.org Git - gcc.git/commitdiff
tree.h (build_vector_from_val): Declare.
authorArtjoms Sinkarovs <artyom.shinkaroff@gmail.com>
Fri, 29 Oct 2010 14:59:07 +0000 (14:59 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 29 Oct 2010 14:59:07 +0000 (14:59 +0000)
2010-10-29  Artjoms Sinkarovs <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.
* doc/extend.texi: Description of the vector shifting operation.

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

Co-Authored-By: Andrew Pinski <pinskia@gmail.com>
From-SVN: r166061

14 files changed:
gcc/ChangeLog
gcc/c-typeck.c
gcc/doc/extend.texi
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/vector-shift.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/vector-shift1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/vector-shift2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/simd-1b.c
gcc/testsuite/gcc.dg/torture/vector-shift2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vector-shift.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vector-shift1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/vector-shift3.c [new file with mode: 0644]
gcc/tree.c
gcc/tree.h

index 68af1080d13dfa5ac9f6d761754c77223fc0fd42..89bc104e227fd7584345299b805bf6d43342141d 100644 (file)
@@ -1,3 +1,11 @@
+2010-10-29  Artjoms Sinkarovs <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.
+       * doc/extend.texi: Description of the vector shifting operation.
+
 2010-10-29  Paul Koning  <pkoning@equallogic.com>
 
        * config/pdp11/pdp11-protos.h (pdp11_cannot_change_mode_class,
index 1476b6d4ffc6d970c7a99a27eb49d8aa69fe22c6..70d9be7a53d22b5e20c16b99ae35958af34020b2 100644 (file)
@@ -9727,7 +9727,21 @@ build_binary_op (location_t location, enum tree_code code,
         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, enum tree_code code,
 
          /* 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, enum tree_code code,
       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, enum tree_code code,
 
          /* 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 c37e4b38489b3777492910d38bf5a5f627137338..de2be889bdc94b518d6cdee11b59ef6e8a7a8297 100644 (file)
@@ -6315,6 +6315,24 @@ minus or complement operators on a vector type is a vector whose
 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 029f70ef0301d18a74f78b93da4d51ae3ef1aa81..7000b10520c200cc15f00d667aa7bde3fd7662b4 100644 (file)
@@ -1,3 +1,15 @@
+2010-10-29  Artjoms Sinkarovs <artyom.shinakroff@gmail.com>
+       Andrew Pinski <pinskia@gmail.com>
+
+       * gcc.c-torture/execute/vector-shift.c: New testcase.
+       * gcc.c-torture/execute/vector-shift1.c: Likewise.
+       * gcc.c-torture/execute/vector-shift2.c: Likewise.
+       * gcc.dg/vector-shift.c: Likewise.
+       * gcc.dg/vector-shift1.c: Likewise.
+       * gcc.dg/torture/vector-shift2.c: Likewise.
+       * gcc.dg/vector-shift3.c: Likewise.
+       * gcc.dg/simd-1b.c: Adjust.
+
 2010-10-29  Kaz Kojima  <kkojima@gcc.gnu.org>
 
        * gcc.c-torture/execute/20101011-1.c: Skip on SH.
diff --git a/gcc/testsuite/gcc.c-torture/execute/vector-shift.c b/gcc/testsuite/gcc.c-torture/execute/vector-shift.c
new file mode 100644 (file)
index 0000000..f52eb58
--- /dev/null
@@ -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;  
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/vector-shift1.c b/gcc/testsuite/gcc.c-torture/execute/vector-shift1.c
new file mode 100644 (file)
index 0000000..6041fc3
--- /dev/null
@@ -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;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/execute/vector-shift2.c b/gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
new file mode 100644 (file)
index 0000000..55f1035
--- /dev/null
@@ -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 1e2b597b56518fce85a5cc3d6a81f65a490ec990..44c39c2ef96f3c920ab30d80ba32f7ef13f4926b 100644 (file)
@@ -18,8 +18,8 @@ hanneke ()
   c &= d;
   a |= b;
   c ^= d;
-  a >>= b; /* { dg-error "invalid operands to binary >>" } */
-  c <<= d; /* { dg-error "invalid operands to binary <<" } */
+  a >>= b;
+  c <<= d;
   a = +b;
   c = ~d;
 
diff --git a/gcc/testsuite/gcc.dg/torture/vector-shift2.c b/gcc/testsuite/gcc.dg/torture/vector-shift2.c
new file mode 100644 (file)
index 0000000..a4ca924
--- /dev/null
@@ -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 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;
+}
+
diff --git a/gcc/testsuite/gcc.dg/vector-shift.c b/gcc/testsuite/gcc.dg/vector-shift.c
new file mode 100644 (file)
index 0000000..f2b12ba
--- /dev/null
@@ -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;
+}
+
diff --git a/gcc/testsuite/gcc.dg/vector-shift1.c b/gcc/testsuite/gcc.dg/vector-shift1.c
new file mode 100644 (file)
index 0000000..51bc0ad
--- /dev/null
@@ -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;
+}
+
diff --git a/gcc/testsuite/gcc.dg/vector-shift3.c b/gcc/testsuite/gcc.dg/vector-shift3.c
new file mode 100644 (file)
index 0000000..38a9843
--- /dev/null
@@ -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 48279ebc18176c5a7b995fbe12dc8c7cfcd49dcd..4eb13c124c1c8b804168e9912fa5e6f795fde9ba 100644 (file)
@@ -1366,6 +1366,28 @@ build_vector_from_ctor (tree type, VEC(constructor_elt,gc) *v)
   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 968a1bc92ac4341eb904978550357a3a905870f6..f0b1e7420942bf0c1fb6e33e7e562bfdcd3d7032 100644 (file)
@@ -4037,6 +4037,7 @@ extern tree build_int_cst_type (tree, HOST_WIDE_INT);
 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);
This page took 0.19492 seconds and 5 git commands to generate.