This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: patch: vector_size attribute
- From: Aldy Hernandez <aldyh at redhat dot com>
- To: "Joseph S. Myers" <jsm28 at cam dot ac dot uk>
- Cc: Richard Henderson <rth at redhat dot com>, gcc patches <gcc-patches at gcc dot gnu dot org>
- Date: 06 Dec 2001 15:01:17 -0800
- Subject: Re: patch: vector_size attribute
- References: <Pine.LNX.4.33.0112060223080.9885-100000@kern.srcf.societies.cam.ac.uk>
> > we need to traverse and find the type being modified (short). then, we
> > need to build back the pointers. this is icky, i know.
>
> You need to do the same thing as well for function return types and array
> element types.
good catch! thanks.
function return types, arrays, and pointers are now supported,
documented, and a corresponding test case is included.
ok?
2001-12-04 Aldy Hernandez <aldyh@redhat.com>
* stor-layout.c (layout_decl): Reset the decl's mode.
* extend.texi (Variable Attributes): Document vector_size.
* gcc.dg/altivec-2.c: New.
* attribs.c (c_common_attribute_table): Add vector_size.
(handle_vector_size_attribute): New.
(vector_size_helper): New.
(decl_attributes): Relayout the decl after calculating attribs.
Index: stor-layout.c
===================================================================
RCS file: /cvs/uberbaum/gcc/stor-layout.c,v
retrieving revision 1.113
diff -c -p -r1.113 stor-layout.c
*** stor-layout.c 2001/12/03 15:22:47 1.113
--- stor-layout.c 2001/12/06 22:57:09
*************** layout_decl (decl, known_align)
*** 358,365 ****
don't set it again since we can be called twice for FIELD_DECLs. */
TREE_UNSIGNED (decl) = TREE_UNSIGNED (type);
! if (DECL_MODE (decl) == VOIDmode)
! DECL_MODE (decl) = TYPE_MODE (type);
if (DECL_SIZE (decl) == 0)
{
--- 358,364 ----
don't set it again since we can be called twice for FIELD_DECLs. */
TREE_UNSIGNED (decl) = TREE_UNSIGNED (type);
! DECL_MODE (decl) = TYPE_MODE (type);
if (DECL_SIZE (decl) == 0)
{
Index: attribs.c
===================================================================
RCS file: /cvs/uberbaum/gcc/attribs.c,v
retrieving revision 1.4
diff -c -p -r1.4 attribs.c
*** attribs.c 2001/11/04 02:51:21 1.4
--- attribs.c 2001/12/06 22:57:09
*************** static tree handle_no_limit_stack_attrib
*** 84,89 ****
--- 84,92 ----
bool *));
static tree handle_pure_attribute PARAMS ((tree *, tree, tree, int,
bool *));
+ static tree handle_vector_size_attribute PARAMS ((tree *, tree, tree, int,
+ bool *));
+ static tree vector_size_helper PARAMS ((tree, tree));
/* Table of machine-independent attributes common to all C-like languages. */
static const struct attribute_spec c_common_attribute_table[] =
*************** static const struct attribute_spec c_com
*** 139,144 ****
--- 142,149 ----
handle_no_limit_stack_attribute },
{ "pure", 0, 0, true, false, false,
handle_pure_attribute },
+ { "vector_size", 1, 1, false, true, false,
+ handle_vector_size_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
*************** decl_attributes (node, attributes, flags
*** 367,372 ****
--- 372,383 ----
returned_attrs = chainon ((*spec->handler) (anode, name, args,
flags, &no_add_attrs),
returned_attrs);
+
+ /* Layout the decl in case anything changed. */
+ if (spec->type_required && DECL_P (*node)
+ && TREE_CODE (*node) == VAR_DECL)
+ layout_decl (*node, 0);
+
if (!no_add_attrs)
{
tree old_attrs;
*************** handle_pure_attribute (node, name, args,
*** 1154,1159 ****
--- 1165,1292 ----
}
return NULL_TREE;
+ }
+
+ /* Handle a "vector_size" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+ static tree
+ handle_vector_size_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+ {
+ unsigned int vecsize, nunits;
+ enum machine_mode mode, orig_mode, new_mode;
+ tree type = *node, new_type;
+
+ *no_add_attrs = true;
+
+ if (TREE_CODE (TREE_VALUE (args)) != INTEGER_CST)
+ {
+ warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+ return NULL_TREE;
+ }
+
+ /* Get the vector size (in bytes). */
+ vecsize = TREE_INT_CST_LOW (TREE_VALUE (args));
+
+ /* We need to provide for vector pointers, vector arrays, and
+ functions returning vectors. For example:
+
+ __attribute__((vector_size(16))) short *foo;
+
+ In this case, the mode is SI, but the type being modified is
+ HI, so we need to look further. */
+
+ while (POINTER_TYPE_P (type)
+ || TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+
+ /* Get the mode of the type being modified. */
+ orig_mode = TYPE_MODE (type);
+
+ if (TREE_CODE (type) == RECORD_TYPE ||
+ (GET_MODE_CLASS (orig_mode) != MODE_FLOAT
+ && GET_MODE_CLASS (orig_mode) != MODE_INT))
+ {
+ error ("invalid vector type for attribute `%s'",
+ IDENTIFIER_POINTER (name));
+ return NULL_TREE;
+ }
+
+ /* Calculate how many units fit in the vector. */
+ nunits = vecsize / TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
+
+ /* Find a suitably sized vector. */
+ new_mode = VOIDmode;
+ for (mode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_mode) == MODE_INT
+ ? MODE_VECTOR_INT
+ : MODE_VECTOR_FLOAT);
+ mode != VOIDmode;
+ mode = GET_MODE_WIDER_MODE (mode))
+ if (vecsize == GET_MODE_SIZE (mode) && nunits == GET_MODE_NUNITS (mode))
+ {
+ new_mode = mode;
+ break;
+ }
+
+ if (new_mode == VOIDmode)
+ error ("no vector mode with the size and type specified could be found");
+ else
+ {
+ new_type = type_for_mode (new_mode, TREE_UNSIGNED (type));
+ if (!new_type)
+ error ("no vector mode with the size and type specified could be found");
+ else
+ /* Build back pointers if needed. */
+ *node = vector_size_helper (*node, new_type);
+ }
+
+ return NULL_TREE;
+ }
+
+ /* HACK. GROSS. This is absolutely disgusting. I wish there was a
+ better way.
+
+ If we requested a pointer to a vector, build up the pointers that
+ we stripped off while looking for the inner type. Similarly for
+ return values from functions.
+
+ The argument "type" is the top of the chain, and "bottom" is the
+ new type which we will point to. */
+
+ static tree
+ vector_size_helper (type, bottom)
+ tree type, bottom;
+ {
+ tree inner, outer;
+
+ if (POINTER_TYPE_P (type))
+ {
+ inner = vector_size_helper (TREE_TYPE (type), bottom);
+ outer = build_pointer_type (inner);
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ inner = vector_size_helper (TREE_TYPE (type), bottom);
+ outer = build_array_type (inner, TYPE_VALUES (type));
+ }
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ inner = vector_size_helper (TREE_TYPE (type), bottom);
+ outer = build_function_type (inner, TYPE_VALUES (type));
+ }
+ else
+ return bottom;
+
+ TREE_READONLY (outer) = TREE_READONLY (type);
+ TREE_THIS_VOLATILE (outer) = TREE_THIS_VOLATILE (type);
+
+ return outer;
}
/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two
Index: doc/extend.texi
===================================================================
RCS file: /cvs/uberbaum/gcc/doc/extend.texi,v
retrieving revision 1.37
diff -c -p -r1.37 extend.texi
*** extend.texi 2001/11/18 03:30:55 1.37
--- extend.texi 2001/12/06 22:57:10
*************** section.
*** 2826,2839 ****
The keyword @code{__attribute__} allows you to specify special
attributes of variables or structure fields. This keyword is followed
! by an attribute specification inside double parentheses. Eight
attributes are currently defined for variables: @code{aligned},
@code{mode}, @code{nocommon}, @code{packed}, @code{section},
! @code{transparent_union}, @code{unused}, and @code{weak}. Some other
! attributes are defined for variables on particular target systems. Other
! attributes are available for functions (@pxref{Function Attributes}) and
! for types (@pxref{Type Attributes}). Other front ends might define more
! attributes (@pxref{C++ Extensions,,Extensions to the C++ Language}).
You may also specify attributes with @samp{__} preceding and following
each keyword. This allows you to use them in header files without
--- 2826,2840 ----
The keyword @code{__attribute__} allows you to specify special
attributes of variables or structure fields. This keyword is followed
! by an attribute specification inside double parentheses. Nine
attributes are currently defined for variables: @code{aligned},
@code{mode}, @code{nocommon}, @code{packed}, @code{section},
! @code{transparent_union}, @code{unused}, @code{vector_size}, and
! @code{weak}. Some other attributes are defined for variables on
! particular target systems. Other attributes are available for functions
! (@pxref{Function Attributes}) and for types (@pxref{Type Attributes}).
! Other front ends might define more attributes (@pxref{C++
! Extensions,,Extensions to the C++ Language}).
You may also specify attributes with @samp{__} preceding and following
each keyword. This allows you to use them in header files without
*************** applies to all function parameters with
*** 3034,3039 ****
--- 3035,3069 ----
This attribute, attached to a variable, means that the variable is meant
to be possibly unused. GCC will not produce a warning for this
variable.
+
+ @item vector_size (@var{bytes})
+ This attribute specifies the vector size for the variable, measured in
+ bytes. For example, the declaration:
+
+ @smallexample
+ int foo __attribute__ ((vector_size (16)));
+ @end smallexample
+
+ @noindent
+ causes the compiler to set the mode for @code{foo}, to be 16 bytes,
+ divided into @code{int} sized units. Assuming a 32-bit int (a vector of
+ 4 units of 4 bytes), the corresponding mode of @code{foo} will be V4SI@.
+
+ This attribute is only applicable to integral and float scalars,
+ although arrays, pointers, and function return values are allowed in
+ conjunction with this construct.
+
+ Aggregates with this attribute are invalid, even if they are of the same
+ size as a corresponding scalar. For example, the declaration:
+
+ @smallexample
+ struct S { int a; };
+ struct S __attribute__ ((vector_size (16))) foo;
+ @end smallexample
+
+ @noindent
+ is invalid even if the size of the structure is the same as the size of
+ the @code{int}.
@item weak
The @code{weak} attribute is described in @xref{Function Attributes}.
Index: testsuite/gcc.dg/altivec-2.c
===================================================================
RCS file: altivec-2.c
diff -N altivec-2.c
*** /dev/null Tue May 5 13:32:27 1998
--- altivec-2.c Thu Dec 6 14:57:10 2001
***************
*** 0 ****
--- 1,34 ----
+ /* { dg-do compile { target powerpc-*-* } } */
+ /* { dg-options "-maltivec" } */
+
+ /* Program to test the vector_size attribute. This needs to run on a
+ target that has vectors, so use AltiVec. */
+
+ #define vector __attribute__((vector_size(16)))
+
+ vector int foobar;
+
+ /* Only floats and integrals allowed. We don't care if they map to SIs. */
+ struct X { int frances; };
+ vector struct X hotdog; /* { dg-bogus "invalid vector type" "case 1" } */
+
+ /* We don't have a V2DF. */
+ vector double x; /* { dg-bogus "no vector mode" "case 2" } */
+
+ /* Arrays of vectors. */
+ vector char b[10], ouch;
+
+ /* Pointers of vectors. */
+ vector short *shoe, polish;
+
+ code ()
+ {
+ *shoe = polish;
+ b[1] = ouch;
+ }
+
+ vector short
+ hoop ()
+ {
+ return polish;
+ }