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:
parent
a01c666cc6
commit
f87bd04b07
14 changed files with 333 additions and 10 deletions
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
48
gcc/testsuite/gcc.c-torture/execute/vector-shift.c
Normal file
48
gcc/testsuite/gcc.c-torture/execute/vector-shift.c
Normal 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;
|
||||
}
|
17
gcc/testsuite/gcc.c-torture/execute/vector-shift1.c
Normal file
17
gcc/testsuite/gcc.c-torture/execute/vector-shift1.c
Normal 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;
|
||||
}
|
||||
|
59
gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
Normal file
59
gcc/testsuite/gcc.c-torture/execute/vector-shift2.c
Normal 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;
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
60
gcc/testsuite/gcc.dg/torture/vector-shift2.c
Normal file
60
gcc/testsuite/gcc.dg/torture/vector-shift2.c
Normal 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;
|
||||
}
|
||||
|
14
gcc/testsuite/gcc.dg/vector-shift.c
Normal file
14
gcc/testsuite/gcc.dg/vector-shift.c
Normal 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;
|
||||
}
|
||||
|
18
gcc/testsuite/gcc.dg/vector-shift1.c
Normal file
18
gcc/testsuite/gcc.dg/vector-shift1.c
Normal 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;
|
||||
}
|
||||
|
16
gcc/testsuite/gcc.dg/vector-shift3.c
Normal file
16
gcc/testsuite/gcc.dg/vector-shift3.c
Normal 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;
|
||||
}
|
||||
|
22
gcc/tree.c
22
gcc/tree.c
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue