Patchwork [C/Ada] Streamline range type building and hashing

login
register
mail settings
Submitter Eric Botcazou
Date Sept. 17, 2010, 8:04 p.m.
Message ID <201009172204.59257.ebotcazou@adacore.com>
Download mbox | patch
Permalink /patch/65104/
State New
Headers show

Comments

Eric Botcazou - Sept. 17, 2010, 8:04 p.m.
> 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  <ebotcazou@adacore.com>

	* 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.
Richard Guenther - Sept. 20, 2010, 12:56 p.m.
On Fri, 17 Sep 2010, Eric Botcazou wrote:

> > 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?

Ok.

Thanks,
RIchard.

> 
> 2010-09-17  Eric Botcazou  <ebotcazou@adacore.com>
> 
> 	* 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.
> 
> 
>

Patch

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