This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Vector indexing patch
- From: Artem Shinkarov <artyom dot shinkaroff at gmail dot com>
- To: gcc-patches at gcc dot gnu dot org, gcc at gcc dot gnu dot org
- Cc: Richard Guenther <richard dot guenther at gmail dot com>
- Date: Tue, 1 Jun 2010 20:21:44 +0100
- Subject: Vector indexing patch
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 *);