This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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 *);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]