Message ID | AANLkTinBCvNWt3ymLHvGWVCJ-cPL84wX++bTy+EBVj5M@mail.gmail.com |
---|---|
State | New |
Headers | show |
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.
> + 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~
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~ >
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~
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~ >
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~
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~ >
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~
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 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~ >> >
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~ >>> >> >
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) {