diff mbox

Vector subscription patch

Message ID AANLkTinBCvNWt3ymLHvGWVCJ-cPL84wX++bTy+EBVj5M@mail.gmail.com
State New
Headers show

Commit Message

Artem Shinkarov Oct. 20, 2010, 10:35 a.m. UTC
This is a patch which was never reviewed and commited because of my
license issues. Now my copyright assignment is solved.


The patch allows to index vectors the same way as arrays.
Bound-checking is enabled when -Warray-bounds is on.


ChangeLog:

2010-10-20  Artjoms Sinkarovs <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.dg/vector-subscript-1.c: Likewise.
     * gcc.dg/vector-subscript-2.c: Likewise.
     * gcc.dg/vector-subscript-3.c: New testcase.
     * gcc.dg/array-8.c: Adjust.

     doc/
     * extend.texi: New paragraph


bootstrapped and tested on x86_64_unknown-linux


Ok?

Comments

Joseph Myers Oct. 20, 2010, 11:54 a.m. UTC | #1
On Wed, 20 Oct 2010, Artem Shinkarov wrote:

>      * c-family/c-common.h (c_common_mark_addressable_vec): Declare.
>      * c-family/c-common.c (c_common_mark_addressable_vec): New function.

c-family/ has its own ChangeLog file.

> Index: gcc/doc/extend.texi
> ===================================================================
> --- gcc/doc/extend.texi	(revision 165700)
> +++ gcc/doc/extend.texi	(working copy)
> @@ -6310,6 +6310,11 @@ minus or complement operators on a vecto
>  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}.

I don't see any C++ changes in this patch, but I don't see any 
documentation saying this feature is C-only either.  If it's C-only, this 
should be documented.

> +  return 0[a]; /* { dg-error "" } */

'{ dg-error "" }' is generally bad; you should match at least some of the 
message text.
Richard Henderson Oct. 20, 2010, 6:57 p.m. UTC | #2
> +      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);

I think it's a bit unfortunate to be expanding this to memory
access and arithmetic immediately in the front end.

We have vec_extract_optab in the backends that allows extraction
of a single element of a vector, and vec_set_optab that allows
insertion of a single element of a vector.

These patterns are used by store_bit_field and extract_bit_field,
generally in response to BIT_FIELD_REF.  This is probably a better
way to represent the operation.



r~
Richard Biener Oct. 20, 2010, 8:55 p.m. UTC | #3
On Wed, Oct 20, 2010 at 8:57 PM, Richard Henderson <rth@redhat.com> wrote:
>> +      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);
>
> I think it's a bit unfortunate to be expanding this to memory
> access and arithmetic immediately in the front end.
>
> We have vec_extract_optab in the backends that allows extraction
> of a single element of a vector, and vec_set_optab that allows
> insertion of a single element of a vector.
>
> These patterns are used by store_bit_field and extract_bit_field,
> generally in response to BIT_FIELD_REF.  This is probably a better
> way to represent the operation.

But that's only possible for constant indices, but yes I remember having
similar comments initially.

Richard.

>
>
> r~
>
Richard Henderson Oct. 20, 2010, 9:13 p.m. UTC | #4
On 10/20/2010 01:55 PM, Richard Guenther wrote:
>> These patterns are used by store_bit_field and extract_bit_field,
>> generally in response to BIT_FIELD_REF.  This is probably a better
>> way to represent the operation.
> 
> But that's only possible for constant indices, but yes I remember having
> similar comments initially.

Then we should invent a VEC_ELT_REF or something.  In most
cases I expect we'll be able to reduce the argument to a
constant.  If not... well, too bad, we'll dump it to memory.

But doing it right away in the front-end has got to be the
least efficient idea.


r~
Richard Biener Oct. 20, 2010, 9:27 p.m. UTC | #5
On Wed, Oct 20, 2010 at 11:13 PM, Richard Henderson <rth@redhat.com> wrote:
> On 10/20/2010 01:55 PM, Richard Guenther wrote:
>>> These patterns are used by store_bit_field and extract_bit_field,
>>> generally in response to BIT_FIELD_REF.  This is probably a better
>>> way to represent the operation.
>>
>> But that's only possible for constant indices, but yes I remember having
>> similar comments initially.
>
> Then we should invent a VEC_ELT_REF or something.  In most
> cases I expect we'll be able to reduce the argument to a
> constant.  If not... well, too bad, we'll dump it to memory.
>
> But doing it right away in the front-end has got to be the
> least efficient idea.

Sure.

A VIEW_CONVERT_EXPR <ARRAY_TYPE, register>[index] should also work.

Richard.

>
> r~
>
Richard Henderson Oct. 20, 2010, 9:36 p.m. UTC | #6
On 10/20/2010 02:27 PM, Richard Guenther wrote:
> A VIEW_CONVERT_EXPR <ARRAY_TYPE, register>[index] should also work.

That should mark the variable addressable iff index is non-constant?


r~
Richard Biener Oct. 20, 2010, 9:47 p.m. UTC | #7
On Wed, Oct 20, 2010 at 11:36 PM, Richard Henderson <rth@redhat.com> wrote:
> On 10/20/2010 02:27 PM, Richard Guenther wrote:
>> A VIEW_CONVERT_EXPR <ARRAY_TYPE, register>[index] should also work.
>
> That should mark the variable addressable iff index is non-constant?

No, the variable will still be in SSA form, thus the expanders have to take
extra care.  The variable will be non-addressable but in non-SSA form
if there are partial stores though.

Well - all the above is in theory, I think even with Ada we don't end up
with this kind of trees, so it might still explode ;)

Richard.

>
> r~
>
Richard Henderson Oct. 20, 2010, 10:06 p.m. UTC | #8
On 10/20/2010 02:47 PM, Richard Guenther wrote:
> On Wed, Oct 20, 2010 at 11:36 PM, Richard Henderson <rth@redhat.com> wrote:
>> On 10/20/2010 02:27 PM, Richard Guenther wrote:
>>> A VIEW_CONVERT_EXPR <ARRAY_TYPE, register>[index] should also work.
>>
>> That should mark the variable addressable iff index is non-constant?
> 
> No, the variable will still be in SSA form, thus the expanders have to take
> extra care.  The variable will be non-addressable but in non-SSA form
> if there are partial stores though.

Er, of course there will be partial stores.  That's the 
whole point of setting an element.

It's almost certainly better, then, to have a new code

  vector<T> v;
  T t;

  v1 = VEC_SET_EXPR(v0, index, t0);
  t1 = VEC_EXT_EXPR(v0, index)

which can at least keep V in SSA form, and avoid playing
silly games with ARRAY_REF_EXPR.


r~
Richard Biener Oct. 20, 2010, 10:47 p.m. UTC | #9
On Thu, Oct 21, 2010 at 12:06 AM, Richard Henderson <rth@redhat.com> wrote:
> On 10/20/2010 02:47 PM, Richard Guenther wrote:
>> On Wed, Oct 20, 2010 at 11:36 PM, Richard Henderson <rth@redhat.com> wrote:
>>> On 10/20/2010 02:27 PM, Richard Guenther wrote:
>>>> A VIEW_CONVERT_EXPR <ARRAY_TYPE, register>[index] should also work.
>>>
>>> That should mark the variable addressable iff index is non-constant?
>>
>> No, the variable will still be in SSA form, thus the expanders have to take
>> extra care.  The variable will be non-addressable but in non-SSA form
>> if there are partial stores though.
>
> Er, of course there will be partial stores.  That's the
> whole point of setting an element.
>
> It's almost certainly better, then, to have a new code
>
>  vector<T> v;
>  T t;
>
>  v1 = VEC_SET_EXPR(v0, index, t0);
>  t1 = VEC_EXT_EXPR(v0, index)
>
> which can at least keep V in SSA form, and avoid playing
> silly games with ARRAY_REF_EXPR.

;)

We also lack a genuine vector construction tree and use CONSTRUCTOR
for it.  But your VEC_SET_EXPR sounds much like the BIT_FIELD_EXPR
I want to invent for the modify part of a read-modify-write bitfield store.

Anyway, the question is what we want to do now, given we're close to
stage3 and nothing in the middle-end currently knows about a
VEC_SET_EXPR or a VEC_EXT_EXPR.

Doing the addressable memory thing will pessimize -O0 for sure, but
the optimizers should be able to fix it up.  We can easily special-case
constant indices on the RHS with BIT_FIELD_REF.

Richard.

>
> r~
>
Artem Shinkarov Oct. 21, 2010, 11:15 a.m. UTC | #10
Richard is right about the fact that backend setterd and getters are
not used properly. For instance, the code like this:

#define vector(elcount, type)  \
__attribute__((vector_size((elcount)*sizeof(type)))) type

extern vector (8, short) vec;

int main (int argc, char *argv[]) {
    vec += (vector (8, short)) {4,4,4,4,4,4,4,4};
    return vec[0];
}

is compiled down to the assembly:

 main:
 .LFB0:
         .cfi_startproc
         movdqa  .LC0(%rip), %xmm0
         paddw   vec(%rip), %xmm0
         movdqa  %xmm0, -24(%rsp)
         movzwl  -24(%rsp), %eax
         movdqa  %xmm0, vec(%rip)
         cwtl
         ret
         .cfi_endproc

but in theory we could use pextrw instead of assigning through the
memory. Like this:

 main:
 .LFB0:
         .cfi_startproc
         movdqa  .LC0(%rip), %xmm0
         paddw   vec(%rip), %xmm0
         pextrw  $0x0, %xmm0, %eax
         movdqa  %xmm0, vec(%rip)
         cwtl
         ret
         .cfi_endproc

Although in the middleend we have transformation of vec[0] to
BIT_FIELD_REF <vec, 16, 0>;

So the question is why the backend did not recognize this as a pattern
for pextrw. And how much effort would it take to fix this.

As for new codes, I think that it would be nicer to recognize the
pattern in the middle end rather than generate new codes at the very
beginning. For instance if I'll have:

vector (8, short) vec;
short x = *((short *) vec + 3);

then it means that I would not be able to get my pextrw out of this?

Any ideas why backend does not catch this pattern?


Artem.

On Wed, Oct 20, 2010 at 11:47 PM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Thu, Oct 21, 2010 at 12:06 AM, Richard Henderson <rth@redhat.com> wrote:
>> On 10/20/2010 02:47 PM, Richard Guenther wrote:
>>> On Wed, Oct 20, 2010 at 11:36 PM, Richard Henderson <rth@redhat.com> wrote:
>>>> On 10/20/2010 02:27 PM, Richard Guenther wrote:
>>>>> A VIEW_CONVERT_EXPR <ARRAY_TYPE, register>[index] should also work.
>>>>
>>>> That should mark the variable addressable iff index is non-constant?
>>>
>>> No, the variable will still be in SSA form, thus the expanders have to take
>>> extra care.  The variable will be non-addressable but in non-SSA form
>>> if there are partial stores though.
>>
>> Er, of course there will be partial stores.  That's the
>> whole point of setting an element.
>>
>> It's almost certainly better, then, to have a new code
>>
>>  vector<T> v;
>>  T t;
>>
>>  v1 = VEC_SET_EXPR(v0, index, t0);
>>  t1 = VEC_EXT_EXPR(v0, index)
>>
>> which can at least keep V in SSA form, and avoid playing
>> silly games with ARRAY_REF_EXPR.
>
> ;)
>
> We also lack a genuine vector construction tree and use CONSTRUCTOR
> for it.  But your VEC_SET_EXPR sounds much like the BIT_FIELD_EXPR
> I want to invent for the modify part of a read-modify-write bitfield store.
>
> Anyway, the question is what we want to do now, given we're close to
> stage3 and nothing in the middle-end currently knows about a
> VEC_SET_EXPR or a VEC_EXT_EXPR.
>
> Doing the addressable memory thing will pessimize -O0 for sure, but
> the optimizers should be able to fix it up.  We can easily special-case
> constant indices on the RHS with BIT_FIELD_REF.
>
> Richard.
>
>>
>> r~
>>
>
Richard Biener Oct. 21, 2010, 1:36 p.m. UTC | #11
On Thu, Oct 21, 2010 at 1:15 PM, Artem Shinkarov
<artyom.shinkaroff@gmail.com> wrote:
> Richard is right about the fact that backend setterd and getters are
> not used properly. For instance, the code like this:
>
> #define vector(elcount, type)  \
> __attribute__((vector_size((elcount)*sizeof(type)))) type
>
> extern vector (8, short) vec;
>
> int main (int argc, char *argv[]) {
>    vec += (vector (8, short)) {4,4,4,4,4,4,4,4};
>    return vec[0];
> }
>
> is compiled down to the assembly:
>
>  main:
>  .LFB0:
>         .cfi_startproc
>         movdqa  .LC0(%rip), %xmm0
>         paddw   vec(%rip), %xmm0
>         movdqa  %xmm0, -24(%rsp)
>         movzwl  -24(%rsp), %eax
>         movdqa  %xmm0, vec(%rip)
>         cwtl
>         ret
>         .cfi_endproc
>
> but in theory we could use pextrw instead of assigning through the
> memory. Like this:
>
>  main:
>  .LFB0:
>         .cfi_startproc
>         movdqa  .LC0(%rip), %xmm0
>         paddw   vec(%rip), %xmm0
>         pextrw  $0x0, %xmm0, %eax
>         movdqa  %xmm0, vec(%rip)
>         cwtl
>         ret
>         .cfi_endproc
>
> Although in the middleend we have transformation of vec[0] to
> BIT_FIELD_REF <vec, 16, 0>;
>
> So the question is why the backend did not recognize this as a pattern
> for pextrw. And how much effort would it take to fix this.
>
> As for new codes, I think that it would be nicer to recognize the
> pattern in the middle end rather than generate new codes at the very
> beginning. For instance if I'll have:
>
> vector (8, short) vec;
> short x = *((short *) vec + 3);
>
> then it means that I would not be able to get my pextrw out of this?
>
> Any ideas why backend does not catch this pattern?

In this particular case it is because the global variable vec isn't
re-written into SSA form and thus the BIT_FIELD_REF operates
on memory (and we do not CSE the BIT_FIELD_REFs variable
operand, something we could fix easily at the tree level).

On the original mem-ref branch BIT_FIELD_REFs were not
allowed on memory, with that lowering in place it would have been
optimized already.  It would already help if sole BIT_FIELD_REF
(and REAL/IMAGPART_EXPR) operating on register type variables
would act as non-reference operations.  For the vector selection
case that is one more reason in favor of a VECT_SELECT_EXPR
of course.

OTOH the case with the global variable is probably not too common
to worry about at the moment.

The argument that we should optimize vec[3] the same as *((short *)vec + 3)
is valid (same as in as good), so the FE could just rely on that.

Richard.

>
> Artem.
>
> On Wed, Oct 20, 2010 at 11:47 PM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Thu, Oct 21, 2010 at 12:06 AM, Richard Henderson <rth@redhat.com> wrote:
>>> On 10/20/2010 02:47 PM, Richard Guenther wrote:
>>>> On Wed, Oct 20, 2010 at 11:36 PM, Richard Henderson <rth@redhat.com> wrote:
>>>>> On 10/20/2010 02:27 PM, Richard Guenther wrote:
>>>>>> A VIEW_CONVERT_EXPR <ARRAY_TYPE, register>[index] should also work.
>>>>>
>>>>> That should mark the variable addressable iff index is non-constant?
>>>>
>>>> No, the variable will still be in SSA form, thus the expanders have to take
>>>> extra care.  The variable will be non-addressable but in non-SSA form
>>>> if there are partial stores though.
>>>
>>> Er, of course there will be partial stores.  That's the
>>> whole point of setting an element.
>>>
>>> It's almost certainly better, then, to have a new code
>>>
>>>  vector<T> v;
>>>  T t;
>>>
>>>  v1 = VEC_SET_EXPR(v0, index, t0);
>>>  t1 = VEC_EXT_EXPR(v0, index)
>>>
>>> which can at least keep V in SSA form, and avoid playing
>>> silly games with ARRAY_REF_EXPR.
>>
>> ;)
>>
>> We also lack a genuine vector construction tree and use CONSTRUCTOR
>> for it.  But your VEC_SET_EXPR sounds much like the BIT_FIELD_EXPR
>> I want to invent for the modify part of a read-modify-write bitfield store.
>>
>> Anyway, the question is what we want to do now, given we're close to
>> stage3 and nothing in the middle-end currently knows about a
>> VEC_SET_EXPR or a VEC_EXT_EXPR.
>>
>> Doing the addressable memory thing will pessimize -O0 for sure, but
>> the optimizers should be able to fix it up.  We can easily special-case
>> constant indices on the RHS with BIT_FIELD_REF.
>>
>> Richard.
>>
>>>
>>> r~
>>>
>>
>
diff mbox

Patch

Index: gcc/doc/extend.texi
===================================================================
--- gcc/doc/extend.texi	(revision 165700)
+++ gcc/doc/extend.texi	(working copy)
@@ -6310,6 +6310,11 @@  minus or complement operators on a vecto
 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 165700)
+++ gcc/c-family/c-common.c	(working copy)
@@ -8703,6 +8703,18 @@  complete_array_type (tree *ptype, tree i
   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 165700)
+++ gcc/c-family/c-common.h	(working copy)
@@ -933,6 +933,8 @@  extern int complete_array_type (tree *, 
 
 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,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-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-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/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,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.dg/array-8.c
===================================================================
--- gcc/testsuite/gcc.dg/array-8.c	(revision 165700)
+++ gcc/testsuite/gcc.dg/array-8.c	(working copy)
@@ -35,7 +35,7 @@  g (void)
   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 165700)
+++ gcc/c-typeck.c	(working copy)
@@ -2305,6 +2305,9 @@  build_indirect_ref (location_t loc, tree
    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
@@ -2317,13 +2320,17 @@  build_array_ref (location_t loc, tree ar
     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;
@@ -2353,6 +2360,27 @@  build_array_ref (location_t loc, tree ar
   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)
     {