From patchwork Wed Oct 27 17:43:06 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Artem Shinkarov X-Patchwork-Id: 69382 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 B7CCBB70D6 for ; Thu, 28 Oct 2010 04:43:43 +1100 (EST) Received: (qmail 24035 invoked by alias); 27 Oct 2010 17:43:40 -0000 Received: (qmail 24022 invoked by uid 22791); 27 Oct 2010 17:43:35 -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, RCVD_IN_DNSWL_NONE, TW_VF X-Spam-Check-By: sourceware.org Received: from mail-qy0-f182.google.com (HELO mail-qy0-f182.google.com) (209.85.216.182) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 27 Oct 2010 17:43:28 +0000 Received: by qyk33 with SMTP id 33so1038385qyk.20 for ; Wed, 27 Oct 2010 10:43:26 -0700 (PDT) Received: by 10.229.238.193 with SMTP id kt1mr739727qcb.292.1288201406458; Wed, 27 Oct 2010 10:43:26 -0700 (PDT) MIME-Version: 1.0 Received: by 10.229.182.207 with HTTP; Wed, 27 Oct 2010 10:43:06 -0700 (PDT) In-Reply-To: References: <20101025144714.GZ2806@nightcrawler> <20101025150704.GC2806@nightcrawler> <20101025152737.GD2806@nightcrawler> From: Artem Shinkarov Date: Wed, 27 Oct 2010 18:43:06 +0100 Message-ID: Subject: Re: Vector shifting patch To: "Joseph S. Myers" Cc: Nathan Froyd , gcc-patches@gcc.gnu.org, Richard Guenther 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 Ok, then here are vector shifts only. ChangeLog: 2010-10-25 Artjoms Sinkarovs Andrew Pinski gcc/ * 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. gcc/testsuite/ * gcc.c-torture/execute/vector-shift.c: Likewise. * gcc.c-torture/execute/vector-shift1.c: New testcase. * gcc.c-torture/execute/vector-shift2.c: New testcase. * gcc.dg/vector-shift.c: New testcase. * gcc.dg/vector-shift1.c: New testcase. * gcc.dg/vector-shift2.c: New testcase. * gcc.dg/vector-shift3.c: New testcase. bootstrapped and tested on x86_64_unknown-linux Artem. On Wed, Oct 27, 2010 at 5:50 PM, Joseph S. Myers wrote: > On Wed, 27 Oct 2010, Artem Shinkarov wrote: > >> Ok, I do understand your concern, but my following patch >> (http://gcc.gnu.org/ml/gcc-patches/2010-08/msg01075.html) implements >> scalar vector and vector scalar for op in {+, -, /, ...}. In >> that patch for integer types I use the function int_fits_type_p before >> I allow scalar to vector conversion. And it would be strange to allow >> scalar vector everywhere except shifting operators. >> >> Would it be ok, if I'll use the same int_fits_type_p checking if scalr >> fits in the vector type and if not then I'll throw an error. And I'll >> add this statement in the documentation. > > That seems safer - but if other operations between scalars and vectors > aren't supported until a subsequent patch, that clearly indicates that you > should not be including mixed scalar/vector shifts in this patch - you > should make this patch only accept vector/vector shifts.  Mixed shifts can > then go in the patch adding other mixed operations, and be reviewed in the > context of the full documentation and set of testcases for that patch. > > -- > Joseph S. Myers > joseph@codesourcery.com > Index: gcc/doc/extend.texi =================================================================== --- gcc/doc/extend.texi (revision 165913) +++ gcc/doc/extend.texi (working copy) @@ -6315,6 +6315,25 @@ minus or complement operators on a vecto elements are the negative or complemented values of the corresponding elements in the operand. +In C it is possible to use shifting operators @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: gcc/tree.c =================================================================== --- gcc/tree.c (revision 165913) +++ gcc/tree.c (working copy) @@ -1366,6 +1366,28 @@ 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 (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: gcc/tree.h =================================================================== --- gcc/tree.h (revision 165913) +++ gcc/tree.h (working copy) @@ -4034,6 +4034,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 (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); 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,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; +} 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 = v0 >> 1; + + r3 = v0 << v1; + r4 = v0 >> v1; + + 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,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; +} + 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-shift3.c =================================================================== --- gcc/testsuite/gcc.dg/vector-shift3.c (revision 0) +++ gcc/testsuite/gcc.dg/vector-shift3.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(8, short) v0 = {argc,2,3,4,5,6,7}; + short sc; + + + scalar1 <<= v0; /* { dg-error ".*scalar1.*undeclared" } */ + + return 0; +} + Index: gcc/c-typeck.c =================================================================== --- gcc/c-typeck.c (revision 165913) +++ gcc/c-typeck.c (working copy) @@ -9727,7 +9727,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) @@ -9754,9 +9768,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; @@ -9764,7 +9779,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) @@ -9786,9 +9815,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;