From patchwork Fri Jun 18 12:32:57 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Artem Shinkarov X-Patchwork-Id: 56177 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 26AC81007D4 for ; Fri, 18 Jun 2010 22:34:10 +1000 (EST) Received: (qmail 19379 invoked by alias); 18 Jun 2010 12:33:43 -0000 Received: (qmail 19329 invoked by uid 22791); 18 Jun 2010 12:33:31 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, TW_BJ, TW_VF X-Spam-Check-By: sourceware.org Received: from mail-fx0-f47.google.com (HELO mail-fx0-f47.google.com) (209.85.161.47) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 18 Jun 2010 12:33:21 +0000 Received: by fxm18 with SMTP id 18so689013fxm.20 for ; Fri, 18 Jun 2010 05:33:17 -0700 (PDT) Received: by 10.204.141.28 with SMTP id k28mr743128bku.207.1276864397107; Fri, 18 Jun 2010 05:33:17 -0700 (PDT) MIME-Version: 1.0 Received: by 10.204.62.78 with HTTP; Fri, 18 Jun 2010 05:32:57 -0700 (PDT) In-Reply-To: References: From: Artem Shinkarov Date: Fri, 18 Jun 2010 13:32:57 +0100 Message-ID: Subject: Re: Vector shifting patch To: Richard Guenther Cc: Andrew Pinski , gcc-patches@gcc.gnu.org X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Thank you everyone for comments. Here is a new version of the patch which considers all the comments. 2010-06-18 Artem Shinkarov Andrew Pinski * 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? 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 scalar' or 'scalar 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