Patchwork Vector subscription patch

login
register
mail settings
Submitter Artem Shinkarov
Date June 11, 2010, 2:56 p.m.
Message ID <AANLkTikK9fgU6pHB6Y1KeEvhaYo96GYrfttz-GnlwmY8@mail.gmail.com>
Download mbox | patch
Permalink /patch/55334/
State New
Headers show

Comments

Artem Shinkarov - June 11, 2010, 2:56 p.m.
This is a reworked version of Andrew Pinski's vector subscription
patch. The work done in terms of GSoC 2010 project.

Improvements:
The C and C++ parts now separated, the current patch is a C part.
The commonly used function is moved to c-common.c.
Bound-checking is enabled when -Warray-bounds are on.

The patch was approved by C maintainers, but the code was never
commited because of unapproved C++ parts.

ChangeLog:

2010-06-10  Artem Shinkarov <artyom.shinakroff@gmail.com>
      Andrew Pinski <pinskia@gmail.com>

      * c-family/c-common.h (c_common_mark_addressable_vec): Declare.
      * c-family/c-common.c (c_common_mark_addressable_vec): New function.
      * c-typeck.c (build_array_ref): Handle subscripting of vectors.

      testsuite/
      * gcc.c-torture/execute/vector-subscript-1.c: Likewise.
      * gcc.c-torture/execute/vector-subscript-2.c: Likewise.
      * gcc.c-torture/execute/vector-subscript-3.c: New testcase.
      * gcc.c-torture/execute/vector-subscript-4.c: New testcase.
      * gcc.dg/vector-subscript-1.c: Likewise.
      * gcc.dg/vector-subscript-2.c: Likewise.
      * gcc.dg/array-8.c: Adjust.

      doc/
      * extend.texi: New paragraph


bootstrapped and tested on x86_64_unknown-linux
Paolo Bonzini - June 11, 2010, 4:10 p.m.
On 06/11/2010 04:56 PM, Artem Shinkarov wrote:
> This is a reworked version of Andrew Pinski's vector subscription
> patch. The work done in terms of GSoC 2010 project.
>
> Improvements:
> The C and C++ parts now separated, the current patch is a C part.
> The commonly used function is moved to c-common.c.
> Bound-checking is enabled when -Warray-bounds are on.

Yay, that would simplify _a lot_ my SIMD bitmap patch.

PaolO

Patch

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 160551)
+++ gcc/doc/extend.texi	(working copy)
@@ -6141,6 +6141,11 @@ 
 elements are the negative or complemented values of the corresponding
 elements in the operand.
 
+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 accesses for vector subscription can be
+enabled with @option{-Warray-bounds}.
+
 You can declare variables and use them in function calls and returns, as
 well as in assignments and some casts.  You can specify a vector type as
 a return type for a function.  Vector types can also be used as function
Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 160551)
+++ gcc/c-family/c-common.c	(working copy)
@@ -8577,6 +8577,18 @@ 
   return failure;
 }
 
+/* Like c_mark_addressable but don't check register qualifier.  */
+void 
+c_common_mark_addressable_vec (tree t)
+{   
+  while (handled_component_p (t))
+    t = TREE_OPERAND (t, 0);
+  if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
+    return;
+  TREE_ADDRESSABLE (t) = 1;
+}
+
+
 
 /* Used to help initialize the builtin-types.def table.  When a type of
    the correct size doesn't exist, use error_mark_node instead of NULL.
Index: gcc/c-family/c-common.h
===================================================================
--- gcc/c-family/c-common.h	(revision 160551)
+++ gcc/c-family/c-common.h	(working copy)
@@ -877,6 +877,8 @@ 
 
 extern tree builtin_type_for_size (int, bool);
 
+extern void c_common_mark_addressable_vec (tree);
+
 extern void warn_array_subscript_with_type_char (tree);
 extern void warn_about_parentheses (enum tree_code,
 				    enum tree_code, tree,
Index: gcc/testsuite/gcc.c-torture/execute/vector-subscript-3.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-subscript-3.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-subscript-3.c	(revision 0)
@@ -0,0 +1,19 @@ 
+/* Check the case when index is out of bound */
+/* { dg-do compile } */
+/* { dg-options "-Warray-bounds" } */
+
+#define vector __attribute__((vector_size(16) ))
+
+
+int test0(void)
+{
+  vector int a;
+  return a[10]; /* { dg-warning "index value is out of bound" } */
+}
+
+int test1(void)
+{
+  vector int a;
+  return a[-1]; /* { dg-warning "index value is out of bound" } */
+}
+
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,67 @@ 
+#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-4.c
===================================================================
--- gcc/testsuite/gcc.c-torture/execute/vector-subscript-4.c	(revision 0)
+++ gcc/testsuite/gcc.c-torture/execute/vector-subscript-4.c	(revision 0)
@@ -0,0 +1,26 @@ 
+/* dg-do run */
+#define vector __attribute__((vector_size(16) ))
+
+/* Check whether register declaration of vector type still 
+   allow us to subscript this type.  */
+
+typedef vector short myvec_t;
+
+struct vec_s {
+    vector short member;
+};
+
+
+int main () {
+  register short vector v0 = {1,2,3,4,5,6,7};
+  register myvec_t v1 = {1,2,3,4,5,6,7};
+  register struct vec_s v2;
+    
+  v2.member = v1;
+
+  short r = v0[0] + v1[1] + v2.member[2];
+  if (r != 6)
+    __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,60 @@ 
+/* dg-do run */
+#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/array-8.c
===================================================================
--- gcc/testsuite/gcc.dg/array-8.c	(revision 160551)
+++ 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,17 @@ 
+/* { 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 160551)
+++ gcc/c-typeck.c	(working copy)
@@ -2290,6 +2290,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
@@ -2302,13 +2305,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;
@@ -2338,7 +2345,28 @@ 
   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)
+        if (!host_integerp (index, 1) 
+            || ((unsigned HOST_WIDE_INT) tree_low_cst (index, 1) 
+               >= TYPE_VECTOR_SUBPARTS (TREE_TYPE (array))))
+          warning_at (loc, OPT_Warray_bounds, "index value is out of bound");
+     
+      c_common_mark_addressable_vec (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;