public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-1090] c++: Elide calls to NOP module initializers
@ 2022-06-14 16:11 Nathan Sidwell
  0 siblings, 0 replies; only message in thread
From: Nathan Sidwell @ 2022-06-14 16:11 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:e8609768fbbc1ec650fe245cb45ee6d893ade3d7

commit r13-1090-ge8609768fbbc1ec650fe245cb45ee6d893ade3d7
Author: Nathan Sidwell <nathan@acm.org>
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<module_processing_cookie *> (cookie));
+			static_cast<module_processing_cookie *> (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-*-* } } }


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-06-14 16:11 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-14 16:11 [gcc r13-1090] c++: Elide calls to NOP module initializers Nathan Sidwell

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).