This is a reworked patch of Andrew Pinski "Subscripting on vector types" in terms of GSoC 2010 [Artjoms Sinkarovs].
This patch allows to index individual elements of vector type in C. For example: vec[i], where vec is a vector with a base type T and i is an integer type. If i is a constant then we construct a BIT_FIELD_REF node considering boundchecking, otherwise we expand it to (((T *)&(vec))[i]). If the vector type variable has a register storage class then it can be accessed only via constant index. Changelog: gcc/c-common.h: helper function c_build_vector_indexed_by_cst added gcc/c-common.c: helper function c_build_vector_indexed_by_cst added gcc/c-typeck.c: build_array_ref modified to handle vector indexing, lvalue_p modified for considering vector element as lvalue. gcc/testsuite/gcc.c-torture/execute/vector-subscript-1.c: test taken from A.Pinski patch gcc/testsuite/gcc.c-torture/execute/vector-subscript-2.c: test taken from A.Pinski patch gcc/testsuite/gcc.dg/vector-subscript-3.c: new test gcc/testsuite/gcc.dg/array-8.c: Update error message about subscripting gcc/testsuite/gcc.dg/vector-subscript-1.c: test taken from A.Pinski patch gcc/testsuite/gcc.dg/vector-subscript-2.c: test taken from A.Pinski patch Teseted on x86_64-unknown-linux-gnu. The documentation was not changed. May be there could be some more ideas to implement. The patch can be found in attachment. _______________________ C++ related question _______________________ Question about C++ frontend people. I would like to implement the same functionality in C++ frontend and typechecker as well. However the problem is that at the moment I have the same code in typechecker and in the decl2.c file (part of frontend). The code looks like this: Index: gcc/cp/typeck.c =================================================================== --- gcc/cp/typeck.c (revision 159699) +++ gcc/cp/typeck.c (working copy) @@ -2912,7 +2912,30 @@ default: break; } + + /* For vector[index], convert the vector to a pointer of the underlying + type. */ + if (TREE_CODE (TREE_TYPE (array)) == VECTOR_TYPE) + { + tree type = TREE_TYPE (array); + tree type1; + + if (TREE_CODE (idx) == INTEGER_CST) + c_build_vector_indexed_by_cst (loc, array, idx); + else + { + /* Mark the vector as addressable but ignore the + register storage class. */ + cxx_mark_addressable (array); + type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type)); + type = build_pointer_type (type); + type1 = build_pointer_type (TREE_TYPE (array)); + array = build1 (ADDR_EXPR, type1, array); + array = convert (type, array); + } + } + if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) { tree rval, type; Index: gcc/cp/decl2.c =================================================================== --- gcc/cp/decl2.c (revision 159699) +++ gcc/cp/decl2.c (working copy) @@ -365,7 +365,30 @@ else { tree p1, p2, i1, i2; + /* For vector[index], convert the vector to a pointer of the underlying + type. */ + if (TREE_CODE (type) == VECTOR_TYPE) + { + tree type = TREE_TYPE (array_expr); + tree type1; + /* If constant index is in bound of vector type */ + if (TREE_CODE (index_exp) == INTEGER_CST) + c_build_vector_indexed_by_cst (input_location, array_expr, + index_exp); + else + { + /* Mark the vector as addressable but ignore the + register storage class. */ + cxx_mark_addressable (array_expr); + type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type)); + type = build_pointer_type (type); + type1 = build_pointer_type (TREE_TYPE (array_expr)); + array_expr = build1 (ADDR_EXPR, type1, array_expr); + array_expr = convert (type, array_expr); + } + } + /* Otherwise, create an ARRAY_REF for a pointer or array type. It is a little-known fact that, if `a' is an array and `i' is My question is whether I can be sure that the tree that I'll have in typeck.c will be passed through the decl2.c? In that case I will be able to avoid code doubling in typeck.c just skipping this check. Because I can be sure that the code will be checked in decl2.c. Can anyone give me a quick description of the C++ front end. Or point me to the right document. -- Thank you, Artem Shinkarov
Index: gcc/testsuite/gcc.c-torture/execute/vector-subscript-2.c =================================================================== --- gcc/testsuite/gcc.c-torture/execute/vector-subscript-2.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/vector-subscript-2.c (revision 0) @@ -0,0 +1,66 @@ +#define vector __attribute__((vector_size(sizeof(int)*4) )) + +/* Check to make sure that we extract and insert the vector at the same + location for vector subscripting (with constant indexes) and + that vectors layout are the same as arrays. */ + +struct TV4 +{ + vector int v; +}; + +typedef struct TV4 MYV4; + +static inline MYV4 myfunc2( int x, int y, int z, int w ) +{ + MYV4 temp; + temp.v[0] = x; + temp.v[1] = y; + temp.v[2] = z; + temp.v[3] = w; + return temp; +} +MYV4 val3; +__attribute__((noinline)) void modify (void) +{ + val3 = myfunc2( 1, 2, 3, 4 ); +} +int main( int argc, char* argv[] ) +{ + int a[4]; + int i; + + /* Set up the vector. */ + modify(); + + /* Check the vector via the global variable. */ + if (val3.v[0] != 1) + __builtin_abort (); + if (val3.v[1] != 2) + __builtin_abort (); + if (val3.v[2] != 3) + __builtin_abort (); + if (val3.v[3] != 4) + __builtin_abort (); + + vector int a1 = val3.v; + + /* Check the vector via a local variable. */ + if (a1[0] != 1) + __builtin_abort (); + if (a1[1] != 2) + __builtin_abort (); + if (a1[2] != 3) + __builtin_abort (); + if (a1[3] != 4) + __builtin_abort (); + + __builtin_memcpy(a, &val3, sizeof(a)); + /* Check the vector via copying it to an array. */ + for(i = 0; i < 4; i++) + if (a[i] != i+1) + __builtin_abort (); + + + return 0; +} Index: gcc/testsuite/gcc.c-torture/execute/vector-subscript-1.c =================================================================== --- gcc/testsuite/gcc.c-torture/execute/vector-subscript-1.c (revision 0) +++ gcc/testsuite/gcc.c-torture/execute/vector-subscript-1.c (revision 0) @@ -0,0 +1,58 @@ +#define vector __attribute__((vector_size(sizeof(int)*4) )) + +/* Check to make sure that we extract and insert the vector at the same + location for vector subscripting and that vectors layout are the same + as arrays. */ + +struct TV4 +{ + vector int v; +}; + +typedef struct TV4 MYV4; +static inline int *f(MYV4 *a, int i) +{ + return &(a->v[i]); +} + +static inline MYV4 myfunc2( int x, int y, int z, int w ) +{ + MYV4 temp; + *f(&temp, 0 ) = x; + *f(&temp, 1 ) = y; + *f(&temp, 2 ) = z; + *f(&temp, 3 ) = w; + return temp; +} + +MYV4 val3; + +__attribute__((noinline)) void modify (void) +{ + val3 = myfunc2( 1, 2, 3, 4 ); +} + +int main( int argc, char* argv[] ) +{ + int a[4]; + int i; + + modify(); + + if (*f(&val3, 0 ) != 1) + __builtin_abort (); + if (*f(&val3, 1 ) != 2) + __builtin_abort (); + if (*f(&val3, 2 ) != 3) + __builtin_abort (); + if (*f(&val3, 3 ) != 4) + __builtin_abort (); + + __builtin_memcpy(a, &val3, 16); + for(i = 0; i < 4; i++) + if (a[i] != i+1) + __builtin_abort (); + + + return 0; +} Index: gcc/testsuite/gcc.dg/vector-subscript-3.c =================================================================== --- gcc/testsuite/gcc.dg/vector-subscript-3.c (revision 0) +++ gcc/testsuite/gcc.dg/vector-subscript-3.c (revision 0) @@ -0,0 +1,18 @@ +/* Check the case when index is out of bound */ +/* { dg-do compile } */ + +#define vector __attribute__((vector_size(16) )) + + +int test0(void) +{ + vector int a; + return a[10]; /* { dg-error "index value is out of bound" } */ +} + +int test1(void) +{ + vector int a; + return a[-1]; /* { dg-error "index value is out of bound" } */ +} + Index: gcc/testsuite/gcc.dg/array-8.c =================================================================== --- gcc/testsuite/gcc.dg/array-8.c (revision 159699) +++ gcc/testsuite/gcc.dg/array-8.c (working copy) @@ -35,7 +35,7 @@ f().c[0]; 0[f().c]; /* Various invalid cases. */ - c[c]; /* { dg-error "subscripted value is neither array nor pointer" } */ + c[c]; /* { dg-error "subscripted value is neither array nor pointer nor vector" } */ p[1.0]; /* { dg-error "array subscript is not an integer" } */ 1.0[a]; /* { dg-error "array subscript is not an integer" } */ fp[0]; /* { dg-error "subscripted value is pointer to function" } */ Index: gcc/testsuite/gcc.dg/vector-subscript-1.c =================================================================== --- gcc/testsuite/gcc.dg/vector-subscript-1.c (revision 0) +++ gcc/testsuite/gcc.dg/vector-subscript-1.c (revision 0) @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-w" } */ + +#define vector __attribute__((vector_size(16) )) +/* Check that vector[index] works and index[vector] is rejected. */ + +float vf(vector float a) +{ + return 0[a]; /* { dg-error "" } */ +} + + +float fv(vector float a) +{ + return a[0]; +} Index: gcc/testsuite/gcc.dg/vector-subscript-2.c =================================================================== --- gcc/testsuite/gcc.dg/vector-subscript-2.c (revision 0) +++ gcc/testsuite/gcc.dg/vector-subscript-2.c (revision 0) @@ -0,0 +1,13 @@ +/* { dg-do compile } */ + +/* Check that subscripting of vectors work with register storage class decls. */ + +#define vector __attribute__((vector_size(16) )) + + +float vf(int i) +{ + register vector float a; + return a[0]; +} + Index: gcc/c-typeck.c =================================================================== --- gcc/c-typeck.c (revision 159699) +++ gcc/c-typeck.c (working copy) @@ -2230,6 +2230,9 @@ arrays that are not lvalues (for example, members of structures returned by functions). + For vector types, allow vector[i] but not i[vector], and create + *(((type*)&vectortype) + i) for the expression. + LOC is the location to use for the returned expression. */ tree @@ -2242,13 +2245,17 @@ return error_mark_node; if (TREE_CODE (TREE_TYPE (array)) != ARRAY_TYPE - && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE) + && TREE_CODE (TREE_TYPE (array)) != POINTER_TYPE + /* Allow vector[index] but not index[vector]. */ + && TREE_CODE (TREE_TYPE (array)) != VECTOR_TYPE) { tree temp; if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE && TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE) { - error_at (loc, "subscripted value is neither array nor pointer"); + error_at (loc, + "subscripted value is neither array nor pointer nor vector"); + return error_mark_node; } temp = array; @@ -2278,7 +2285,29 @@ index = default_conversion (index); gcc_assert (TREE_CODE (TREE_TYPE (index)) == INTEGER_TYPE); + + /* For vector[index], convert the vector to a + pointer of the underlying type. */ + if (TREE_CODE (TREE_TYPE (array)) == VECTOR_TYPE) + { + tree type = TREE_TYPE (array); + tree type1; + if (TREE_CODE (index) == INTEGER_CST) + return c_build_vector_indexed_by_cst (loc, array, index); + else + { + /* Mark the vector as addressable but ignore the + register storage class. */ + c_mark_addressable (array); + type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type)); + type = build_pointer_type (type); + type1 = build_pointer_type (TREE_TYPE (array)); + array = build1 (ADDR_EXPR, type1, array); + array = convert (type, array); + } + } + if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE) { tree rval, type; @@ -3769,6 +3798,9 @@ case STRING_CST: return 1; + case BIT_FIELD_REF: + return (TREE_CODE (TREE_TYPE (TREE_OPERAND (ref,0))) == VECTOR_TYPE); + case INDIRECT_REF: case ARRAY_REF: case VAR_DECL: Index: gcc/c-common.c =================================================================== --- gcc/c-common.c (revision 159699) +++ gcc/c-common.c (working copy) @@ -3277,6 +3277,36 @@ return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp); } +/* Build a BIT_FIELD_REF node when vecor is indexed by a constant index. */ + +tree +c_build_vector_indexed_by_cst (location_t loc, tree vect, tree index) +{ + unsigned HOST_WIDE_INT idx; + unsigned HOST_WIDE_INT el_size; + tree type, size, pos; + + gcc_assert (TREE_CODE (index) == INTEGER_CST); + + /* Check if the constant index INDEX is in bound of the vector VECT. */ + if (!host_integerp (index, 1) + || tree_low_cst (index, 1) >= TYPE_VECTOR_SUBPARTS (TREE_TYPE (vect))) + { + error_at (loc, "index value is out of bound"); + return error_mark_node; + } + + type = TREE_TYPE (vect); + + /* Constructing a BIT_FIELD_REF node. */ + size = TYPE_SIZE (TREE_TYPE (TREE_TYPE (vect))); + idx = tree_low_cst (index, 1); + el_size = tree_low_cst (size, 1); + pos = size_int (idx * el_size); + type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type)); + return build3 (BIT_FIELD_REF, type, vect, size, pos); +} + /* Build a bit-field integer type for the given WIDTH and UNSIGNEDP. */ tree Index: gcc/c-common.h =================================================================== --- gcc/c-common.h (revision 159699) +++ gcc/c-common.h (working copy) @@ -832,6 +832,7 @@ extern tree c_common_unsigned_type (tree); extern tree c_common_signed_type (tree); extern tree c_common_signed_or_unsigned_type (int, tree); +extern tree c_build_vector_indexed_by_cst (location_t, tree, tree); extern tree c_build_bitfield_integer_type (unsigned HOST_WIDE_INT, int); extern bool decl_with_nonnull_addr_p (const_tree); extern tree c_fully_fold (tree, bool, bool *);