tree.h (build_vector_from_val): Declare.

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
This commit is contained in:
Artjoms Sinkarovs 2010-10-29 14:59:07 +00:00 committed by Richard Biener
parent a01c666cc6
commit f87bd04b07
14 changed files with 333 additions and 10 deletions

View 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,

View 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;

View 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

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

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View 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;

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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;
}

View 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

View 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);