]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gimple.c (gimple_canonical_types, [...]): Move to lto/lto.c
authorRichard Biener <rguenther@suse.de>
Mon, 14 Oct 2013 12:06:38 +0000 (12:06 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 14 Oct 2013 12:06:38 +0000 (12:06 +0000)
2013-10-14  Richard Biener  <rguenther@suse.de>

* gimple.c (gimple_canonical_types, canonical_type_hash_cache,
iterative_hash_canonical_type, gimple_canonical_type_hash,
gimple_canonical_types_compatible_p, gimple_canonical_type_eq,
gimple_register_canonical_type, print_gimple_types_stats,
free_gimple_type_tables): Move to lto/lto.c
(gt-gimple.h): Do not include.
* gimple.h (gimple_register_canonical_type,
print_gimple_types_stats, free_gimple_type_tables): Remove.
* Makefile.in (GTFILES): Remove gimple.c.

lto/
* lto-lang.c (lto_init): Do not re-init canonical types here.
(lto_register_canonical_types): Move to ...
* lto.c (lto_register_canonical_types): ... here.
(gimple_canonical_types, canonical_type_hash_cache,
iterative_hash_canonical_type, gimple_canonical_type_hash,
gimple_canonical_types_compatible_p, gimple_canonical_type_eq,
gimple_register_canonical_type): Add canonical type merging machinery
moved from gimple.c.
(read_cgraph_and_symbols): Init and free canonical type tables
here.
(print_lto_report_1): Report canonical type table stats here.

From-SVN: r203521

gcc/ChangeLog
gcc/Makefile.in
gcc/gimple.c
gcc/gimple.h
gcc/lto/ChangeLog
gcc/lto/lto-lang.c
gcc/lto/lto.c

index 08c99309870babe98ae24d95ca95b1cb1c9f8f92..0a03d3ccb8112fd695d990b4ddb38919c75478fc 100644 (file)
@@ -1,3 +1,15 @@
+2013-10-14  Richard Biener  <rguenther@suse.de>
+
+       * gimple.c (gimple_canonical_types, canonical_type_hash_cache,
+       iterative_hash_canonical_type, gimple_canonical_type_hash,
+       gimple_canonical_types_compatible_p, gimple_canonical_type_eq,
+       gimple_register_canonical_type, print_gimple_types_stats,
+       free_gimple_type_tables): Move to lto/lto.c
+       (gt-gimple.h): Do not include.
+       * gimple.h (gimple_register_canonical_type,
+       print_gimple_types_stats, free_gimple_type_tables): Remove.
+       * Makefile.in (GTFILES): Remove gimple.c.
+
 2013-10-14  Travis Snoozy  <quandary@remstate.com>
 
        PR target/58716
index 4e396aab9d9347e81226b3a5896744250deedbd8..24c8fed8a64b09a42bace583dc40a3329c27d68e 100644 (file)
@@ -2240,7 +2240,7 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
   $(srcdir)/reg-stack.c $(srcdir)/cfgrtl.c \
   $(srcdir)/sdbout.c $(srcdir)/stor-layout.c \
   $(srcdir)/stringpool.c $(srcdir)/tree.c $(srcdir)/varasm.c \
-  $(srcdir)/gimple.h $(srcdir)/gimple.c \
+  $(srcdir)/gimple.h \
   $(srcdir)/tree-mudflap.c $(srcdir)/gimple-ssa.h \
   $(srcdir)/tree-ssanames.c $(srcdir)/tree-eh.c $(srcdir)/tree-ssa-address.c \
   $(srcdir)/tree-cfg.c \
index e0cc4ef92d1a18ebbeeae02d046c2e81a3db8795..a12dd67a118eaa994eab7a1791e6331f61bdb03e 100644 (file)
@@ -37,11 +37,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "demangle.h"
 #include "langhooks.h"
 
-/* Global canonical type table.  */
-static GTY((if_marked ("ggc_marked_p"), param_is (union tree_node)))
-  htab_t gimple_canonical_types;
-static GTY((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map)))
-  htab_t canonical_type_hash_cache;
 
 /* All the tuples have their operand vector (if present) at the very bottom
    of the structure.  Therefore, the offset required to find the
@@ -3099,458 +3094,6 @@ gimple_compare_field_offset (tree f1, tree f2)
   return false;
 }
 
-/* Returning a hash value for gimple type TYPE combined with VAL.
-
-   The hash value returned is equal for types considered compatible
-   by gimple_canonical_types_compatible_p.  */
-
-static hashval_t
-iterative_hash_canonical_type (tree type, hashval_t val)
-{
-  hashval_t v;
-  void **slot;
-  struct tree_int_map *mp, m;
-
-  m.base.from = type;
-  if ((slot = htab_find_slot (canonical_type_hash_cache, &m, NO_INSERT)))
-    return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, val);
-
-  /* Combine a few common features of types so that types are grouped into
-     smaller sets; when searching for existing matching types to merge,
-     only existing types having the same features as the new type will be
-     checked.  */
-  v = iterative_hash_hashval_t (TREE_CODE (type), 0);
-  v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v);
-  v = iterative_hash_hashval_t (TYPE_ALIGN (type), v);
-  v = iterative_hash_hashval_t (TYPE_MODE (type), v);
-
-  /* Incorporate common features of numerical types.  */
-  if (INTEGRAL_TYPE_P (type)
-      || SCALAR_FLOAT_TYPE_P (type)
-      || FIXED_POINT_TYPE_P (type)
-      || TREE_CODE (type) == OFFSET_TYPE
-      || POINTER_TYPE_P (type))
-    {
-      v = iterative_hash_hashval_t (TYPE_PRECISION (type), v);
-      v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
-    }
-
-  if (VECTOR_TYPE_P (type))
-    {
-      v = iterative_hash_hashval_t (TYPE_VECTOR_SUBPARTS (type), v);
-      v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
-    }
-
-  if (TREE_CODE (type) == COMPLEX_TYPE)
-    v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
-
-  /* For pointer and reference types, fold in information about the type
-     pointed to but do not recurse to the pointed-to type.  */
-  if (POINTER_TYPE_P (type))
-    {
-      v = iterative_hash_hashval_t (TYPE_REF_CAN_ALIAS_ALL (type), v);
-      v = iterative_hash_hashval_t (TYPE_ADDR_SPACE (TREE_TYPE (type)), v);
-      v = iterative_hash_hashval_t (TYPE_RESTRICT (type), v);
-      v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
-    }
-
-  /* For integer types hash only the string flag.  */
-  if (TREE_CODE (type) == INTEGER_TYPE)
-    v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
-
-  /* For array types hash the domain bounds and the string flag.  */
-  if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
-    {
-      v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
-      /* OMP lowering can introduce error_mark_node in place of
-        random local decls in types.  */
-      if (TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != error_mark_node)
-       v = iterative_hash_expr (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), v);
-      if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != error_mark_node)
-       v = iterative_hash_expr (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), v);
-    }
-
-  /* Recurse for aggregates with a single element type.  */
-  if (TREE_CODE (type) == ARRAY_TYPE
-      || TREE_CODE (type) == COMPLEX_TYPE
-      || TREE_CODE (type) == VECTOR_TYPE)
-    v = iterative_hash_canonical_type (TREE_TYPE (type), v);
-
-  /* Incorporate function return and argument types.  */
-  if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
-    {
-      unsigned na;
-      tree p;
-
-      /* For method types also incorporate their parent class.  */
-      if (TREE_CODE (type) == METHOD_TYPE)
-       v = iterative_hash_canonical_type (TYPE_METHOD_BASETYPE (type), v);
-
-      v = iterative_hash_canonical_type (TREE_TYPE (type), v);
-
-      for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
-       {
-         v = iterative_hash_canonical_type (TREE_VALUE (p), v);
-         na++;
-       }
-
-      v = iterative_hash_hashval_t (na, v);
-    }
-
-  if (RECORD_OR_UNION_TYPE_P (type))
-    {
-      unsigned nf;
-      tree f;
-
-      for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
-       if (TREE_CODE (f) == FIELD_DECL)
-         {
-           v = iterative_hash_canonical_type (TREE_TYPE (f), v);
-           nf++;
-         }
-
-      v = iterative_hash_hashval_t (nf, v);
-    }
-
-  /* Cache the just computed hash value.  */
-  mp = ggc_alloc_cleared_tree_int_map ();
-  mp->base.from = type;
-  mp->to = v;
-  /* As we recurse the hashtable may expand between looking up the
-     cached value (and not finding one) and here, so we have to
-     re-lookup the slot.  */
-  slot = htab_find_slot (canonical_type_hash_cache, &m, INSERT);
-  *slot = (void *) mp;
-
-  return iterative_hash_hashval_t (v, val);
-}
-
-static hashval_t
-gimple_canonical_type_hash (const void *p)
-{
-  if (canonical_type_hash_cache == NULL)
-    canonical_type_hash_cache = htab_create_ggc (512, tree_int_map_hash,
-                                                tree_int_map_eq, NULL);
-
-  return iterative_hash_canonical_type (CONST_CAST_TREE ((const_tree) p), 0);
-}
-
-
-
-
-/* The TYPE_CANONICAL merging machinery.  It should closely resemble
-   the middle-end types_compatible_p function.  It needs to avoid
-   claiming types are different for types that should be treated
-   the same with respect to TBAA.  Canonical types are also used
-   for IL consistency checks via the useless_type_conversion_p
-   predicate which does not handle all type kinds itself but falls
-   back to pointer-comparison of TYPE_CANONICAL for aggregates
-   for example.  */
-
-/* Return true iff T1 and T2 are structurally identical for what
-   TBAA is concerned.  */
-
-static bool
-gimple_canonical_types_compatible_p (tree t1, tree t2)
-{
-  /* Before starting to set up the SCC machinery handle simple cases.  */
-
-  /* Check first for the obvious case of pointer identity.  */
-  if (t1 == t2)
-    return true;
-
-  /* Check that we have two types to compare.  */
-  if (t1 == NULL_TREE || t2 == NULL_TREE)
-    return false;
-
-  /* If the types have been previously registered and found equal
-     they still are.  */
-  if (TYPE_CANONICAL (t1)
-      && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2))
-    return true;
-
-  /* Can't be the same type if the types don't have the same code.  */
-  if (TREE_CODE (t1) != TREE_CODE (t2))
-    return false;
-
-  if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2))
-    return false;
-
-  /* Qualifiers do not matter for canonical type comparison purposes.  */
-
-  /* Void types and nullptr types are always the same.  */
-  if (TREE_CODE (t1) == VOID_TYPE
-      || TREE_CODE (t1) == NULLPTR_TYPE)
-    return true;
-
-  /* Can't be the same type if they have different alignment, or mode.  */
-  if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
-      || TYPE_MODE (t1) != TYPE_MODE (t2))
-    return false;
-
-  /* Non-aggregate types can be handled cheaply.  */
-  if (INTEGRAL_TYPE_P (t1)
-      || SCALAR_FLOAT_TYPE_P (t1)
-      || FIXED_POINT_TYPE_P (t1)
-      || TREE_CODE (t1) == VECTOR_TYPE
-      || TREE_CODE (t1) == COMPLEX_TYPE
-      || TREE_CODE (t1) == OFFSET_TYPE
-      || POINTER_TYPE_P (t1))
-    {
-      /* Can't be the same type if they have different sign or precision.  */
-      if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
-         || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
-       return false;
-
-      if (TREE_CODE (t1) == INTEGER_TYPE
-         && TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))
-       return false;
-
-      /* For canonical type comparisons we do not want to build SCCs
-        so we cannot compare pointed-to types.  But we can, for now,
-        require the same pointed-to type kind and match what
-        useless_type_conversion_p would do.  */
-      if (POINTER_TYPE_P (t1))
-       {
-         /* If the two pointers have different ref-all attributes,
-            they can't be the same type.  */
-         if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
-           return false;
-
-         if (TYPE_ADDR_SPACE (TREE_TYPE (t1))
-             != TYPE_ADDR_SPACE (TREE_TYPE (t2)))
-           return false;
-
-         if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2))
-           return false;
-
-         if (TREE_CODE (TREE_TYPE (t1)) != TREE_CODE (TREE_TYPE (t2)))
-           return false;
-       }
-
-      /* Tail-recurse to components.  */
-      if (TREE_CODE (t1) == VECTOR_TYPE
-         || TREE_CODE (t1) == COMPLEX_TYPE)
-       return gimple_canonical_types_compatible_p (TREE_TYPE (t1),
-                                                   TREE_TYPE (t2));
-
-      return true;
-    }
-
-  /* Do type-specific comparisons.  */
-  switch (TREE_CODE (t1))
-    {
-    case ARRAY_TYPE:
-      /* Array types are the same if the element types are the same and
-        the number of elements are the same.  */
-      if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))
-         || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
-         || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
-       return false;
-      else
-       {
-         tree i1 = TYPE_DOMAIN (t1);
-         tree i2 = TYPE_DOMAIN (t2);
-
-         /* For an incomplete external array, the type domain can be
-            NULL_TREE.  Check this condition also.  */
-         if (i1 == NULL_TREE && i2 == NULL_TREE)
-           return true;
-         else if (i1 == NULL_TREE || i2 == NULL_TREE)
-           return false;
-         else
-           {
-             tree min1 = TYPE_MIN_VALUE (i1);
-             tree min2 = TYPE_MIN_VALUE (i2);
-             tree max1 = TYPE_MAX_VALUE (i1);
-             tree max2 = TYPE_MAX_VALUE (i2);
-
-             /* The minimum/maximum values have to be the same.  */
-             if ((min1 == min2
-                  || (min1 && min2
-                      && ((TREE_CODE (min1) == PLACEHOLDER_EXPR
-                           && TREE_CODE (min2) == PLACEHOLDER_EXPR)
-                          || operand_equal_p (min1, min2, 0))))
-                 && (max1 == max2
-                     || (max1 && max2
-                         && ((TREE_CODE (max1) == PLACEHOLDER_EXPR
-                              && TREE_CODE (max2) == PLACEHOLDER_EXPR)
-                             || operand_equal_p (max1, max2, 0)))))
-               return true;
-             else
-               return false;
-           }
-       }
-
-    case METHOD_TYPE:
-    case FUNCTION_TYPE:
-      /* Function types are the same if the return type and arguments types
-        are the same.  */
-      if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
-       return false;
-
-      if (!comp_type_attributes (t1, t2))
-       return false;
-
-      if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
-       return true;
-      else
-       {
-         tree parms1, parms2;
-
-         for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
-              parms1 && parms2;
-              parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
-           {
-             if (!gimple_canonical_types_compatible_p
-                    (TREE_VALUE (parms1), TREE_VALUE (parms2)))
-               return false;
-           }
-
-         if (parms1 || parms2)
-           return false;
-
-         return true;
-       }
-
-    case RECORD_TYPE:
-    case UNION_TYPE:
-    case QUAL_UNION_TYPE:
-      {
-       tree f1, f2;
-
-       /* For aggregate types, all the fields must be the same.  */
-       for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
-            f1 || f2;
-            f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
-         {
-           /* Skip non-fields.  */
-           while (f1 && TREE_CODE (f1) != FIELD_DECL)
-             f1 = TREE_CHAIN (f1);
-           while (f2 && TREE_CODE (f2) != FIELD_DECL)
-             f2 = TREE_CHAIN (f2);
-           if (!f1 || !f2)
-             break;
-           /* The fields must have the same name, offset and type.  */
-           if (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
-               || !gimple_compare_field_offset (f1, f2)
-               || !gimple_canonical_types_compatible_p
-                     (TREE_TYPE (f1), TREE_TYPE (f2)))
-             return false;
-         }
-
-       /* If one aggregate has more fields than the other, they
-          are not the same.  */
-       if (f1 || f2)
-         return false;
-
-       return true;
-      }
-
-    default:
-      gcc_unreachable ();
-    }
-}
-
-
-/* Returns nonzero if P1 and P2 are equal.  */
-
-static int
-gimple_canonical_type_eq (const void *p1, const void *p2)
-{
-  const_tree t1 = (const_tree) p1;
-  const_tree t2 = (const_tree) p2;
-  return gimple_canonical_types_compatible_p (CONST_CAST_TREE (t1),
-                                             CONST_CAST_TREE (t2));
-}
-
-/* Register type T in the global type table gimple_types.
-   If another type T', compatible with T, already existed in
-   gimple_types then return T', otherwise return T.  This is used by
-   LTO to merge identical types read from different TUs.
-
-   ???  This merging does not exactly match how the tree.c middle-end
-   functions will assign TYPE_CANONICAL when new types are created
-   during optimization (which at least happens for pointer and array
-   types).  */
-
-tree
-gimple_register_canonical_type (tree t)
-{
-  void **slot;
-
-  gcc_assert (TYPE_P (t));
-
-  if (TYPE_CANONICAL (t))
-    return TYPE_CANONICAL (t);
-
-  if (gimple_canonical_types == NULL)
-    gimple_canonical_types = htab_create_ggc (16381, gimple_canonical_type_hash,
-                                             gimple_canonical_type_eq, 0);
-
-  slot = htab_find_slot (gimple_canonical_types, t, INSERT);
-  if (*slot
-      && *(tree *)slot != t)
-    {
-      tree new_type = (tree) *((tree *) slot);
-
-      TYPE_CANONICAL (t) = new_type;
-      t = new_type;
-    }
-  else
-    {
-      TYPE_CANONICAL (t) = t;
-      *slot = (void *) t;
-    }
-
-  return t;
-}
-
-
-/* Show statistics on references to the global type table gimple_types.  */
-
-void
-print_gimple_types_stats (const char *pfx)
-{
-  if (gimple_canonical_types)
-    fprintf (stderr, "[%s] GIMPLE canonical type table: size %ld, "
-            "%ld elements, %ld searches, %ld collisions (ratio: %f)\n", pfx,
-            (long) htab_size (gimple_canonical_types),
-            (long) htab_elements (gimple_canonical_types),
-            (long) gimple_canonical_types->searches,
-            (long) gimple_canonical_types->collisions,
-            htab_collisions (gimple_canonical_types));
-  else
-    fprintf (stderr, "[%s] GIMPLE canonical type table is empty\n", pfx);
-  if (canonical_type_hash_cache)
-    fprintf (stderr, "[%s] GIMPLE canonical type hash table: size %ld, "
-            "%ld elements, %ld searches, %ld collisions (ratio: %f)\n", pfx,
-            (long) htab_size (canonical_type_hash_cache),
-            (long) htab_elements (canonical_type_hash_cache),
-            (long) canonical_type_hash_cache->searches,
-            (long) canonical_type_hash_cache->collisions,
-            htab_collisions (canonical_type_hash_cache));
-  else
-    fprintf (stderr, "[%s] GIMPLE canonical type hash table is empty\n", pfx);
-}
-
-/* Free the gimple type hashtables used for LTO type merging.  */
-
-void
-free_gimple_type_tables (void)
-{
-  if (gimple_canonical_types)
-    {
-      htab_delete (gimple_canonical_types);
-      gimple_canonical_types = NULL;
-    }
-  if (canonical_type_hash_cache)
-    {
-      htab_delete (canonical_type_hash_cache);
-      canonical_type_hash_cache = NULL;
-    }
-}
-
 
 /* Return a type the same as TYPE except unsigned or
    signed according to UNSIGNEDP.  */
@@ -4520,5 +4063,3 @@ nonfreeing_call_p (gimple call)
 
   return false;
 }
-
-#include "gt-gimple.h"
index 822274a29f06009a55b62a3e6c8560fa4b3fb731..c0c19ce995a9c29a2a398a650aa6ddecca4f2fa6 100644 (file)
@@ -891,9 +891,6 @@ extern bool is_gimple_builtin_call (gimple stmt);
 
 extern void recalculate_side_effects (tree);
 extern bool gimple_compare_field_offset (tree, tree);
-extern tree gimple_register_canonical_type (tree);
-extern void print_gimple_types_stats (const char *);
-extern void free_gimple_type_tables (void);
 extern tree gimple_unsigned_type (tree);
 extern tree gimple_signed_type (tree);
 extern alias_set_type gimple_get_alias_set (tree);
index eaa69306f6726c144e141b665154aff0a4442263..58474af57ca6243950ebd1008c4854e628c28f6f 100644 (file)
@@ -1,3 +1,17 @@
+2013-10-14  Richard Biener  <rguenther@suse.de>
+
+       * lto-lang.c (lto_init): Do not re-init canonical types here.
+       (lto_register_canonical_types): Move to ...
+       * lto.c (lto_register_canonical_types): ... here.
+       (gimple_canonical_types, canonical_type_hash_cache,
+       iterative_hash_canonical_type, gimple_canonical_type_hash,
+       gimple_canonical_types_compatible_p, gimple_canonical_type_eq,
+       gimple_register_canonical_type): Add canonical type merging machinery
+       moved from gimple.c.
+       (read_cgraph_and_symbols): Init and free canonical type tables
+       here.
+       (print_lto_report_1): Report canonical type table stats here.
+
 2013-10-11  Jakub Jelinek  <jakub@redhat.com>
 
        * lto-lang.c (DEF_FUNCTION_TYPE_8): Define.
index 79cc5609994d76cc808eda6cc318988fe2fe29e8..0fa0fc9a4380337d6f0c8acfffe025a4172e0e3f 100644 (file)
@@ -1134,31 +1134,11 @@ lto_build_c_type_nodes (void)
   pid_type_node = integer_type_node;
 }
 
-/* Re-compute TYPE_CANONICAL for NODE and related types.  */
-
-static void
-lto_register_canonical_types (tree node)
-{
-  if (!node
-      || !TYPE_P (node))
-    return;
-
-  TYPE_CANONICAL (node) = NULL_TREE;
-  TYPE_CANONICAL (node) = gimple_register_canonical_type (node);
-
-  if (POINTER_TYPE_P (node)
-      || TREE_CODE (node) == COMPLEX_TYPE
-      || TREE_CODE (node) == ARRAY_TYPE)
-    lto_register_canonical_types (TREE_TYPE (node));
-}
-
 /* Perform LTO-specific initialization.  */
 
 static bool
 lto_init (void)
 {
-  unsigned i;
-
   /* We need to generate LTO if running in WPA mode.  */
   flag_generate_lto = flag_wpa;
 
@@ -1226,17 +1206,6 @@ lto_init (void)
   NAME_TYPE (boolean_type_node, "bool");
 #undef NAME_TYPE
 
-  /* Register the common node types with the canonical type machinery so
-     we properly share alias-sets across languages and TUs.  Do not
-     expose the common nodes as type merge target - those that should be
-     are already exposed so by pre-loading the LTO streamer caches.  */
-  for (i = 0; i < itk_none; ++i)
-    lto_register_canonical_types (integer_types[i]);
-  /* The sizetypes are not used to access data so we do not need to
-     do anything about them.  */
-  for (i = 0; i < TI_MAX; ++i)
-    lto_register_canonical_types (global_trees[i]);
-
   /* Initialize LTO-specific data structures.  */
   vec_alloc (lto_global_var_decls, 256);
   in_lto_p = true;
index 470f3c1d7a7ed2b1fb64c6baf1916fdb9dd75740..f01b37521fd46fb658f83db45734784ae14dd91e 100644 (file)
@@ -254,6 +254,427 @@ lto_read_in_decl_state (struct data_in *data_in, const uint32_t *data,
 }
 
 
+/* Global canonical type table.  */
+static GTY((if_marked ("ggc_marked_p"), param_is (union tree_node)))
+  htab_t gimple_canonical_types;
+static GTY((if_marked ("tree_int_map_marked_p"), param_is (struct tree_int_map)))
+  htab_t canonical_type_hash_cache;
+
+/* Returning a hash value for gimple type TYPE combined with VAL.
+
+   The hash value returned is equal for types considered compatible
+   by gimple_canonical_types_compatible_p.  */
+
+static hashval_t
+iterative_hash_canonical_type (tree type, hashval_t val)
+{
+  hashval_t v;
+  void **slot;
+  struct tree_int_map *mp, m;
+
+  m.base.from = type;
+  if ((slot = htab_find_slot (canonical_type_hash_cache, &m, NO_INSERT)))
+    return iterative_hash_hashval_t (((struct tree_int_map *) *slot)->to, val);
+
+  /* Combine a few common features of types so that types are grouped into
+     smaller sets; when searching for existing matching types to merge,
+     only existing types having the same features as the new type will be
+     checked.  */
+  v = iterative_hash_hashval_t (TREE_CODE (type), 0);
+  v = iterative_hash_hashval_t (TREE_ADDRESSABLE (type), v);
+  v = iterative_hash_hashval_t (TYPE_ALIGN (type), v);
+  v = iterative_hash_hashval_t (TYPE_MODE (type), v);
+
+  /* Incorporate common features of numerical types.  */
+  if (INTEGRAL_TYPE_P (type)
+      || SCALAR_FLOAT_TYPE_P (type)
+      || FIXED_POINT_TYPE_P (type)
+      || TREE_CODE (type) == OFFSET_TYPE
+      || POINTER_TYPE_P (type))
+    {
+      v = iterative_hash_hashval_t (TYPE_PRECISION (type), v);
+      v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
+    }
+
+  if (VECTOR_TYPE_P (type))
+    {
+      v = iterative_hash_hashval_t (TYPE_VECTOR_SUBPARTS (type), v);
+      v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
+    }
+
+  if (TREE_CODE (type) == COMPLEX_TYPE)
+    v = iterative_hash_hashval_t (TYPE_UNSIGNED (type), v);
+
+  /* For pointer and reference types, fold in information about the type
+     pointed to but do not recurse to the pointed-to type.  */
+  if (POINTER_TYPE_P (type))
+    {
+      v = iterative_hash_hashval_t (TYPE_REF_CAN_ALIAS_ALL (type), v);
+      v = iterative_hash_hashval_t (TYPE_ADDR_SPACE (TREE_TYPE (type)), v);
+      v = iterative_hash_hashval_t (TYPE_RESTRICT (type), v);
+      v = iterative_hash_hashval_t (TREE_CODE (TREE_TYPE (type)), v);
+    }
+
+  /* For integer types hash only the string flag.  */
+  if (TREE_CODE (type) == INTEGER_TYPE)
+    v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
+
+  /* For array types hash the domain bounds and the string flag.  */
+  if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
+    {
+      v = iterative_hash_hashval_t (TYPE_STRING_FLAG (type), v);
+      /* OMP lowering can introduce error_mark_node in place of
+        random local decls in types.  */
+      if (TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != error_mark_node)
+       v = iterative_hash_expr (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), v);
+      if (TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != error_mark_node)
+       v = iterative_hash_expr (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), v);
+    }
+
+  /* Recurse for aggregates with a single element type.  */
+  if (TREE_CODE (type) == ARRAY_TYPE
+      || TREE_CODE (type) == COMPLEX_TYPE
+      || TREE_CODE (type) == VECTOR_TYPE)
+    v = iterative_hash_canonical_type (TREE_TYPE (type), v);
+
+  /* Incorporate function return and argument types.  */
+  if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
+    {
+      unsigned na;
+      tree p;
+
+      /* For method types also incorporate their parent class.  */
+      if (TREE_CODE (type) == METHOD_TYPE)
+       v = iterative_hash_canonical_type (TYPE_METHOD_BASETYPE (type), v);
+
+      v = iterative_hash_canonical_type (TREE_TYPE (type), v);
+
+      for (p = TYPE_ARG_TYPES (type), na = 0; p; p = TREE_CHAIN (p))
+       {
+         v = iterative_hash_canonical_type (TREE_VALUE (p), v);
+         na++;
+       }
+
+      v = iterative_hash_hashval_t (na, v);
+    }
+
+  if (RECORD_OR_UNION_TYPE_P (type))
+    {
+      unsigned nf;
+      tree f;
+
+      for (f = TYPE_FIELDS (type), nf = 0; f; f = TREE_CHAIN (f))
+       if (TREE_CODE (f) == FIELD_DECL)
+         {
+           v = iterative_hash_canonical_type (TREE_TYPE (f), v);
+           nf++;
+         }
+
+      v = iterative_hash_hashval_t (nf, v);
+    }
+
+  /* Cache the just computed hash value.  */
+  mp = ggc_alloc_cleared_tree_int_map ();
+  mp->base.from = type;
+  mp->to = v;
+  /* As we recurse the hashtable may expand between looking up the
+     cached value (and not finding one) and here, so we have to
+     re-lookup the slot.  */
+  slot = htab_find_slot (canonical_type_hash_cache, &m, INSERT);
+  *slot = (void *) mp;
+
+  return iterative_hash_hashval_t (v, val);
+}
+
+static hashval_t
+gimple_canonical_type_hash (const void *p)
+{
+  return iterative_hash_canonical_type (CONST_CAST_TREE ((const_tree) p), 0);
+}
+
+
+/* The TYPE_CANONICAL merging machinery.  It should closely resemble
+   the middle-end types_compatible_p function.  It needs to avoid
+   claiming types are different for types that should be treated
+   the same with respect to TBAA.  Canonical types are also used
+   for IL consistency checks via the useless_type_conversion_p
+   predicate which does not handle all type kinds itself but falls
+   back to pointer-comparison of TYPE_CANONICAL for aggregates
+   for example.  */
+
+/* Return true iff T1 and T2 are structurally identical for what
+   TBAA is concerned.  */
+
+static bool
+gimple_canonical_types_compatible_p (tree t1, tree t2)
+{
+  /* Before starting to set up the SCC machinery handle simple cases.  */
+
+  /* Check first for the obvious case of pointer identity.  */
+  if (t1 == t2)
+    return true;
+
+  /* Check that we have two types to compare.  */
+  if (t1 == NULL_TREE || t2 == NULL_TREE)
+    return false;
+
+  /* If the types have been previously registered and found equal
+     they still are.  */
+  if (TYPE_CANONICAL (t1)
+      && TYPE_CANONICAL (t1) == TYPE_CANONICAL (t2))
+    return true;
+
+  /* Can't be the same type if the types don't have the same code.  */
+  if (TREE_CODE (t1) != TREE_CODE (t2))
+    return false;
+
+  if (TREE_ADDRESSABLE (t1) != TREE_ADDRESSABLE (t2))
+    return false;
+
+  /* Qualifiers do not matter for canonical type comparison purposes.  */
+
+  /* Void types and nullptr types are always the same.  */
+  if (TREE_CODE (t1) == VOID_TYPE
+      || TREE_CODE (t1) == NULLPTR_TYPE)
+    return true;
+
+  /* Can't be the same type if they have different alignment, or mode.  */
+  if (TYPE_ALIGN (t1) != TYPE_ALIGN (t2)
+      || TYPE_MODE (t1) != TYPE_MODE (t2))
+    return false;
+
+  /* Non-aggregate types can be handled cheaply.  */
+  if (INTEGRAL_TYPE_P (t1)
+      || SCALAR_FLOAT_TYPE_P (t1)
+      || FIXED_POINT_TYPE_P (t1)
+      || TREE_CODE (t1) == VECTOR_TYPE
+      || TREE_CODE (t1) == COMPLEX_TYPE
+      || TREE_CODE (t1) == OFFSET_TYPE
+      || POINTER_TYPE_P (t1))
+    {
+      /* Can't be the same type if they have different sign or precision.  */
+      if (TYPE_PRECISION (t1) != TYPE_PRECISION (t2)
+         || TYPE_UNSIGNED (t1) != TYPE_UNSIGNED (t2))
+       return false;
+
+      if (TREE_CODE (t1) == INTEGER_TYPE
+         && TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2))
+       return false;
+
+      /* For canonical type comparisons we do not want to build SCCs
+        so we cannot compare pointed-to types.  But we can, for now,
+        require the same pointed-to type kind and match what
+        useless_type_conversion_p would do.  */
+      if (POINTER_TYPE_P (t1))
+       {
+         /* If the two pointers have different ref-all attributes,
+            they can't be the same type.  */
+         if (TYPE_REF_CAN_ALIAS_ALL (t1) != TYPE_REF_CAN_ALIAS_ALL (t2))
+           return false;
+
+         if (TYPE_ADDR_SPACE (TREE_TYPE (t1))
+             != TYPE_ADDR_SPACE (TREE_TYPE (t2)))
+           return false;
+
+         if (TYPE_RESTRICT (t1) != TYPE_RESTRICT (t2))
+           return false;
+
+         if (TREE_CODE (TREE_TYPE (t1)) != TREE_CODE (TREE_TYPE (t2)))
+           return false;
+       }
+
+      /* Tail-recurse to components.  */
+      if (TREE_CODE (t1) == VECTOR_TYPE
+         || TREE_CODE (t1) == COMPLEX_TYPE)
+       return gimple_canonical_types_compatible_p (TREE_TYPE (t1),
+                                                   TREE_TYPE (t2));
+
+      return true;
+    }
+
+  /* Do type-specific comparisons.  */
+  switch (TREE_CODE (t1))
+    {
+    case ARRAY_TYPE:
+      /* Array types are the same if the element types are the same and
+        the number of elements are the same.  */
+      if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))
+         || TYPE_STRING_FLAG (t1) != TYPE_STRING_FLAG (t2)
+         || TYPE_NONALIASED_COMPONENT (t1) != TYPE_NONALIASED_COMPONENT (t2))
+       return false;
+      else
+       {
+         tree i1 = TYPE_DOMAIN (t1);
+         tree i2 = TYPE_DOMAIN (t2);
+
+         /* For an incomplete external array, the type domain can be
+            NULL_TREE.  Check this condition also.  */
+         if (i1 == NULL_TREE && i2 == NULL_TREE)
+           return true;
+         else if (i1 == NULL_TREE || i2 == NULL_TREE)
+           return false;
+         else
+           {
+             tree min1 = TYPE_MIN_VALUE (i1);
+             tree min2 = TYPE_MIN_VALUE (i2);
+             tree max1 = TYPE_MAX_VALUE (i1);
+             tree max2 = TYPE_MAX_VALUE (i2);
+
+             /* The minimum/maximum values have to be the same.  */
+             if ((min1 == min2
+                  || (min1 && min2
+                      && ((TREE_CODE (min1) == PLACEHOLDER_EXPR
+                           && TREE_CODE (min2) == PLACEHOLDER_EXPR)
+                          || operand_equal_p (min1, min2, 0))))
+                 && (max1 == max2
+                     || (max1 && max2
+                         && ((TREE_CODE (max1) == PLACEHOLDER_EXPR
+                              && TREE_CODE (max2) == PLACEHOLDER_EXPR)
+                             || operand_equal_p (max1, max2, 0)))))
+               return true;
+             else
+               return false;
+           }
+       }
+
+    case METHOD_TYPE:
+    case FUNCTION_TYPE:
+      /* Function types are the same if the return type and arguments types
+        are the same.  */
+      if (!gimple_canonical_types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
+       return false;
+
+      if (!comp_type_attributes (t1, t2))
+       return false;
+
+      if (TYPE_ARG_TYPES (t1) == TYPE_ARG_TYPES (t2))
+       return true;
+      else
+       {
+         tree parms1, parms2;
+
+         for (parms1 = TYPE_ARG_TYPES (t1), parms2 = TYPE_ARG_TYPES (t2);
+              parms1 && parms2;
+              parms1 = TREE_CHAIN (parms1), parms2 = TREE_CHAIN (parms2))
+           {
+             if (!gimple_canonical_types_compatible_p
+                    (TREE_VALUE (parms1), TREE_VALUE (parms2)))
+               return false;
+           }
+
+         if (parms1 || parms2)
+           return false;
+
+         return true;
+       }
+
+    case RECORD_TYPE:
+    case UNION_TYPE:
+    case QUAL_UNION_TYPE:
+      {
+       tree f1, f2;
+
+       /* For aggregate types, all the fields must be the same.  */
+       for (f1 = TYPE_FIELDS (t1), f2 = TYPE_FIELDS (t2);
+            f1 || f2;
+            f1 = TREE_CHAIN (f1), f2 = TREE_CHAIN (f2))
+         {
+           /* Skip non-fields.  */
+           while (f1 && TREE_CODE (f1) != FIELD_DECL)
+             f1 = TREE_CHAIN (f1);
+           while (f2 && TREE_CODE (f2) != FIELD_DECL)
+             f2 = TREE_CHAIN (f2);
+           if (!f1 || !f2)
+             break;
+           /* The fields must have the same name, offset and type.  */
+           if (DECL_NONADDRESSABLE_P (f1) != DECL_NONADDRESSABLE_P (f2)
+               || !gimple_compare_field_offset (f1, f2)
+               || !gimple_canonical_types_compatible_p
+                     (TREE_TYPE (f1), TREE_TYPE (f2)))
+             return false;
+         }
+
+       /* If one aggregate has more fields than the other, they
+          are not the same.  */
+       if (f1 || f2)
+         return false;
+
+       return true;
+      }
+
+    default:
+      gcc_unreachable ();
+    }
+}
+
+
+/* Returns nonzero if P1 and P2 are equal.  */
+
+static int
+gimple_canonical_type_eq (const void *p1, const void *p2)
+{
+  const_tree t1 = (const_tree) p1;
+  const_tree t2 = (const_tree) p2;
+  return gimple_canonical_types_compatible_p (CONST_CAST_TREE (t1),
+                                             CONST_CAST_TREE (t2));
+}
+
+/* Register type T in the global type table gimple_types.
+   If another type T', compatible with T, already existed in
+   gimple_types then return T', otherwise return T.  This is used by
+   LTO to merge identical types read from different TUs.
+
+   ???  This merging does not exactly match how the tree.c middle-end
+   functions will assign TYPE_CANONICAL when new types are created
+   during optimization (which at least happens for pointer and array
+   types).  */
+
+static tree
+gimple_register_canonical_type (tree t)
+{
+  void **slot;
+
+  gcc_assert (TYPE_P (t));
+
+  if (TYPE_CANONICAL (t))
+    return TYPE_CANONICAL (t);
+
+  slot = htab_find_slot (gimple_canonical_types, t, INSERT);
+  if (*slot
+      && *(tree *)slot != t)
+    {
+      tree new_type = (tree) *((tree *) slot);
+
+      TYPE_CANONICAL (t) = new_type;
+      t = new_type;
+    }
+  else
+    {
+      TYPE_CANONICAL (t) = t;
+      *slot = (void *) t;
+    }
+
+  return t;
+}
+
+/* Re-compute TYPE_CANONICAL for NODE and related types.  */
+
+static void
+lto_register_canonical_types (tree node)
+{
+  if (!node
+      || !TYPE_P (node))
+    return;
+
+  TYPE_CANONICAL (node) = NULL_TREE;
+  TYPE_CANONICAL (node) = gimple_register_canonical_type (node);
+
+  if (POINTER_TYPE_P (node)
+      || TREE_CODE (node) == COMPLEX_TYPE
+      || TREE_CODE (node) == ARRAY_TYPE)
+    lto_register_canonical_types (TREE_TYPE (node));
+}
+
 
 /* ???  Old hashing and merging code follows, we keep it for statistics
    purposes for now.  */
@@ -3398,6 +3819,10 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
     }
   cgraph_state = CGRAPH_LTO_STREAMING;
 
+  canonical_type_hash_cache = htab_create_ggc (512, tree_int_map_hash,
+                                              tree_int_map_eq, NULL);
+  gimple_canonical_types = htab_create_ggc (16381, gimple_canonical_type_hash,
+                                           gimple_canonical_type_eq, 0);
   type_hash_cache = htab_create_ggc (512, tree_int_map_hash,
                                     tree_int_map_eq, NULL);
   type_pair_cache = XCNEWVEC (struct type_pair_d, GIMPLE_TYPE_PAIR_SIZE);
@@ -3405,6 +3830,17 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
   gcc_obstack_init (&tree_scc_hash_obstack);
   tree_scc_hash.create (4096);
 
+  /* Register the common node types with the canonical type machinery so
+     we properly share alias-sets across languages and TUs.  Do not
+     expose the common nodes as type merge target - those that should be
+     are already exposed so by pre-loading the LTO streamer caches.  */
+  for (i = 0; i < itk_none; ++i)
+    lto_register_canonical_types (integer_types[i]);
+  /* The sizetypes are not used to access data so we do not need to
+     do anything about them.  */
+  for (i = 0; i < TI_MAX; ++i)
+    lto_register_canonical_types (global_trees[i]);
+
   if (!quiet_flag)
     fprintf (stderr, "Reading object files:");
 
@@ -3459,7 +3895,10 @@ read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
   type_pair_cache = NULL;
   tree_scc_hash.dispose ();
   obstack_free (&tree_scc_hash_obstack, NULL);
-  free_gimple_type_tables ();
+  htab_delete (gimple_canonical_types);
+  gimple_canonical_types = NULL;
+  htab_delete (canonical_type_hash_cache);
+  canonical_type_hash_cache = NULL;
   ggc_collect ();
 
   /* Set the hooks so that all of the ipa passes can read in their data.  */
@@ -3663,9 +4102,22 @@ print_lto_report_1 (void)
               pfx, num_not_merged_types, num_not_merged_types_in_same_scc,
               num_not_merged_types_trees,
               num_not_merged_types_in_same_scc_trees);
+      fprintf (stderr, "[%s] GIMPLE canonical type table: size %ld, "
+              "%ld elements, %ld searches, %ld collisions (ratio: %f)\n", pfx,
+              (long) htab_size (gimple_canonical_types),
+              (long) htab_elements (gimple_canonical_types),
+              (long) gimple_canonical_types->searches,
+              (long) gimple_canonical_types->collisions,
+              htab_collisions (gimple_canonical_types));
+      fprintf (stderr, "[%s] GIMPLE canonical type hash table: size %ld, "
+              "%ld elements, %ld searches, %ld collisions (ratio: %f)\n", pfx,
+              (long) htab_size (canonical_type_hash_cache),
+              (long) htab_elements (canonical_type_hash_cache),
+              (long) canonical_type_hash_cache->searches,
+              (long) canonical_type_hash_cache->collisions,
+              htab_collisions (canonical_type_hash_cache));
     }
 
-  print_gimple_types_stats (pfx);
   print_lto_report (pfx);
 }