]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++/102228 - make lookup_anon_field O(1)
authorRichard Biener <rguenther@suse.de>
Wed, 8 Sep 2021 08:39:27 +0000 (10:39 +0200)
committerRichard Biener <rguenther@suse.de>
Wed, 8 Sep 2021 15:43:40 +0000 (17:43 +0200)
For the testcase in PR101555 lookup_anon_field takes the majority
of parsing time followed by get_class_binding_direct/fields_linear_search
which is PR83309.  The situation with anon aggregates is particularly
dire when we need to build accesses to their members and the anon
aggregates are nested.  There for each such access we recursively
build sub-accesses to the anon aggregate FIELD_DECLs bottom-up,
DFS searching for them.  That's inefficient since as I believe
there's a 1:1 relationship between anon aggregate types and the
FIELD_DECL used to place them.

The patch below does away with the search in lookup_anon_field and
instead records the single FIELD_DECL in the anon aggregate types
lang-specific data, re-using the RTTI typeinfo_var field.  That
speeds up the compile of the testcase with -fsyntax-only from
about 4.5s to slightly less than 1s.

I tried to poke holes into the 1:1 relationship idea with my C++
knowledge but failed (which might not say much).  It also leaves
a hole for the case when the C++ FE itself duplicates such type
and places it at a semantically different position.  I've tried
to poke holes into it with the duplication mechanism I understand
(templates) but failed.

2021-09-08  Richard Biener  <rguenther@suse.de>

PR c++/102228
gcc/cp/
* cp-tree.h (ANON_AGGR_TYPE_FIELD): New define.
* decl.c (fixup_anonymous_aggr): Wipe RTTI info put in
place on invalid code.
* decl2.c (reset_type_linkage): Guard CLASSTYPE_TYPEINFO_VAR
access.
* module.cc (trees_in::read_class_def): Likewise.  Reconstruct
ANON_AGGR_TYPE_FIELD.
* semantics.c (finish_member_declaration): Populate
ANON_AGGR_TYPE_FIELD for anon aggregate typed members.
* typeck.c (lookup_anon_field): Remove DFS search and return
ANON_AGGR_TYPE_FIELD directly.

gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/module.cc
gcc/cp/semantics.c
gcc/cp/typeck.c

index 435f32bf90914c4455752283890fa54a3c28f7bd..ceb53591926e46bf4435f3fc81aa82162f977ade 100644 (file)
@@ -4800,6 +4800,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 #define ANON_UNION_TYPE_P(NODE) \
   (TREE_CODE (NODE) == UNION_TYPE && ANON_AGGR_TYPE_P (NODE))
 
+/* For an ANON_AGGR_TYPE_P the single FIELD_DECL it is used with.  */
+#define ANON_AGGR_TYPE_FIELD(NODE) \
+  (LANG_TYPE_CLASS_CHECK (NODE)->typeinfo_var)
+
 /* Define fields and accessors for nodes representing declared names.  */
 
 /* True if TYPE is an unnamed structured type with a typedef for
index 146979ba96b336a8c7ea87081604b474731bf1f7..bce62ad202a52d6d92be34c364f438bf674241c2 100644 (file)
@@ -5096,6 +5096,9 @@ fixup_anonymous_aggr (tree t)
       (*vec)[store++] = elt;
   vec_safe_truncate (vec, store);
 
+  /* Wipe RTTI info.  */
+  CLASSTYPE_TYPEINFO_VAR (t) = NULL_TREE;
+
   /* Anonymous aggregates cannot have fields with ctors, dtors or complex
      assignment operators (because they cannot have these methods themselves).
      For anonymous unions this is already checked because they are not allowed
index 107edcaaccfcaf7bf1fce830eb6a526ea06aedf0..a79a70ba9c2f94666298cbf87276ac23dbb7fd40 100644 (file)
@@ -2977,14 +2977,15 @@ reset_type_linkage (tree type)
          SET_DECL_ASSEMBLER_NAME (vt, name);
          reset_decl_linkage (vt);
        }
-      if (tree ti = CLASSTYPE_TYPEINFO_VAR (type))
-       {
-         tree name = mangle_typeinfo_for_type (type);
-         DECL_NAME (ti) = name;
-         SET_DECL_ASSEMBLER_NAME (ti, name);
-         TREE_TYPE (name) = type;
-         reset_decl_linkage (ti);
-       }
+      if (!ANON_AGGR_TYPE_P (type))
+       if (tree ti = CLASSTYPE_TYPEINFO_VAR (type))
+         {
+           tree name = mangle_typeinfo_for_type (type);
+           DECL_NAME (ti) = name;
+           SET_DECL_ASSEMBLER_NAME (ti, name);
+           TREE_TYPE (name) = type;
+           reset_decl_linkage (ti);
+         }
       for (tree m = TYPE_FIELDS (type); m; m = DECL_CHAIN (m))
        {
          tree mem = STRIP_TEMPLATE (m);
index 4b2ad6f3db8087a2601fcaa16fa8fa7443706bba..71d0fab411f6fb3fc976f8e31b42fe6d0d055761 100644 (file)
@@ -11859,8 +11859,9 @@ trees_in::read_class_def (tree defn, tree maybe_template)
                {
                  CLASSTYPE_BEFRIENDING_CLASSES (type_dup)
                    = CLASSTYPE_BEFRIENDING_CLASSES (type);
-                 CLASSTYPE_TYPEINFO_VAR (type_dup)
-                   = CLASSTYPE_TYPEINFO_VAR (type);
+                 if (!ANON_AGGR_TYPE_P (type))
+                   CLASSTYPE_TYPEINFO_VAR (type_dup)
+                     = CLASSTYPE_TYPEINFO_VAR (type);
                }
              for (tree v = type; v; v = TYPE_NEXT_VARIANT (v))
                TYPE_LANG_SPECIFIC (v) = ls;
@@ -11891,6 +11892,11 @@ trees_in::read_class_def (tree defn, tree maybe_template)
              *chain = decl;
              chain = &DECL_CHAIN (decl);
 
+             if (TREE_CODE (decl) == FIELD_DECL
+                 && ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
+               ANON_AGGR_TYPE_FIELD
+                 (TYPE_MAIN_VARIANT (TREE_TYPE (decl))) = decl;
+
              if (TREE_CODE (decl) == USING_DECL
                  && TREE_CODE (USING_DECL_SCOPE (decl)) == RECORD_TYPE)
                {
index 8b78e89ce3a145956fd5efe7ad972d633b3106db..4b7f4ace1806f4b74571b592342b92fa4eec6b5b 100644 (file)
@@ -3489,6 +3489,14 @@ finish_member_declaration (tree decl)
   if (TREE_CODE (decl) != CONST_DECL)
     DECL_CONTEXT (decl) = current_class_type;
 
+  /* Remember the single FIELD_DECL an anonymous aggregate type is used for.  */
+  if (TREE_CODE (decl) == FIELD_DECL
+      && ANON_AGGR_TYPE_P (TREE_TYPE (decl)))
+    {
+      gcc_assert (!ANON_AGGR_TYPE_FIELD (TYPE_MAIN_VARIANT (TREE_TYPE (decl))));
+      ANON_AGGR_TYPE_FIELD (TYPE_MAIN_VARIANT (TREE_TYPE (decl))) = decl;
+    }
+
   if (TREE_CODE (decl) == USING_DECL)
     /* For now, ignore class-scope USING_DECLS, so that debugging
        backends do not see them. */
index cc61b509f8a5552b5c88a29675dd88c37713708b..a2398dbe660c004cdd635cac3f61f9d88c3ed6e5 100644 (file)
@@ -2618,36 +2618,14 @@ rationalize_conditional_expr (enum tree_code code, tree t,
    that are directly reachable.  */
 
 tree
-lookup_anon_field (tree t, tree type)
+lookup_anon_field (tree, tree type)
 {
   tree field;
 
-  t = TYPE_MAIN_VARIANT (t);
-
-  for (field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
-    {
-      if (TREE_STATIC (field))
-       continue;
-      if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
-       continue;
-
-      /* If we find it directly, return the field.  */
-      if (DECL_NAME (field) == NULL_TREE
-         && type == TYPE_MAIN_VARIANT (TREE_TYPE (field)))
-       {
-         return field;
-       }
-
-      /* Otherwise, it could be nested, search harder.  */
-      if (DECL_NAME (field) == NULL_TREE
-         && ANON_AGGR_TYPE_P (TREE_TYPE (field)))
-       {
-         tree subfield = lookup_anon_field (TREE_TYPE (field), type);
-         if (subfield)
-           return subfield;
-       }
-    }
-  return NULL_TREE;
+  type = TYPE_MAIN_VARIANT (type);
+  field = ANON_AGGR_TYPE_FIELD (type);
+  gcc_assert (field);
+  return field;
 }
 
 /* Build an expression representing OBJECT.MEMBER.  OBJECT is an