On Wed, Nov 20, 2019 at 07:46:13PM -0500, Jason Merrill wrote:
> > If decl_tree_cache_map will be needed in more than one spot, I'll probably
> > need to move it to some generic header.
> 
> Most of them probably need it, for code that uses the relevant features.
> Except debug_type_map, which probably needs to use TYPE_UID.
> 
> Or we might make default_hash_traits<tree> use DECL_UID for decls and
> TYPE_UID for types even if it doesn't do the more complex analysis of
> tree_operand_hash.

Finding out what is a type and what is decl (and what to do with rest?)
at runtime would be more costly than necessary.

The following updated patch moves the decl_tree_cache_map to tree.h and
adds there type_tree_cache_map too and uses it in all the tree_cache_map
spots in the C++ FE.
tree-hash-traits.h can't be included from tree.h, because operand_equal_p is
declared elsewhere, so instead this patch moves some of the
tree-hash-traits.h traits from that header to tree.h.  I could move there
just tree_decl_hash if moving the other two doesn't look right to you.

Bootstrapped/regtested on x86_64-linux and i686-linux, additionally tested
by compiling stdc++.h as PCH with -std=c++2a and using it.  Ok for trunk?

2019-11-22  Jakub Jelinek  <ja...@redhat.com>

        PR c++/92458
        * tree-hash-traits.h (tree_decl_hash, tree_ssa_name_hash,
        tree_hash): Move to ...
        * tree.h (tree_decl_hash, tree_ssa_name_hash, tree_hash): ... here.
        (struct decl_tree_cache_traits, struct type_tree_cache_traits): New
        types.
        (decl_tree_cache_map, tree_tree_cache_map): New typedefs.

        * init.c (nsdmi_inst): Change type to
        decl_tree_cache_map * from tree_cache_map *.
        * constraint.cc (decl_constraints): Likewise.
        * decl.c (get_tuple_decomp_init): Likewise.
        * pt.c (defarg_inst, explicit_specifier_map): Likewise.
        (tsubst_default_argument, store_explicit_specifier): Use
        decl_tree_cache_map::create_ggc rather than
        tree_cache_map::create_ggc.
        * cp-objcp-common.c (debug_type_map): Change type to
        type_tree_cache_map * from tree_cache_map *.

        * g++.dg/pch/pr92458.C: New test.
        * g++.dg/pch/pr92458.Hs: New test.

--- gcc/tree-hash-traits.h.jj   2019-01-01 12:37:16.902979134 +0100
+++ gcc/tree-hash-traits.h      2019-11-22 12:00:01.538725844 +0100
@@ -41,44 +41,4 @@ tree_operand_hash::equal (const value_ty
   return operand_equal_p (t1, t2, 0);
 }
 
-/* Hasher for tree decls.  Pointer equality is enough here, but the DECL_UID
-   is a better hash than the pointer value and gives a predictable traversal
-   order.  */
-struct tree_decl_hash : ggc_ptr_hash <tree_node>
-{
-  static inline hashval_t hash (tree);
-};
-
-inline hashval_t
-tree_decl_hash::hash (tree t)
-{
-  return DECL_UID (t);
-}
-
-/* Hash for SSA_NAMEs in the same function.  Pointer equality is enough
-   here, but the SSA_NAME_VERSION is a better hash than the pointer
-   value and gives a predictable traversal order.  */
-struct tree_ssa_name_hash : ggc_ptr_hash <tree_node>
-{
-  static inline hashval_t hash (tree);
-};
-
-inline hashval_t
-tree_ssa_name_hash::hash (tree t)
-{
-  return SSA_NAME_VERSION (t);
-}
-
-/* Hasher for general trees, based on their TREE_HASH.  */
-struct tree_hash : ggc_ptr_hash <tree_node>
-{
-  static hashval_t hash (tree);
-};
-
-inline hashval_t
-tree_hash::hash (tree t)
-{
-  return TREE_HASH (t);
-}
-
 #endif
--- gcc/tree.h.jj       2019-11-15 00:37:26.293070143 +0100
+++ gcc/tree.h  2019-11-22 12:00:17.479478830 +0100
@@ -5351,6 +5351,58 @@ struct tree_decl_map_cache_hasher : ggc_
 #define tree_vec_map_hash tree_decl_map_hash
 #define tree_vec_map_marked_p tree_map_base_marked_p
 
+/* Hasher for tree decls.  Pointer equality is enough here, but the DECL_UID
+   is a better hash than the pointer value and gives a predictable traversal
+   order.  Additionally it can be used across PCH save/restore.  */
+struct tree_decl_hash : ggc_ptr_hash <tree_node>
+{
+  static inline hashval_t hash (tree);
+};
+
+inline hashval_t
+tree_decl_hash::hash (tree t)
+{
+  return DECL_UID (t);
+}
+
+/* Similarly for types.  Uses TYPE_UID as hash function.  */
+struct tree_type_hash : ggc_ptr_hash <tree_node>
+{
+  static inline hashval_t hash (tree);
+};
+
+inline hashval_t
+tree_type_hash::hash (tree t)
+{
+  return TYPE_UID (t);
+}
+
+/* Hash for SSA_NAMEs in the same function.  Pointer equality is enough
+   here, but the SSA_NAME_VERSION is a better hash than the pointer
+   value and gives a predictable traversal order.  */
+struct tree_ssa_name_hash : ggc_ptr_hash <tree_node>
+{
+  static inline hashval_t hash (tree);
+};
+
+inline hashval_t
+tree_ssa_name_hash::hash (tree t)
+{
+  return SSA_NAME_VERSION (t);
+}
+
+/* Hasher for general trees, based on their TREE_HASH.  */
+struct tree_hash : ggc_ptr_hash <tree_node>
+{
+  static hashval_t hash (tree);
+};
+
+inline hashval_t
+tree_hash::hash (tree t)
+{
+  return TREE_HASH (t);
+}
+
 /* A hash_map of two trees for use with GTY((cache)).  Garbage collection for
    such a map will not mark keys, and will mark values if the key is already
    marked.  */
@@ -5358,6 +5410,18 @@ struct tree_cache_traits
   : simple_cache_map_traits<default_hash_traits<tree>, tree> { };
 typedef hash_map<tree,tree,tree_cache_traits> tree_cache_map;
 
+/* Similarly, but use DECL_UID as hash function rather than pointer hashing.
+   This is for hash_maps from decls to trees that need to work across PCH.  */
+struct decl_tree_cache_traits
+  : simple_cache_map_traits<tree_decl_hash, tree> { };
+typedef hash_map<tree,tree,decl_tree_cache_traits> decl_tree_cache_map;
+
+/* Similarly, but use TYPE_UID as hash function rather than pointer hashing.
+   This is for hash_maps from types to trees that need to work across PCH.  */
+struct type_tree_cache_traits
+  : simple_cache_map_traits<tree_type_hash, tree> { };
+typedef hash_map<tree,tree,type_tree_cache_traits> type_tree_cache_map;
+
 /* Initialize the abstract argument list iterator object ITER with the
    arguments from CALL_EXPR node EXP.  */
 static inline void
--- gcc/cp/init.c.jj    2019-11-08 00:22:12.042424097 +0100
+++ gcc/cp/init.c       2019-11-22 11:50:11.285872353 +0100
@@ -548,7 +548,7 @@ perform_target_ctor (tree init)
 
 /* Return the non-static data initializer for FIELD_DECL MEMBER.  */
 
-static GTY((cache)) tree_cache_map *nsdmi_inst;
+static GTY((cache)) decl_tree_cache_map *nsdmi_inst;
 
 tree
 get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
--- gcc/cp/constraint.cc.jj     2019-11-11 21:04:02.104306246 +0100
+++ gcc/cp/constraint.cc        2019-11-22 11:47:05.621749384 +0100
@@ -1113,7 +1113,7 @@ build_constraints (tree tr, tree dr)
 
 /* A mapping from declarations to constraint information.  */
 
-static GTY ((cache)) tree_cache_map *decl_constraints;
+static GTY ((cache)) decl_tree_cache_map *decl_constraints;
 
 /* Returns the template constraints of declaration T. If T is not
    constrained, return NULL_TREE. Note that T must be non-null. */
--- gcc/cp/decl.c.jj    2019-11-19 22:26:46.289293903 +0100
+++ gcc/cp/decl.c       2019-11-22 11:49:01.954946691 +0100
@@ -7998,7 +7998,7 @@ get_tuple_decomp_init (tree decl, unsign
 /* It's impossible to recover the decltype of a tuple decomposition variable
    based on the actual type of the variable, so store it in a hash table.  */
 
-static GTY((cache)) tree_cache_map *decomp_type_table;
+static GTY((cache)) decl_tree_cache_map *decomp_type_table;
 
 tree
 lookup_decomp_type (tree v)
--- gcc/cp/pt.c.jj      2019-11-19 22:27:00.737077646 +0100
+++ gcc/cp/pt.c 2019-11-22 11:52:37.590605226 +0100
@@ -13272,7 +13272,7 @@ tsubst_aggr_type (tree t,
     }
 }
 
-static GTY((cache)) tree_cache_map *defarg_inst;
+static GTY((cache)) decl_tree_cache_map *defarg_inst;
 
 /* Substitute into the default argument ARG (a default argument for
    FN), which has the indicated TYPE.  */
@@ -13346,7 +13346,7 @@ tsubst_default_argument (tree fn, int pa
   if (arg != error_mark_node && !cp_unevaluated_operand)
     {
       if (!defarg_inst)
-       defarg_inst = tree_cache_map::create_ggc (37);
+       defarg_inst = decl_tree_cache_map::create_ggc (37);
       defarg_inst->put (parm, arg);
     }
 
@@ -13383,7 +13383,7 @@ tsubst_default_arguments (tree fn, tsubs
 }
 
 /* Hash table mapping a FUNCTION_DECL to its dependent explicit-specifier.  */
-static GTY((cache)) tree_cache_map *explicit_specifier_map;
+static GTY((cache)) decl_tree_cache_map *explicit_specifier_map;
 
 /* Store a pair to EXPLICIT_SPECIFIER_MAP.  */
 
@@ -13391,7 +13391,7 @@ void
 store_explicit_specifier (tree v, tree t)
 {
   if (!explicit_specifier_map)
-    explicit_specifier_map = tree_cache_map::create_ggc (37);
+    explicit_specifier_map = decl_tree_cache_map::create_ggc (37);
   DECL_HAS_DEPENDENT_EXPLICIT_SPEC_P (v) = true;
   explicit_specifier_map->put (v, t);
 }
--- gcc/cp/cp-objcp-common.c.jj 2019-11-06 08:58:38.189471399 +0100
+++ gcc/cp/cp-objcp-common.c    2019-11-22 11:51:28.090682190 +0100
@@ -123,7 +123,7 @@ cxx_types_compatible_p (tree x, tree y)
   return same_type_ignoring_top_level_qualifiers_p (x, y);
 }
 
-static GTY((cache)) tree_cache_map *debug_type_map;
+static GTY((cache)) type_tree_cache_map *debug_type_map;
 
 /* Return a type to use in the debug info instead of TYPE, or NULL_TREE to
    keep TYPE.  */
--- gcc/testsuite/g++.dg/pch/pr92458.C.jj       2019-11-22 11:46:31.465278668 
+0100
+++ gcc/testsuite/g++.dg/pch/pr92458.C  2019-11-22 11:46:31.465278668 +0100
@@ -0,0 +1,5 @@
+// PR c++/92458
+// { dg-options "-std=c++2a" }
+
+#include "pr92458.H"
+S<int> s;
--- gcc/testsuite/g++.dg/pch/pr92458.Hs.jj      2019-11-22 11:46:31.466278653 
+0100
+++ gcc/testsuite/g++.dg/pch/pr92458.Hs 2019-11-22 11:46:31.466278653 +0100
@@ -0,0 +1,7 @@
+// PR c++/92458
+// { dg-options "-std=c++2a" }
+
+template<typename T> concept C = sizeof(T) > 1;
+template<typename T> struct S { };
+template<typename T> requires C<T> struct S<T> { };
+template<typename T> requires (!C<T>) struct S<T> { };


        Jakub

Reply via email to