From patchwork Fri Sep 17 20:04:59 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Botcazou X-Patchwork-Id: 65104 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 7FE8BB70AE for ; Sat, 18 Sep 2010 06:11:49 +1000 (EST) Received: (qmail 1035 invoked by alias); 17 Sep 2010 20:11:46 -0000 Received: (qmail 1023 invoked by uid 22791); 17 Sep 2010 20:11:43 -0000 X-SWARE-Spam-Status: No, hits=-2.1 required=5.0 tests=AWL,BAYES_00 X-Spam-Check-By: sourceware.org Received: from mel.act-europe.fr (HELO mel.act-europe.fr) (212.99.106.210) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 17 Sep 2010 20:11:35 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id E27F8CB029B; Fri, 17 Sep 2010 22:11:32 +0200 (CEST) Received: from mel.act-europe.fr ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id eQKmq2z3sT9m; Fri, 17 Sep 2010 22:11:32 +0200 (CEST) Received: from [192.168.1.2] (bon31-9-83-155-120-49.fbx.proxad.net [83.155.120.49]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mel.act-europe.fr (Postfix) with ESMTP id 8A40FCB0240; Fri, 17 Sep 2010 22:11:32 +0200 (CEST) From: Eric Botcazou To: Richard Guenther Subject: Re: [PATCH][C/Ada] Streamline range type building and hashing Date: Fri, 17 Sep 2010 22:04:59 +0200 User-Agent: KMail/1.9.9 Cc: gcc-patches@gcc.gnu.org References: <201009101228.58933.ebotcazou@adacore.com> In-Reply-To: MIME-Version: 1.0 Message-Id: <201009172204.59257.ebotcazou@adacore.com> Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org > Sure. Another approach would be to introduce a build_nonshared_array_type > function and make that and build_array_type wrap a common worker with > a flag. Unsurprisingly we need the same treatment for range types as for array types. Here's the proposed patch, tested on i586-suse-linux, OK for mainline? 2010-09-17 Eric Botcazou * langhooks.h (struct lang_hooks_for_types): Remove hash_types field. * langhooks-def.h (LANG_HOOKS_HASH_TYPES): Delete. (LANG_HOOKS_FOR_TYPES_INITIALIZER): Remove LANG_HOOKS_HASH_TYPES. * system.h (LANG_HOOKS_HASH_TYPES): Poison. * tree.c (type_hash_canon): Do not test lang_hooks.types.hash_types. (build_nonstandard_integer_type): Likewise. (build_range_type_1): New function, built from... (build_range_type): ...this. Call build_range_type_1. (build_nonshared_range_type): New function. (build_array_type_1): New function, built from... (build_array_type: ...this. Call build_array_type_1. (build_nonshared_array_type): New function. * tree.h (build_nonshared_range_type): Declare. (build_nonshared_array_type): Likewise. ada/ * gcc-interface/decl.c (gnat_to_gnu_entity): Replace calls to build_array_type with calls to build_nonshared_array_type. (substitute_in_type): Likewise. * gcc-interface/misc.c (LANG_HOOKS_HASH_TYPES): Delete. (LANG_HOOKS_TYPE_HASH_EQ): Define. (gnat_post_options): Add 'static' keyword. (gnat_type_hash_eq): New static function. * gcc-interface/utils.c (fntype_same_flags_p): New function. (create_subprog_type): Call it. (create_index_type): Call build_nonshared_range_type and tidy up. (create_range_type): Likewise. * gcc-interface/gigi.h (fntype_same_flags_p): Declare. Index: tree.c =================================================================== --- tree.c (revision 164295) +++ tree.c (working copy) @@ -6104,9 +6104,6 @@ type_hash_canon (unsigned int hashcode, being passed. */ gcc_assert (TYPE_MAIN_VARIANT (type) == type); - if (!lang_hooks.types.hash_types) - return type; - /* See if the type is in the hash table already. If so, return it. Otherwise, add the type. */ t1 = type_hash_lookup (hashcode, type); @@ -7074,21 +7071,20 @@ build_nonstandard_integer_type (unsigned ret = itype; if (host_integerp (TYPE_MAX_VALUE (itype), 1)) ret = type_hash_canon (tree_low_cst (TYPE_MAX_VALUE (itype), 1), itype); - if (precision <= MAX_INT_CACHED_PREC && lang_hooks.types.hash_types) + if (precision <= MAX_INT_CACHED_PREC) nonstandard_integer_type_cache[precision + unsignedp] = ret; return ret; } -/* Create a range of some discrete type TYPE (an INTEGER_TYPE, - ENUMERAL_TYPE or BOOLEAN_TYPE), with low bound LOWVAL and - high bound HIGHVAL. */ +/* Create a range of some discrete type TYPE (an INTEGER_TYPE, ENUMERAL_TYPE + or BOOLEAN_TYPE) with low bound LOWVAL and high bound HIGHVAL. If SHARED + is true, reuse such a type that has already been constructed. */ -tree -build_range_type (tree type, tree lowval, tree highval) +static tree +build_range_type_1 (tree type, tree lowval, tree highval, bool shared) { tree itype = make_node (INTEGER_TYPE); - hashval_t hash; TREE_TYPE (itype) = type; @@ -7112,10 +7108,32 @@ build_range_type (tree type, tree lowval SET_TYPE_STRUCTURAL_EQUALITY (itype); return itype; } - hash = iterative_hash_expr (TYPE_MIN_VALUE (itype), 0); - hash = iterative_hash_expr (TYPE_MAX_VALUE (itype), hash); - hash = iterative_hash_hashval_t (TYPE_HASH (type), hash); - return type_hash_canon (hash, itype); + + if (shared) + { + hashval_t hash = iterative_hash_expr (TYPE_MIN_VALUE (itype), 0); + hash = iterative_hash_expr (TYPE_MAX_VALUE (itype), hash); + hash = iterative_hash_hashval_t (TYPE_HASH (type), hash); + itype = type_hash_canon (hash, itype); + } + + return itype; +} + +/* Wrapper around build_range_type_1 with SHARED set to true. */ + +tree +build_range_type (tree type, tree lowval, tree highval) +{ + return build_range_type_1 (type, lowval, highval, true); +} + +/* Wrapper around build_range_type_1 with SHARED set to false. */ + +tree +build_nonshared_range_type (tree type, tree lowval, tree highval) +{ + return build_range_type_1 (type, lowval, highval, false); } /* Create a type of integers to be the TYPE_DOMAIN of an ARRAY_TYPE. @@ -7186,13 +7204,12 @@ subrange_type_for_debug_p (const_tree ty /* Construct, lay out and return the type of arrays of elements with ELT_TYPE and number of elements specified by the range of values of INDEX_TYPE. - If such a type has already been constructed, reuse it. */ + If SHARED is true, reuse such a type that has already been constructed. */ -tree -build_array_type (tree elt_type, tree index_type) +static tree +build_array_type_1 (tree elt_type, tree index_type, bool shared) { tree t; - hashval_t hashcode = 0; if (TREE_CODE (elt_type) == FUNCTION_TYPE) { @@ -7212,10 +7229,13 @@ build_array_type (tree elt_type, tree in if (TYPE_STRUCTURAL_EQUALITY_P (t)) return t; - hashcode = iterative_hash_object (TYPE_HASH (elt_type), hashcode); - if (index_type) - hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode); - t = type_hash_canon (hashcode, t); + if (shared) + { + hashval_t hashcode = iterative_hash_object (TYPE_HASH (elt_type), 0); + if (index_type) + hashcode = iterative_hash_object (TYPE_HASH (index_type), hashcode); + t = type_hash_canon (hashcode, t); + } if (TYPE_CANONICAL (t) == t) { @@ -7225,13 +7245,31 @@ build_array_type (tree elt_type, tree in else if (TYPE_CANONICAL (elt_type) != elt_type || (index_type && TYPE_CANONICAL (index_type) != index_type)) TYPE_CANONICAL (t) - = build_array_type (TYPE_CANONICAL (elt_type), - index_type ? TYPE_CANONICAL (index_type) : NULL); + = build_array_type_1 (TYPE_CANONICAL (elt_type), + index_type + ? TYPE_CANONICAL (index_type) : NULL_TREE, + shared); } return t; } +/* Wrapper around build_array_type_1 with SHARED set to true. */ + +tree +build_array_type (tree elt_type, tree index_type) +{ + return build_array_type_1 (elt_type, index_type, true); +} + +/* Wrapper around build_array_type_1 with SHARED set to false. */ + +tree +build_nonshared_array_type (tree elt_type, tree index_type) +{ + return build_array_type_1 (elt_type, index_type, false); +} + /* Recursively examines the array elements of TYPE, until a non-array element type is found. */ Index: tree.h =================================================================== --- tree.h (revision 164295) +++ tree.h (working copy) @@ -4082,6 +4082,7 @@ extern tree build_opaque_vector_type (tr extern tree build_type_no_quals (tree); extern tree build_index_type (tree); extern tree build_array_type (tree, tree); +extern tree build_nonshared_array_type (tree, tree); extern tree build_function_type (tree, tree); extern tree build_function_type_list (tree, ...); extern tree build_function_type_skip_args (tree, bitmap); @@ -5107,6 +5108,7 @@ extern void build_common_tree_nodes_2 (i extern void build_common_builtin_nodes (void); extern tree build_nonstandard_integer_type (unsigned HOST_WIDE_INT, int); extern tree build_range_type (tree, tree, tree); +extern tree build_nonshared_range_type (tree, tree, tree); extern bool subrange_type_for_debug_p (const_tree, tree *, tree *); extern HOST_WIDE_INT int_cst_value (const_tree); extern HOST_WIDEST_INT widest_int_cst_value (const_tree); Index: langhooks.h =================================================================== --- langhooks.h (revision 164295) +++ langhooks.h (working copy) @@ -138,11 +138,6 @@ struct lang_hooks_for_types return values from functions. The argument TYPE is the top of the chain, and BOTTOM is the new type which we will point to. */ tree (*reconstruct_complex_type) (tree, tree); - - /* Nonzero if types that are identical are to be hashed so that only - one copy is kept. If a language requires unique types for each - user-specified type, such as Ada, this should be set to TRUE. */ - bool hash_types; }; /* Language hooks related to decls and the symbol table. */ Index: system.h =================================================================== --- system.h (revision 164295) +++ system.h (working copy) @@ -780,7 +780,7 @@ extern void fancy_abort (const char *, i LANG_HOOKS_MAYBE_BUILD_CLEANUP LANG_HOOKS_UPDATE_DECL_AFTER_SAVING \ LANG_HOOKS_POPLEVEL LANG_HOOKS_TRUTHVALUE_CONVERSION \ TARGET_PROMOTE_FUNCTION_ARGS TARGET_PROMOTE_FUNCTION_RETURN \ - LANG_HOOKS_MISSING_ARGUMENT + LANG_HOOKS_MISSING_ARGUMENT LANG_HOOKS_HASH_TYPES /* Miscellaneous macros that are no longer used. */ #pragma GCC poison USE_MAPPED_LOCATION Index: langhooks-def.h =================================================================== --- langhooks-def.h (revision 164295) +++ langhooks-def.h (working copy) @@ -178,7 +178,6 @@ extern tree lhd_make_node (enum tree_cod #define LANG_HOOKS_GET_ARRAY_DESCR_INFO NULL #define LANG_HOOKS_GET_SUBRANGE_BOUNDS NULL #define LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE reconstruct_complex_type -#define LANG_HOOKS_HASH_TYPES true #define LANG_HOOKS_FOR_TYPES_INITIALIZER { \ LANG_HOOKS_MAKE_TYPE, \ @@ -195,8 +194,7 @@ extern tree lhd_make_node (enum tree_cod LANG_HOOKS_TYPE_HASH_EQ, \ LANG_HOOKS_GET_ARRAY_DESCR_INFO, \ LANG_HOOKS_GET_SUBRANGE_BOUNDS, \ - LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE, \ - LANG_HOOKS_HASH_TYPES \ + LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE \ } /* Declaration hooks. */ Index: ada/gcc-interface/utils.c =================================================================== --- ada/gcc-interface/utils.c (revision 167894) +++ ada/gcc-interface/utils.c (working copy) @@ -1106,10 +1106,8 @@ create_subprog_type (tree return_type, t /* TYPE may have been shared since GCC hashes types. If it has a different CICO_LIST, make a copy. Likewise for the various flags. */ - if (TYPE_CI_CO_LIST (type) != cico_list - || TYPE_RETURN_UNCONSTRAINED_P (type) != return_unconstrained_p - || TYPE_RETURN_BY_DIRECT_REF_P (type) != return_by_direct_ref_p - || TREE_ADDRESSABLE (type) != return_by_invisi_ref_p) + if (!fntype_same_flags_p (type, cico_list, return_unconstrained_p, + return_by_direct_ref_p, return_by_invisi_ref_p)) { type = copy_type (type); TYPE_CI_CO_LIST (type) = cico_list; @@ -1165,17 +1163,9 @@ tree create_index_type (tree min, tree max, tree index, Node_Id gnat_node) { /* First build a type for the desired range. */ - tree type = build_range_type (sizetype, min, max); - - /* If this type has the TYPE_INDEX_TYPE we want, return it. */ - if (TYPE_INDEX_TYPE (type) == index) - return type; - - /* Otherwise, if TYPE_INDEX_TYPE is set, make a copy. Note that we have - no way of sharing these types, but that's only a small hole. */ - if (TYPE_INDEX_TYPE (type)) - type = copy_type (type); + tree type = build_nonshared_range_type (sizetype, min, max); + /* Then set the index type. */ SET_TYPE_INDEX_TYPE (type, index); create_type_decl (NULL_TREE, type, NULL, true, false, gnat_node); @@ -1194,26 +1184,12 @@ create_range_type (tree type, tree min, type = sizetype; /* First build a type with the base range. */ - range_type - = build_range_type (type, TYPE_MIN_VALUE (type), TYPE_MAX_VALUE (type)); - - min = convert (type, min); - max = convert (type, max); - - /* If this type has the TYPE_RM_{MIN,MAX}_VALUE we want, return it. */ - if (TYPE_RM_MIN_VALUE (range_type) - && TYPE_RM_MAX_VALUE (range_type) - && operand_equal_p (TYPE_RM_MIN_VALUE (range_type), min, 0) - && operand_equal_p (TYPE_RM_MAX_VALUE (range_type), max, 0)) - return range_type; - - /* Otherwise, if TYPE_RM_{MIN,MAX}_VALUE is set, make a copy. */ - if (TYPE_RM_MIN_VALUE (range_type) || TYPE_RM_MAX_VALUE (range_type)) - range_type = copy_type (range_type); + range_type = build_nonshared_range_type (type, TYPE_MIN_VALUE (type), + TYPE_MAX_VALUE (type)); /* Then set the actual range. */ - SET_TYPE_RM_MIN_VALUE (range_type, min); - SET_TYPE_RM_MAX_VALUE (range_type, max); + SET_TYPE_RM_MIN_VALUE (range_type, convert (type, min)); + SET_TYPE_RM_MAX_VALUE (range_type, convert (type, max)); return range_type; } @@ -2123,6 +2099,18 @@ gnat_types_compatible_p (tree t1, tree t return 0; } + +/* Return true if T, a FUNCTION_TYPE, has the specified list of flags. */ + +bool +fntype_same_flags_p (const_tree t, tree cico_list, bool return_unconstrained_p, + bool return_by_direct_ref_p, bool return_by_invisi_ref_p) +{ + return TYPE_CI_CO_LIST (t) == cico_list + && TYPE_RETURN_UNCONSTRAINED_P (t) == return_unconstrained_p + && TYPE_RETURN_BY_DIRECT_REF_P (t) == return_by_direct_ref_p + && TREE_ADDRESSABLE (t) == return_by_invisi_ref_p; +} /* EXP is an expression for the size of an object. If this size contains discriminant references, replace them with the maximum (if MAX_P) or Index: ada/gcc-interface/decl.c =================================================================== --- ada/gcc-interface/decl.c (revision 167848) +++ ada/gcc-interface/decl.c (working copy) @@ -2070,7 +2070,7 @@ gnat_to_gnu_entity (Entity_Id gnat_entit /* Now build the array type. */ for (index = ndim - 1; index >= 0; index--) { - tem = build_array_type (tem, gnu_index_types[index]); + tem = build_nonshared_array_type (tem, gnu_index_types[index]); TYPE_MULTI_ARRAY_P (tem) = (index > 0); if (array_type_has_nonaliased_component (tem, gnat_entity)) TYPE_NONALIASED_COMPONENT (tem) = 1; @@ -2403,7 +2403,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entit /* Now build the array type. */ for (index = ndim - 1; index >= 0; index --) { - gnu_type = build_array_type (gnu_type, gnu_index_types[index]); + gnu_type = build_nonshared_array_type (gnu_type, + gnu_index_types[index]); TYPE_MULTI_ARRAY_P (gnu_type) = (index > 0); if (array_type_has_nonaliased_component (gnu_type, gnat_entity)) TYPE_NONALIASED_COMPONENT (gnu_type) = 1; @@ -2649,8 +2650,9 @@ gnat_to_gnu_entity (Entity_Id gnat_entit gnat_entity); gnu_type - = build_array_type (gnat_to_gnu_type (Component_Type (gnat_entity)), - gnu_index_type); + = build_nonshared_array_type (gnat_to_gnu_type + (Component_Type (gnat_entity)), + gnu_index_type); if (array_type_has_nonaliased_component (gnu_type, gnat_entity)) TYPE_NONALIASED_COMPONENT (gnu_type) = 1; relate_alias_sets (gnu_type, gnu_string_type, ALIAS_SET_COPY); @@ -8610,7 +8612,7 @@ substitute_in_type (tree t, tree f, tree if (component == TREE_TYPE (t) && domain == TYPE_DOMAIN (t)) return t; - nt = build_array_type (component, domain); + nt = build_nonshared_array_type (component, domain); TYPE_ALIGN (nt) = TYPE_ALIGN (t); TYPE_USER_ALIGN (nt) = TYPE_USER_ALIGN (t); SET_TYPE_MODE (nt, TYPE_MODE (t)); Index: ada/gcc-interface/gigi.h =================================================================== --- ada/gcc-interface/gigi.h (revision 167824) +++ ada/gcc-interface/gigi.h (working copy) @@ -447,6 +447,9 @@ extern tree gnat_signed_type (tree type_ transparently converted to each other. */ extern int gnat_types_compatible_p (tree t1, tree t2); +/* Return true if T, a FUNCTION_TYPE, has the specified list of flags. */ +extern bool fntype_same_flags_p (const_tree, tree, bool, bool, bool); + /* Create an expression whose value is that of EXPR, converted to type TYPE. The TREE_TYPE of the value is always TYPE. This function implements all reasonable Index: ada/gcc-interface/misc.c =================================================================== --- ada/gcc-interface/misc.c (revision 167824) +++ ada/gcc-interface/misc.c (working copy) @@ -72,6 +72,7 @@ static void gnat_print_decl (FILE *, tr static void gnat_print_type (FILE *, tree, int); static const char *gnat_printable_name (tree, int); static const char *gnat_dwarf_name (tree, int); +static bool gnat_type_hash_eq (const_tree, const_tree); static tree gnat_return_tree (tree); static void gnat_parse_file (int); static void internal_error_function (diagnostic_context *, @@ -98,8 +99,8 @@ static tree gnat_eh_personality (void); #define LANG_HOOKS_POST_OPTIONS gnat_post_options #undef LANG_HOOKS_PARSE_FILE #define LANG_HOOKS_PARSE_FILE gnat_parse_file -#undef LANG_HOOKS_HASH_TYPES -#define LANG_HOOKS_HASH_TYPES false +#undef LANG_HOOKS_TYPE_HASH_EQ +#define LANG_HOOKS_TYPE_HASH_EQ gnat_type_hash_eq #undef LANG_HOOKS_GETDECLS #define LANG_HOOKS_GETDECLS lhd_return_null_tree_v #undef LANG_HOOKS_PUSHDECL @@ -304,7 +305,7 @@ gnat_init_options (unsigned int decoded_ /* Post-switch processing. */ -bool +static bool gnat_post_options (const char **pfilename ATTRIBUTE_UNUSED) { /* Excess precision other than "fast" requires front-end @@ -598,6 +599,20 @@ gnat_dwarf_name (tree decl, int verbosit return (const char *) IDENTIFIER_POINTER (DECL_NAME (decl)); } +/* Return true if types T1 and T2 are identical for type hashing purposes. + Called only after doing all language independent checks. At present, + this function is only called when both types are FUNCTION_TYPE. */ + +static bool +gnat_type_hash_eq (const_tree t1, const_tree t2) +{ + gcc_assert (TREE_CODE (t1) == FUNCTION_TYPE); + return fntype_same_flags_p (t1, TYPE_CI_CO_LIST (t2), + TYPE_RETURN_UNCONSTRAINED_P (t2), + TYPE_RETURN_BY_DIRECT_REF_P (t2), + TREE_ADDRESSABLE (t2)); +} + /* Do nothing (return the tree node passed). */ static tree