From fc07fe6f0dea70cf76f449013807b5d243d9f771 Mon Sep 17 00:00:00 2001 From: ebotcazou Date: Tue, 15 Apr 2014 08:59:12 +0000 Subject: [PATCH] * gcc-interface/utils.c (type_for_vector_element_p): New predicate. (build_vector_type_for_size): New function. (build_vector_type_for_array): Likewise. (unchecked_convert): Build an intermediate vector type to convert from a generic array type to a vector type. (handle_vector_size_attribute): Reimplement. (handle_vector_type_attribute): Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@209410 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ada/ChangeLog | 10 ++ gcc/ada/gcc-interface/utils.c | 240 +++++++++++++++++++-------------------- gcc/testsuite/ChangeLog | 4 + gcc/testsuite/gnat.dg/vect14.adb | 25 ++++ 4 files changed, 157 insertions(+), 122 deletions(-) create mode 100644 gcc/testsuite/gnat.dg/vect14.adb diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index 7658d3d6a5b..7f66b56fcf4 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,5 +1,15 @@ 2014-04-15 Eric Botcazou + * gcc-interface/utils.c (type_for_vector_element_p): New predicate. + (build_vector_type_for_size): New function. + (build_vector_type_for_array): Likewise. + (unchecked_convert): Build an intermediate vector type to convert + from a generic array type to a vector type. + (handle_vector_size_attribute): Reimplement. + (handle_vector_type_attribute): Likewise. + +2014-04-15 Eric Botcazou + * gcc-interface/decl.c (prepend_one_attribute_pragma): Call Is_OK_Static_Expression in lieu of Is_Static_Expression to detect valid arguments. diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c index 44877b6d767..8172f5f9900 100644 --- a/gcc/ada/gcc-interface/utils.c +++ b/gcc/ada/gcc-interface/utils.c @@ -3194,6 +3194,96 @@ build_template (tree template_type, tree array_type, tree expr) return gnat_build_constructor (template_type, template_elts); } +/* Return true if TYPE is suitable for the element type of a vector. */ + +static bool +type_for_vector_element_p (tree type) +{ + enum machine_mode mode; + + if (!INTEGRAL_TYPE_P (type) + && !SCALAR_FLOAT_TYPE_P (type) + && !FIXED_POINT_TYPE_P (type)) + return false; + + mode = TYPE_MODE (type); + if (GET_MODE_CLASS (mode) != MODE_INT + && !SCALAR_FLOAT_MODE_P (mode) + && !ALL_SCALAR_FIXED_POINT_MODE_P (mode)) + return false; + + return true; +} + +/* Return a vector type given the SIZE and the INNER_TYPE, or NULL_TREE if + this is not possible. If ATTRIBUTE is non-zero, we are processing the + attribute declaration and want to issue error messages on failure. */ + +static tree +build_vector_type_for_size (tree inner_type, tree size, tree attribute) +{ + unsigned HOST_WIDE_INT size_int, inner_size_int; + int nunits; + + /* Silently punt on variable sizes. We can't make vector types for them, + need to ignore them on front-end generated subtypes of unconstrained + base types, and this attribute is for binding implementors, not end + users, so we should never get there from legitimate explicit uses. */ + if (!tree_fits_uhwi_p (size)) + return NULL_TREE; + size_int = tree_to_uhwi (size); + + if (!type_for_vector_element_p (inner_type)) + { + if (attribute) + error ("invalid element type for attribute %qs", + IDENTIFIER_POINTER (attribute)); + return NULL_TREE; + } + inner_size_int = tree_to_uhwi (TYPE_SIZE_UNIT (inner_type)); + + if (size_int % inner_size_int) + { + if (attribute) + error ("vector size not an integral multiple of component size"); + return NULL_TREE; + } + + if (size_int == 0) + { + if (attribute) + error ("zero vector size"); + return NULL_TREE; + } + + nunits = size_int / inner_size_int; + if (nunits & (nunits - 1)) + { + if (attribute) + error ("number of components of vector not a power of two"); + return NULL_TREE; + } + + return build_vector_type (inner_type, nunits); +} + +/* Return a vector type whose representative array type is ARRAY_TYPE, or + NULL_TREE if this is not possible. If ATTRIBUTE is non-zero, we are + processing the attribute and want to issue error messages on failure. */ + +static tree +build_vector_type_for_array (tree array_type, tree attribute) +{ + tree vector_type = build_vector_type_for_size (TREE_TYPE (array_type), + TYPE_SIZE_UNIT (array_type), + attribute); + if (!vector_type) + return NULL_TREE; + + TYPE_REPRESENTATIVE_ARRAY (vector_type) = array_type; + return vector_type; +} + /* Helper routine to make a descriptor field. FIELD_LIST is the list of decls being built; the new decl is chained on to the front of the list. */ @@ -5268,6 +5358,7 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) tree etype = TREE_TYPE (expr); enum tree_code ecode = TREE_CODE (etype); enum tree_code code = TREE_CODE (type); + tree tem; int c; /* If the expression is already of the right type, we are done. */ @@ -5414,6 +5505,18 @@ unchecked_convert (tree type, tree expr, bool notrunc_p) etype)) expr = convert (type, expr); + /* And, if the array type is not the representative, we try to build an + intermediate vector type of which the array type is the representative + and to do the unchecked conversion between the vector types, in order + to enable further simplifications in the middle-end. */ + else if (code == VECTOR_TYPE + && ecode == ARRAY_TYPE + && (tem = build_vector_type_for_array (etype, NULL_TREE))) + { + expr = convert (tem, expr); + return unchecked_convert (type, expr, notrunc_p); + } + /* If we are converting a CONSTRUCTOR to a more aligned RECORD_TYPE, bump the alignment of the CONSTRUCTOR to speed up the copy operation. */ else if (TREE_CODE (expr) == CONSTRUCTOR @@ -6310,27 +6413,13 @@ handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name), static tree handle_vector_size_attribute (tree *node, tree name, tree args, - int ARG_UNUSED (flags), - bool *no_add_attrs) + int ARG_UNUSED (flags), bool *no_add_attrs) { - unsigned HOST_WIDE_INT vecsize, nunits; - enum machine_mode orig_mode; - tree type = *node, new_type, size; + tree type = *node; + tree vector_type; *no_add_attrs = true; - size = TREE_VALUE (args); - - if (!tree_fits_uhwi_p (size)) - { - warning (OPT_Wattributes, "%qs attribute ignored", - IDENTIFIER_POINTER (name)); - return NULL_TREE; - } - - /* Get the vector size (in bytes). */ - vecsize = tree_to_uhwi (size); - /* We need to provide for vector pointers, vector arrays, and functions returning vectors. For example: @@ -6338,53 +6427,17 @@ handle_vector_size_attribute (tree *node, tree name, tree args, 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 ((!INTEGRAL_TYPE_P (type) - && !SCALAR_FLOAT_TYPE_P (type) - && !FIXED_POINT_TYPE_P (type)) - || (!SCALAR_FLOAT_MODE_P (orig_mode) - && GET_MODE_CLASS (orig_mode) != MODE_INT - && !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode)) - || !tree_fits_uhwi_p (TYPE_SIZE_UNIT (type)) - || TREE_CODE (type) == BOOLEAN_TYPE) - { - error ("invalid vector type for attribute %qs", - IDENTIFIER_POINTER (name)); - return NULL_TREE; - } - - if (vecsize % tree_to_uhwi (TYPE_SIZE_UNIT (type))) - { - error ("vector size not an integral multiple of component size"); - return NULL; - } - - if (vecsize == 0) - { - error ("zero vector size"); - return NULL; - } - - /* Calculate how many units fit in the vector. */ - nunits = vecsize / tree_to_uhwi (TYPE_SIZE_UNIT (type)); - if (nunits & (nunits - 1)) - { - error ("number of components of the vector not a power of two"); - return NULL_TREE; - } - - new_type = build_vector_type (type, nunits); + vector_type = build_vector_type_for_size (type, TREE_VALUE (args), name); + if (!vector_type) + return NULL_TREE; /* Build back pointers if needed. */ - *node = reconstruct_complex_type (*node, new_type); + *node = reconstruct_complex_type (*node, vector_type); return NULL_TREE; } @@ -6394,83 +6447,26 @@ handle_vector_size_attribute (tree *node, tree name, tree args, static tree handle_vector_type_attribute (tree *node, tree name, tree ARG_UNUSED (args), - int ARG_UNUSED (flags), - bool *no_add_attrs) + int ARG_UNUSED (flags), bool *no_add_attrs) { - /* Vector representative type and size. */ - tree rep_type = *node; - tree rep_size = TYPE_SIZE_UNIT (rep_type); - - /* Vector size in bytes and number of units. */ - unsigned HOST_WIDE_INT vec_bytes, vec_units; - - /* Vector element type and mode. */ - tree elem_type; - enum machine_mode elem_mode; + tree type = *node; + tree vector_type; *no_add_attrs = true; - if (TREE_CODE (rep_type) != ARRAY_TYPE) + if (TREE_CODE (type) != ARRAY_TYPE) { error ("attribute %qs applies to array types only", IDENTIFIER_POINTER (name)); return NULL_TREE; } - /* Silently punt on variable sizes. We can't make vector types for them, - need to ignore them on front-end generated subtypes of unconstrained - bases, and this attribute is for binding implementors, not end-users, so - we should never get there from legitimate explicit uses. */ - - if (!tree_fits_uhwi_p (rep_size)) + vector_type = build_vector_type_for_array (type, name); + if (!vector_type) return NULL_TREE; - /* Get the element type/mode and check this is something we know - how to make vectors of. */ - - elem_type = TREE_TYPE (rep_type); - elem_mode = TYPE_MODE (elem_type); - - if ((!INTEGRAL_TYPE_P (elem_type) - && !SCALAR_FLOAT_TYPE_P (elem_type) - && !FIXED_POINT_TYPE_P (elem_type)) - || (!SCALAR_FLOAT_MODE_P (elem_mode) - && GET_MODE_CLASS (elem_mode) != MODE_INT - && !ALL_SCALAR_FIXED_POINT_MODE_P (elem_mode)) - || !tree_fits_uhwi_p (TYPE_SIZE_UNIT (elem_type))) - { - error ("invalid element type for attribute %qs", - IDENTIFIER_POINTER (name)); - return NULL_TREE; - } - - /* Sanity check the vector size and element type consistency. */ - - vec_bytes = tree_to_uhwi (rep_size); - - if (vec_bytes % tree_to_uhwi (TYPE_SIZE_UNIT (elem_type))) - { - error ("vector size not an integral multiple of component size"); - return NULL; - } - - if (vec_bytes == 0) - { - error ("zero vector size"); - return NULL; - } - - vec_units = vec_bytes / tree_to_uhwi (TYPE_SIZE_UNIT (elem_type)); - if (vec_units & (vec_units - 1)) - { - error ("number of components of the vector not a power of two"); - return NULL_TREE; - } - - /* Build the vector type and replace. */ - - *node = build_vector_type (elem_type, vec_units); - TYPE_REPRESENTATIVE_ARRAY (*node) = rep_type; + TYPE_REPRESENTATIVE_ARRAY (vector_type) = type; + *node = vector_type; return NULL_TREE; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 739e1ecc5bd..a2645d84097 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2014-04-15 Eric Botcazou + * gnat.dg/vect14.adb: New test. + +2014-04-15 Eric Botcazou + * gnat.dg/vect12.ad[sb]: New test. * gnat.dg/vect13.ad[sb]: Likewise. diff --git a/gcc/testsuite/gnat.dg/vect14.adb b/gcc/testsuite/gnat.dg/vect14.adb new file mode 100644 index 00000000000..adc6ff14b66 --- /dev/null +++ b/gcc/testsuite/gnat.dg/vect14.adb @@ -0,0 +1,25 @@ +-- { dg-do compile { target i?86-*-* x86_64-*-* } } +-- { dg-options "-fdump-tree-optimized" } + +with Interfaces; +with Unchecked_Conversion; + +with GNAT.SSE.Vector_Types; use GNAT.SSE.Vector_Types; + +procedure Vect14 is + + Msk1 : constant := 16#000FFAFFFFFFFB3F#; + Msk2 : constant := 16#000FFDFFFC90FFFD#; + + type Unsigned_64_Array_Type is array (1 .. 2) of Interfaces.Unsigned_64; + + function Convert is new Unchecked_Conversion (Unsigned_64_Array_Type, M128i); + + Sse2_Param_Mask : constant M128i := Convert ((Msk1, Msk2)); + +begin + null; +end; + +-- { dg-final { scan-tree-dump-not "VIEW_CONVERT_EXPR" "optimized" } } +-- { dg-final { cleanup-tree-dump "optimized" } } -- 2.11.4.GIT