There's no point adding no-op initializer fns (that a module might
have) to the static initializer list. Also, we can add any objc
initializer call to a partial initializer function and simplify some
control flow.
nathan
--
Nathan Sidwell
From c970d0072e3f962afa278e28f918fdcd1b3e755c Mon Sep 17 00:00:00 2001
From: Nathan Sidwell <nat...@acm.org>
Date: Thu, 16 Jun 2022 10:14:56 -0700
Subject: [PATCH] c++: Elide inactive initializer fns from init array
There's no point adding no-op initializer fns (that a module might
have) to the static initializer list. Also, we can add any objc
initializer call to a partial initializer function and simplify some
control flow.
gcc/cp/
* decl2.cc (finish_objects): Add startp parameter, adjust.
(generate_ctor_or_dtor_function): Detect empty fn, and don't
generate unnecessary code. Remove objc startup here ...
(c_parse_final_cleanyps): ... do it here.
gcc/testsuite/
* g++.dg/modules/init-2_b.C: Add init check.
* g++.dg/modules/init-2_c.C: Add init check.
---
gcc/cp/decl2.cc | 97 +++++++++++++------------
gcc/testsuite/g++.dg/modules/init-2_b.C | 1 +
gcc/testsuite/g++.dg/modules/init-2_c.C | 1 +
3 files changed, 53 insertions(+), 46 deletions(-)
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 0c4492f7354..3737e5f010c 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -56,7 +56,7 @@ int raw_dump_id;
extern cpp_reader *parse_in;
static tree start_objects (bool, unsigned, bool);
-static tree finish_objects (bool, unsigned, tree);
+static tree finish_objects (bool, unsigned, tree, bool = true);
static tree start_partial_init_fini_fn (bool, unsigned, unsigned);
static void finish_partial_init_fini_fn (tree);
static void emit_partial_init_fini_fn (bool, unsigned, tree,
@@ -3932,16 +3932,19 @@ start_objects (bool initp, unsigned priority, bool has_body)
return body;
}
-/* Finish a global constructor or destructor. */
+/* Finish a global constructor or destructor. Add it to the global
+ ctors or dtors, if STARTP is true. */
static tree
-finish_objects (bool initp, unsigned priority, tree body)
+finish_objects (bool initp, unsigned priority, tree body, bool startp)
{
/* Finish up. */
finish_compound_stmt (body);
tree fn = finish_function (/*inline_p=*/false);
- if (initp)
+ if (!startp)
+ ; // Neither ctor nor dtor I be.
+ else if (initp)
{
DECL_STATIC_CONSTRUCTOR (fn) = 1;
decl_init_priority_insert (fn, priority);
@@ -4307,58 +4310,54 @@ write_out_vars (tree vars)
}
}
-/* Generate a static constructor (if CONSTRUCTOR_P) or destructor
- (otherwise) that will initialize all global objects with static
- storage duration having the indicated PRIORITY. */
+/* Generate a static constructor or destructor that calls the given
+ init/fini fns at the indicated priority. */
static void
generate_ctor_or_dtor_function (bool initp, unsigned priority,
tree fns, location_t locus)
{
input_location = locus;
-
tree body = start_objects (initp, priority, bool (fns));
- /* To make sure dynamic construction doesn't access globals from other
- compilation units where they might not be yet constructed, for
- -fsanitize=address insert __asan_before_dynamic_init call that
- prevents access to either all global variables that need construction
- in other compilation units, or at least those that haven't been
- initialized yet. Variables that need dynamic construction in
- the current compilation unit are kept accessible. */
- if (initp && (flag_sanitize & SANITIZE_ADDRESS))
- finish_expr_stmt (asan_dynamic_init_call (/*after_p=*/false));
-
- if (initp && priority == DEFAULT_INIT_PRIORITY
- && c_dialect_objc () && objc_static_init_needed_p ())
- /* For Objective-C++, we may need to initialize metadata found in
- this module. This must be done _before_ any other static
- initializations. */
- objc_generate_static_init_call (NULL_TREE);
-
- /* Call the static init/fini functions. */
- for (tree node = fns; node; node = TREE_CHAIN (node))
+ if (fns)
{
- tree fn = TREE_PURPOSE (node);
+ /* To make sure dynamic construction doesn't access globals from
+ other compilation units where they might not be yet
+ constructed, for -fsanitize=address insert
+ __asan_before_dynamic_init call that prevents access to
+ either all global variables that need construction in other
+ compilation units, or at least those that haven't been
+ initialized yet. Variables that need dynamic construction in
+ the current compilation unit are kept accessible. */
+ if (initp && (flag_sanitize & SANITIZE_ADDRESS))
+ finish_expr_stmt (asan_dynamic_init_call (/*after_p=*/false));
- // We should never find a pure or constant cdtor.
- gcc_checking_assert (!(flags_from_decl_or_type (fn)
- & (ECF_CONST | ECF_PURE)));
+ /* Call the static init/fini functions. */
+ for (tree node = fns; node; node = TREE_CHAIN (node))
+ {
+ tree fn = TREE_PURPOSE (node);
- tree call = cp_build_function_call_nary (fn, tf_warning_or_error,
- NULL_TREE);
- finish_expr_stmt (call);
+ // We should never find a pure or constant cdtor.
+ gcc_checking_assert (!(flags_from_decl_or_type (fn)
+ & (ECF_CONST | ECF_PURE)));
+
+ tree call = cp_build_function_call_nary (fn, tf_warning_or_error,
+ NULL_TREE);
+ finish_expr_stmt (call);
+ }
+
+ /* Revert what __asan_before_dynamic_init did by calling
+ __asan_after_dynamic_init. */
+ if (initp && (flag_sanitize & SANITIZE_ADDRESS))
+ finish_expr_stmt (asan_dynamic_init_call (/*after_p=*/true));
}
- /* Revert what __asan_before_dynamic_init did by calling
- __asan_after_dynamic_init. */
- if (initp && (flag_sanitize & SANITIZE_ADDRESS))
- finish_expr_stmt (asan_dynamic_init_call (/*after_p=*/true));
-
/* Close out the function, and arrange for it to be called at init
- or fini time. (Even module initializer functions need this, as
- we cannot guarantee the module is imported somewhere in the programq.) */
- expand_or_defer_fn (finish_objects (initp, priority, body));
+ or fini time, if non-empty. (Even non-nop module initializer
+ functions need this, as we cannot guarantee the module is
+ imported somewhere in the program.) */
+ expand_or_defer_fn (finish_objects (initp, priority, body, fns != NULL_TREE));
}
/* Return C++ property of T, based on given operation OP. */
@@ -5206,18 +5205,24 @@ c_parse_final_cleanups (void)
objc_write_global_declarations ();
bool has_module_inits = module_determine_import_inits ();
- if (has_module_inits)
+ bool has_objc_init = c_dialect_objc () && objc_static_init_needed_p ();
+ if (has_module_inits || has_objc_init)
{
input_location = locus_at_end_of_parsing;
tree body = start_partial_init_fini_fn (true, DEFAULT_INIT_PRIORITY,
ssdf_count++);
- module_add_import_initializers ();
+ /* For Objective-C++, we may need to initialize metadata found
+ in this module. This must be done _before_ any other static
+ initializations. */
+ if (has_objc_init)
+ objc_generate_static_init_call (NULL_TREE);
+ if (has_module_inits)
+ module_add_import_initializers ();
input_location = locus_at_end_of_parsing;
finish_partial_init_fini_fn (body);
}
- if ((c_dialect_objc () && objc_static_init_needed_p ())
- || module_global_init_needed ())
+ if (module_global_init_needed ())
{
// Make sure there's a default priority entry.
if (!static_init_fini_fns[true])
diff --git a/gcc/testsuite/g++.dg/modules/init-2_b.C b/gcc/testsuite/g++.dg/modules/init-2_b.C
index 4350944139f..a98e67616a2 100644
--- a/gcc/testsuite/g++.dg/modules/init-2_b.C
+++ b/gcc/testsuite/g++.dg/modules/init-2_b.C
@@ -8,3 +8,4 @@ import Foo;
// There should be an idempotency check
// { dg-final { scan-assembler {_ZZ9_ZGIW3BarE9__in_chrg} } }
// { dg-final { scan-assembler {call[ \t]+_?_ZGIW3Foo} { target i?86-*-* x86_64-*-* } } }
+// { dg-final { scan-assembler {.(quad|long)[ \t]+_ZGIW3Bar} { target i?86-*-* x86_64-*-* } } }
diff --git a/gcc/testsuite/g++.dg/modules/init-2_c.C b/gcc/testsuite/g++.dg/modules/init-2_c.C
index 2b1315e2892..c386582b9c0 100644
--- a/gcc/testsuite/g++.dg/modules/init-2_c.C
+++ b/gcc/testsuite/g++.dg/modules/init-2_c.C
@@ -5,3 +5,4 @@ export module Baz;
// { dg-final { scan-assembler {_ZGIW3Baz:} } }
// But it is empty, and so no idempotency bool
// { dg-final { scan-assembler-not {_ZZ9_ZGIW3BazE9__in_chrg} } }
+// { dg-final { scan-assembler-not {.(quad|long)[ \t]+_ZGIW3Baz} { target i?86-*-* x86_64-*-* } } }
--
2.30.2