===================================================================
@@ -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;
+}
+
===================================================================
@@ -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;
+}
+
===================================================================
@@ -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;
+}
+
===================================================================
@@ -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;
+}
+
===================================================================
@@ -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;
+}
+
+
+
===================================================================
@@ -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;
+}
+
===================================================================
@@ -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;
+}
+
+
===================================================================
@@ -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);
+
+}
===================================================================
@@ -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;
===================================================================
@@ -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);
===================================================================
@@ -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
===================================================================
@@ -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