From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1059) id DA43E385C321; Tue, 14 Jun 2022 16:11:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DA43E385C321 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Nathan Sidwell To: gcc-cvs@gcc.gnu.org Subject: [gcc r13-1090] c++: Elide calls to NOP module initializers X-Act-Checkin: gcc X-Git-Author: Nathan Sidwell X-Git-Refname: refs/heads/master X-Git-Oldrev: 8f6c317b3a16350698f3c9e0accb43a9b4acb4ae X-Git-Newrev: e8609768fbbc1ec650fe245cb45ee6d893ade3d7 Message-Id: <20220614161154.DA43E385C321@sourceware.org> Date: Tue, 14 Jun 2022 16:11:54 +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: Tue, 14 Jun 2022 16:11:55 -0000 https://gcc.gnu.org/g:e8609768fbbc1ec650fe245cb45ee6d893ade3d7 commit r13-1090-ge8609768fbbc1ec650fe245cb45ee6d893ade3d7 Author: Nathan Sidwell Date: Thu Jun 9 11:18:19 2022 -0700 c++: Elide calls to NOP module initializers gcc/cp * cp-tree.h (fini_modules): Add has_inits parm. * decl2.cc (c_parse_final_cleanups): Check for inits, adjust fini_modules flags. * module.cc (module_state): Rename call_init_p to active_init_p. (module_state::write_config): Write active_init. (module_state::read_config): Read it. (module_determine_import_inits): Clear active_init_p of covered inits. (late_finish_module): Add has_init parm. Record it. (fini_modules): Adjust. gcc/testsuite/ * g++.dg/modules/init-2_a.C: Adjust. * g++.dg/modules/init-2_c.C: Adjust. * g++.dg/modules/init-2_d.C: New. Diff: --- gcc/cp/cp-tree.h | 2 +- gcc/cp/decl2.cc | 10 ++++--- gcc/cp/module.cc | 49 ++++++++++++++++++++------------- gcc/testsuite/g++.dg/modules/init-2_a.C | 9 ++++-- gcc/testsuite/g++.dg/modules/init-2_c.C | 11 ++++---- gcc/testsuite/g++.dg/modules/init-2_d.C | 11 ++++++++ 6 files changed, 60 insertions(+), 32 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 60d7b201595..2fde4f83b41 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7209,7 +7209,7 @@ extern void import_module (module_state *, location_t, bool export_p, extern void declare_module (module_state *, location_t, bool export_p, tree attr, cpp_reader *); extern void init_modules (cpp_reader *); -extern void fini_modules (cpp_reader *, void *cookie); +extern void fini_modules (cpp_reader *, void *cookie, bool); extern void maybe_check_all_macros (cpp_reader *); extern void *finish_module_processing (cpp_reader *); extern char const *module_name (unsigned, bool header_ok); diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index cc0b41324b3..a8f3e6e5fba 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -5205,7 +5205,8 @@ c_parse_final_cleanups (void) if (c_dialect_objc ()) objc_write_global_declarations (); - if (module_determine_import_inits ()) + bool has_module_inits = module_determine_import_inits (); + if (has_module_inits) { input_location = locus_at_end_of_parsing; tree body = start_partial_init_fini_fn (true, DEFAULT_INIT_PRIORITY, @@ -5221,8 +5222,9 @@ c_parse_final_cleanups (void) // Make sure there's a default priority entry. if (!static_init_fini_fns[true]) static_init_fini_fns[true] = priority_map_t::create_ggc (); - static_init_fini_fns[true]->get_or_insert (DEFAULT_INIT_PRIORITY); - } + if (static_init_fini_fns[true]->get_or_insert (DEFAULT_INIT_PRIORITY)) + has_module_inits = true; + } /* Generate initialization and destruction functions for all priorities for which they are required. They have C-language @@ -5238,7 +5240,7 @@ c_parse_final_cleanups (void) } pop_lang_context (); - fini_modules (parse_in, module_cookie); + fini_modules (parse_in, module_cookie, has_module_inits); /* Generate any missing aliases. */ maybe_apply_pending_pragma_weaks (); diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index e7ce40ef464..5566c49490f 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -3439,7 +3439,7 @@ class GTY((chain_next ("%h.parent"), for_user)) module_state { bool exported_p : 1; /* directness != MD_NONE && exported. */ bool cmi_noted_p : 1; /* We've told the user about the CMI, don't do it again */ - bool call_init_p : 1; /* This module's global initializer needs + bool active_init_p : 1; /* This module's global initializer needs calling. */ bool inform_cmi_p : 1; /* Inform of a read/write. */ bool visited_p : 1; /* A walk-once flag. */ @@ -3677,7 +3677,7 @@ module_state::module_state (tree name, module_state *parent, bool partition) exported_p = false; cmi_noted_p = false; - call_init_p = false; + active_init_p = false; partition_p = partition; @@ -14393,12 +14393,14 @@ struct module_state_config { unsigned ordinary_locs; unsigned macro_locs; unsigned ordinary_loc_align; + unsigned active_init; public: module_state_config () :dialect_str (get_dialect ()), num_imports (0), num_partitions (0), num_entities (0), - ordinary_locs (0), macro_locs (0), ordinary_loc_align (0) + ordinary_locs (0), macro_locs (0), ordinary_loc_align (0), + active_init (0) { } @@ -17336,7 +17338,9 @@ module_state::write_config (elf_out *to, module_state_config &config, cfg.u (config.ordinary_locs); cfg.u (config.macro_locs); - cfg.u (config.ordinary_loc_align); + cfg.u (config.ordinary_loc_align); + + cfg.u (config.active_init); /* Now generate CRC, we'll have incorporated the inner CRC because of its serialization above. */ @@ -17522,6 +17526,8 @@ module_state::read_config (module_state_config &config) config.macro_locs = cfg.u (); config.ordinary_loc_align = cfg.u (); + config.active_init = cfg.u (); + done: return cfg.end (from ()); } @@ -17922,6 +17928,9 @@ module_state::read_initial (cpp_reader *reader) if (ok && have_locs && !read_macro_maps ()) ok = false; + /* Note whether there's an active initializer. */ + active_init_p = !is_header () && bool (config.active_init); + gcc_assert (slurp->current == ~0u); return ok; } @@ -19047,10 +19056,10 @@ module_determine_import_inits () if (!modules || header_module_p ()) return false; - /* Determine call_init_p. We need the same bitmap allocation + /* Prune active_init_p. We need the same bitmap allocation scheme as for the imports member. */ function_depth++; /* Disable GC. */ - bitmap indirect_imports (BITMAP_GGC_ALLOC ()); + bitmap covered_imports (BITMAP_GGC_ALLOC ()); bool any = false; @@ -19060,16 +19069,15 @@ module_determine_import_inits () { module_state *import = (*modules)[ix]; - if (!import->is_header () - && !bitmap_bit_p (indirect_imports, ix)) + if (!import->active_init_p) + ; + else if (bitmap_bit_p (covered_imports, ix)) + import->active_init_p = false; + else { - /* Everything this imports is therefore indirectly - imported. */ - bitmap_ior_into (indirect_imports, import->imports); - /* We don't have to worry about the self-import bit, - because of the single pass. */ - - import->call_init_p = true; + /* Everything this imports is therefore handled by its + initializer, so doesn't need initializing by us. */ + bitmap_ior_into (covered_imports, import->imports); any = true; } } @@ -19098,7 +19106,7 @@ module_add_import_initializers () for (unsigned ix = modules->length (); --ix;) { module_state *import = (*modules)[ix]; - if (import->call_init_p) + if (import->active_init_p) { tree name = mangle_module_global_init (ix); tree fndecl = build_lang_decl (FUNCTION_DECL, name, fntype); @@ -19979,7 +19987,8 @@ finish_module_processing (cpp_reader *reader) // the module static initializer is a NOP or not. static void -late_finish_module (cpp_reader *reader, module_processing_cookie *cookie) +late_finish_module (cpp_reader *reader, module_processing_cookie *cookie, + bool init_fn_non_empty) { timevar_start (TV_MODULE_EXPORT); @@ -19987,6 +19996,7 @@ late_finish_module (cpp_reader *reader, module_processing_cookie *cookie) unsigned n = dump.push (state); state->announce ("finishing"); + cookie->config.active_init = init_fn_non_empty; if (cookie->began) state->write_end (&cookie->out, reader, cookie->config, cookie->crc); @@ -20029,11 +20039,12 @@ late_finish_module (cpp_reader *reader, module_processing_cookie *cookie) } void -fini_modules (cpp_reader *reader, void *cookie) +fini_modules (cpp_reader *reader, void *cookie, bool has_inits) { if (cookie) late_finish_module (reader, - static_cast (cookie)); + static_cast (cookie), + has_inits); /* We're done with the macro tables now. */ vec_free (macro_exports); diff --git a/gcc/testsuite/g++.dg/modules/init-2_a.C b/gcc/testsuite/g++.dg/modules/init-2_a.C index 4174cf53911..c7ec782420d 100644 --- a/gcc/testsuite/g++.dg/modules/init-2_a.C +++ b/gcc/testsuite/g++.dg/modules/init-2_a.C @@ -2,6 +2,11 @@ export module Foo; // { dg-module-cmi Foo } +static int init () +{ + return 1; +} + +int var = init (); + // { dg-final { scan-assembler {_ZGIW3Foo:} } } -// But it is empty, and so no idempotency bool -// { dg-final { scan-assembler-not {_ZZ9_ZGIW3FooE9__in_chrg} } } diff --git a/gcc/testsuite/g++.dg/modules/init-2_c.C b/gcc/testsuite/g++.dg/modules/init-2_c.C index 4ca880df771..2b1315e2892 100644 --- a/gcc/testsuite/g++.dg/modules/init-2_c.C +++ b/gcc/testsuite/g++.dg/modules/init-2_c.C @@ -1,8 +1,7 @@ // { dg-additional-options "-fmodules-ts -fno-inline" } +export module Baz; +// { dg-module-cmi Baz } -import Foo; -import Bar; - -// We know Bar imports Foo, so only call Bar's Global Init -// { dg-final { scan-assembler {call[ \t]+_?_ZGIW3Bar} { target i?86-*-* x86_64-*-* } } } -// { dg-final { scan-assembler-not {call[ \t]+_?_ZGIW3Foo} { target i?86-*-* x86_64-*-* } } } +// { dg-final { scan-assembler {_ZGIW3Baz:} } } +// But it is empty, and so no idempotency bool +// { dg-final { scan-assembler-not {_ZZ9_ZGIW3BazE9__in_chrg} } } diff --git a/gcc/testsuite/g++.dg/modules/init-2_d.C b/gcc/testsuite/g++.dg/modules/init-2_d.C new file mode 100644 index 00000000000..d125cfc1c15 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/init-2_d.C @@ -0,0 +1,11 @@ +// { dg-additional-options "-fmodules-ts -fno-inline" } + +import Foo; +import Bar; +import Baz; + +// We know Bar imports Foo, so only call Bar's Global Init +// { dg-final { scan-assembler {call[ \t]+_?_ZGIW3Bar} { target i?86-*-* x86_64-*-* } } } +// { dg-final { scan-assembler-not {call[ \t]+_?_ZGIW3Foo} { target i?86-*-* x86_64-*-* } } } +// We know Baz has a nop init, so don't call it. +// { dg-final { scan-assembler-not {call[ \t]+_?_ZGIW3Baz} { target i?86-*-* x86_64-*-* } } }