From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1666) id 742DB385840F; Wed, 8 Sep 2021 15:43:53 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 742DB385840F MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Richard Biener To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-3421] c++/102228 - make lookup_anon_field O(1) X-Act-Checkin: gcc X-Git-Author: Richard Biener X-Git-Refname: refs/heads/master X-Git-Oldrev: d27d694151c5604d2daba23dd2a328ae70b65194 X-Git-Newrev: 716a5836928ee6d8fb884d9a2fbc1b1386ec8994 Message-Id: <20210908154353.742DB385840F@sourceware.org> Date: Wed, 8 Sep 2021 15:43:53 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 08 Sep 2021 15:43:53 -0000 https://gcc.gnu.org/g:716a5836928ee6d8fb884d9a2fbc1b1386ec8994 commit r12-3421-g716a5836928ee6d8fb884d9a2fbc1b1386ec8994 Author: Richard Biener Date: Wed Sep 8 10:39:27 2021 +0200 c++/102228 - make lookup_anon_field O(1) 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 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. Diff: --- gcc/cp/cp-tree.h | 4 ++++ gcc/cp/decl.c | 3 +++ gcc/cp/decl2.c | 17 +++++++++-------- gcc/cp/module.cc | 10 ++++++++-- gcc/cp/semantics.c | 8 ++++++++ gcc/cp/typeck.c | 32 +++++--------------------------- 6 files changed, 37 insertions(+), 37 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 435f32bf909..ceb53591926 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 146979ba96b..bce62ad202a 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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 diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 107edcaaccf..a79a70ba9c2 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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); diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 4b2ad6f3db8..71d0fab411f 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -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) { diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 8b78e89ce3a..4b7f4ace180 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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. */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index cc61b509f8a..a2398dbe660 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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