public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* c++: Static init guard generation
@ 2022-06-01 15:33 Nathan Sidwell
  0 siblings, 0 replies; only message in thread
From: Nathan Sidwell @ 2022-06-01 15:33 UTC (permalink / raw)
  To: GCC Patches

[-- Attachment #1: Type: text/plain, Size: 252 bytes --]

The guard generation for a static var init was overly verbose.  We can
use a bit of RAII and avoid some rechecking.  Also in the !cxa_atexit
case, the only difference is whether can become whether to use
post-inc or pre-dec.

nathan

-- 
Nathan Sidwell

[-- Attachment #2: 0001-c-Static-init-guard-generation.patch --]
[-- Type: text/x-patch, Size: 7213 bytes --]

From 289f860fe62423a66e43989688e1d24bcdb25b5e Mon Sep 17 00:00:00 2001
From: Nathan Sidwell <nathan@acm.org>
Date: Wed, 1 Jun 2022 04:52:21 -0700
Subject: [PATCH] c++: Static init guard generation

The guard generation for a static var init was overly verbose.  We can
use a bit of RAII and avoid some rechecking.  Also in the !cxa_atexit
case, the only difference is whether can become whether to use
post-inc or pre-dec.

	gcc/cp/
	* decl2.cc (fix_temporary_vars_context_r): Use data argument
	for new context.
	(one_static_initialization_or_destruction): Adjust tree walk
	call.  Refactor guard generation.
---
 gcc/cp/decl2.cc | 111 ++++++++++++++++++------------------------------
 1 file changed, 42 insertions(+), 69 deletions(-)

diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc
index 9de3f806e95..974afe798b6 100644
--- a/gcc/cp/decl2.cc
+++ b/gcc/cp/decl2.cc
@@ -4085,34 +4085,25 @@ get_priority_info (int priority)
 						    || DECL_ONE_ONLY (decl) \
 						    || DECL_WEAK (decl)))
 
-/* Called from one_static_initialization_or_destruction(),
-   via walk_tree.
-   Walks the initializer list of a global variable and looks for
+/* Walks the initializer list of a global variable and looks for
    temporary variables (DECL_NAME() == NULL and DECL_ARTIFICIAL != 0)
-   and that have their DECL_CONTEXT() == NULL.
-   For each such temporary variable, set their DECL_CONTEXT() to
-   the current function. This is necessary because otherwise
-   some optimizers (enabled by -O2 -fprofile-arcs) might crash
-   when trying to refer to a temporary variable that does not have
-   it's DECL_CONTECT() properly set.  */
+   and that have their DECL_CONTEXT() == NULL.  For each such
+   temporary variable, set their DECL_CONTEXT() to CTX -- the
+   initializing function. This is necessary because otherwise some
+   optimizers (enabled by -O2 -fprofile-arcs) might crash when trying
+   to refer to a temporary variable that does not have its
+   DECL_CONTEXT() properly set.  */
+
 static tree 
 fix_temporary_vars_context_r (tree *node,
 			      int  * /*unused*/,
-			      void * /*unused1*/)
+			      void *ctx)
 {
-  gcc_assert (current_function_decl);
-
   if (TREE_CODE (*node) == BIND_EXPR)
-    {
-      tree var;
-
-      for (var = BIND_EXPR_VARS (*node); var; var = DECL_CHAIN (var))
-	if (VAR_P (var)
-	  && !DECL_NAME (var)
-	  && DECL_ARTIFICIAL (var)
-	  && !DECL_CONTEXT (var))
-	  DECL_CONTEXT (var) = current_function_decl;
-    }
+    for (tree var = BIND_EXPR_VARS (*node); var; var = DECL_CHAIN (var))
+      if (VAR_P (var) && !DECL_NAME (var)
+	  && DECL_ARTIFICIAL (var) && !DECL_CONTEXT (var))
+	DECL_CONTEXT (var) = tree (ctx);
 
   return NULL_TREE;
 }
@@ -4124,9 +4115,6 @@ fix_temporary_vars_context_r (tree *node,
 static void
 one_static_initialization_or_destruction (bool initp, tree decl, tree init)
 {
-  tree guard_if_stmt = NULL_TREE;
-  tree guard;
-
   /* If we are supposed to destruct and there's a trivial destructor,
      nothing has to be done.  */
   if (!initp
@@ -4150,7 +4138,7 @@ one_static_initialization_or_destruction (bool initp, tree decl, tree init)
      of the temporaries are set to the current function decl.  */
   cp_walk_tree_without_duplicates (&init,
 				   fix_temporary_vars_context_r,
-				   NULL);
+				   current_function_decl);
 
   /* Because of:
 
@@ -4171,62 +4159,50 @@ one_static_initialization_or_destruction (bool initp, tree decl, tree init)
     }
 
   /* Assume we don't need a guard.  */
-  guard = NULL_TREE;
+  tree guard_if_stmt = NULL_TREE;
+
   /* We need a guard if this is an object with external linkage that
      might be initialized in more than one place.  (For example, a
      static data member of a template, when the data member requires
      construction.)  */
   if (NEEDS_GUARD_P (decl))
     {
+      tree guard = get_guard (decl);
       tree guard_cond;
 
-      guard = get_guard (decl);
-
-      /* When using __cxa_atexit, we just check the GUARD as we would
-	 for a local static.  */
       if (flag_use_cxa_atexit)
 	{
-	  /* When using __cxa_atexit, we never try to destroy
+	  /* When using __cxa_atexit, we just check the GUARD as we
+	     would for a local static.  We never try to destroy
 	     anything from a static destructor.  */
 	  gcc_assert (initp);
 	  guard_cond = get_guard_cond (guard, false);
 	}
-      /* If we don't have __cxa_atexit, then we will be running
-	 destructors from .fini sections, or their equivalents.  So,
-	 we need to know how many times we've tried to initialize this
-	 object.  We do initializations only if the GUARD is zero,
-	 i.e., if we are the first to initialize the variable.  We do
-	 destructions only if the GUARD is one, i.e., if we are the
-	 last to destroy the variable.  */
-      else if (initp)
-	guard_cond
-	  = cp_build_binary_op (input_location,
-				EQ_EXPR,
-				cp_build_unary_op (PREINCREMENT_EXPR,
-						   guard,
-						   /*noconvert=*/true,
-						   tf_warning_or_error),
-				integer_one_node,
-				tf_warning_or_error);
       else
-	guard_cond
-	  = cp_build_binary_op (input_location,
-				EQ_EXPR,
-				cp_build_unary_op (PREDECREMENT_EXPR,
-						   guard,
-						   /*noconvert=*/true,
-						   tf_warning_or_error),
-				integer_zero_node,
-				tf_warning_or_error);
+	{
+	  /* If we don't have __cxa_atexit, then we will be running
+	     destructors from .fini sections, or their equivalents.
+	     So, we need to know how many times we've tried to
+	     initialize this object.  We do initializations only if
+	     the GUARD was or becomes zero (initp vs !initp
+	     respectively).  */
+	  guard_cond = cp_build_unary_op (initp ? POSTINCREMENT_EXPR
+					  : PREDECREMENT_EXPR,
+					  guard,
+					  /*noconvert=*/true,
+					  tf_warning_or_error);
+	  guard_cond = cp_build_binary_op (input_location, EQ_EXPR, guard_cond, 
+					   integer_zero_node,
+					   tf_warning_or_error);
+	}
 
       guard_if_stmt = begin_if_stmt ();
       finish_if_stmt_cond (guard_cond, guard_if_stmt);
-    }
 
-  /* If we're using __cxa_atexit, we have not already set the GUARD,
-     so we must do so now.  */
-  if (guard && initp && flag_use_cxa_atexit)
-    finish_expr_stmt (set_guard (guard));
+      if (flag_use_cxa_atexit)
+	/* Set the GUARD now.  */
+	finish_expr_stmt (set_guard (guard));
+    }
 
   /* Perform the initialization or destruction.  */
   if (initp)
@@ -4235,11 +4211,8 @@ one_static_initialization_or_destruction (bool initp, tree decl, tree init)
 	{
 	  finish_expr_stmt (init);
 	  if (sanitize_flags_p (SANITIZE_ADDRESS, decl))
-	    {
-	      varpool_node *vnode = varpool_node::get (decl);
-	      if (vnode)
-		vnode->dynamically_initialized = 1;
-	    }
+	    if (varpool_node *vnode = varpool_node::get (decl))
+	      vnode->dynamically_initialized = 1;
 	}
 
       /* If we're using __cxa_atexit, register a function that calls the
@@ -4251,7 +4224,7 @@ one_static_initialization_or_destruction (bool initp, tree decl, tree init)
     finish_expr_stmt (build_cleanup (decl));
 
   /* Finish the guard if-stmt, if necessary.  */
-  if (guard)
+  if (guard_if_stmt)
     {
       finish_then_clause (guard_if_stmt);
       finish_if_stmt (guard_if_stmt);
-- 
2.30.2


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

only message in thread, other threads:[~2022-06-01 15:33 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-01 15:33 c++: Static init guard generation 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).