public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] tree-profile: Don't instrument an IFUNC resolver nor its callees
@ 2024-02-26 22:53 H.J. Lu
  2024-02-29 13:39 ` Jan Hubicka
  0 siblings, 1 reply; 8+ messages in thread
From: H.J. Lu @ 2024-02-26 22:53 UTC (permalink / raw)
  To: gcc-patches

We can't instrument an IFUNC resolver nor its callees as it may require
TLS which hasn't been set up yet when the dynamic linker is resolving
IFUNC symbols.  Add an IFUNC resolver caller marker to symtab_node to
avoid recursive checking.

gcc/ChangeLog:

	PR tree-optimization/114115
	* cgraph.h (enum ifunc_caller): New.
	(symtab_node): Add has_ifunc_caller.
	* tree-profile.cc (check_ifunc_resolver): New.
	(is_caller_ifunc_resolver): Likewise.
	(tree_profiling): Don't instrument an IFUNC resolver nor its
	callees.

gcc/testsuite/ChangeLog:

	PR tree-optimization/114115
	* gcc.dg/pr114115.c: New test.
---
 gcc/cgraph.h                    | 18 +++++++
 gcc/testsuite/gcc.dg/pr114115.c | 24 +++++++++
 gcc/tree-profile.cc             | 92 +++++++++++++++++++++++++++++++++
 3 files changed, 134 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/pr114115.c

diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 47f35e8078d..ce99f4a5114 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -100,6 +100,21 @@ enum symbol_partitioning_class
    SYMBOL_DUPLICATE
 };
 
+/* Classification whether a function has any IFUNC resolver caller.  */
+enum ifunc_caller
+{
+  /* It is unknown if this function has any IFUNC resolver caller.  */
+  IFUNC_CALLER_UNKNOWN,
+  /* Work in progress to check if this function has any IFUNC resolver
+     caller.  */
+  IFUNC_CALLER_WIP,
+  /* This function has at least an IFUNC resolver caller, including
+     itself.  */
+  IFUNC_CALLER_TRUE,
+  /* This function doesn't have any IFUNC resolver caller.  */
+  IFUNC_CALLER_FALSE
+};
+
 /* Base of all entries in the symbol table.
    The symtab_node is inherited by cgraph and varpol nodes.  */
 struct GTY((desc ("%h.type"), tag ("SYMTAB_SYMBOL"),
@@ -121,6 +136,7 @@ public:
       used_from_other_partition (false), in_other_partition (false),
       address_taken (false), in_init_priority_hash (false),
       need_lto_streaming (false), offloadable (false), ifunc_resolver (false),
+      has_ifunc_caller (IFUNC_CALLER_UNKNOWN),
       order (false), next_sharing_asm_name (NULL),
       previous_sharing_asm_name (NULL), same_comdat_group (NULL), ref_list (),
       alias_target (NULL), lto_file_data (NULL), aux (NULL),
@@ -595,6 +611,8 @@ public:
   /* Set when symbol is an IFUNC resolver.  */
   unsigned ifunc_resolver : 1;
 
+  /* Classification whether a function has any IFUNC resolver caller.  */
+  ENUM_BITFIELD (ifunc_caller) has_ifunc_caller : 2;
 
   /* Ordering of all symtab entries.  */
   int order;
diff --git a/gcc/testsuite/gcc.dg/pr114115.c b/gcc/testsuite/gcc.dg/pr114115.c
new file mode 100644
index 00000000000..2629f591877
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr114115.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O0 -fprofile-generate -fdump-tree-optimized" } */
+/* { dg-require-profiling "-fprofile-generate" } */
+/* { dg-require-ifunc "" } */
+
+void *foo_ifunc2() __attribute__((ifunc("foo_resolver")));
+
+void bar(void)
+{
+}
+
+static int f3()
+{
+  bar ();
+  return 5;
+}
+
+void (*foo_resolver(void))(void)
+{
+  f3();
+  return bar;
+}
+
+/* { dg-final { scan-tree-dump-not "__gcov_indirect_call_profiler_v" "optimized" } } */
diff --git a/gcc/tree-profile.cc b/gcc/tree-profile.cc
index aed13e2b1bc..46478648b32 100644
--- a/gcc/tree-profile.cc
+++ b/gcc/tree-profile.cc
@@ -738,6 +738,72 @@ include_source_file_for_profile (const char *filename)
   return false;
 }
 
+/* Return true and set *DATA to true if NODE is an ifunc resolver.  */
+
+static bool
+check_ifunc_resolver (cgraph_node *node, void *data)
+{
+  if (node->ifunc_resolver)
+    {
+      bool *is_ifunc_resolver = (bool *) data;
+      *is_ifunc_resolver = true;
+      return true;
+    }
+  return false;
+}
+
+/* Return true if any caller of NODE is an ifunc resolver.  */
+
+static bool
+is_caller_ifunc_resolver (cgraph_node *node)
+{
+  if (node->has_ifunc_caller == IFUNC_CALLER_WIP)
+    gcc_unreachable ();
+
+  node->has_ifunc_caller = IFUNC_CALLER_WIP;
+  bool is_ifunc_resolver = false;
+
+  for (cgraph_edge *e = node->callers; e; e = e->next_caller)
+    {
+      /* Check for recursive call.  */
+      if (e->caller == node)
+	continue;
+
+      switch (e->caller->has_ifunc_caller)
+	{
+	case IFUNC_CALLER_UNKNOWN:
+	  e->caller->call_for_symbol_and_aliases (check_ifunc_resolver,
+						  &is_ifunc_resolver,
+						  true);
+	  if (is_ifunc_resolver)
+	    {
+	      e->caller->has_ifunc_caller = IFUNC_CALLER_TRUE;
+	      return true;
+	    }
+	  break;
+	case IFUNC_CALLER_TRUE:
+	  return true;
+	case IFUNC_CALLER_FALSE:
+	  /* This caller doesn't have any IFUNC resolver call.  Check
+	     the next caller.  */
+	  continue;
+
+	case IFUNC_CALLER_WIP:
+	  continue;
+	}
+
+      if (is_caller_ifunc_resolver (e->caller))
+	{
+	  e->caller->has_ifunc_caller = IFUNC_CALLER_TRUE;
+	  return true;
+	}
+      else
+	e->caller->has_ifunc_caller = IFUNC_CALLER_FALSE;
+    }
+
+  return false;
+}
+
 #ifndef HAVE_sync_compare_and_swapsi
 #define HAVE_sync_compare_and_swapsi 0
 #endif
@@ -848,6 +914,32 @@ tree_profiling (void)
 	    }
 	}
 
+      /* Do not instrument an IFUNC resolver nor its callees.  */
+      bool is_ifunc_resolver = false;
+      switch (node->has_ifunc_caller)
+	{
+	case IFUNC_CALLER_UNKNOWN:
+	  node->call_for_symbol_and_aliases (check_ifunc_resolver,
+					     &is_ifunc_resolver, true);
+	  if (is_ifunc_resolver || is_caller_ifunc_resolver (node))
+	    {
+	      node->has_ifunc_caller = IFUNC_CALLER_TRUE;
+	      continue;
+	    }
+	  else
+	    node->has_ifunc_caller = IFUNC_CALLER_FALSE;
+	  break;
+
+	case IFUNC_CALLER_TRUE:
+	  continue;
+
+	case IFUNC_CALLER_FALSE:
+	  break;
+
+	case IFUNC_CALLER_WIP:
+	  gcc_unreachable ();
+	}
+
       push_cfun (DECL_STRUCT_FUNCTION (node->decl));
 
       if (dump_file)
-- 
2.43.2


^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2024-03-05 21:47 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-02-26 22:53 [PATCH] tree-profile: Don't instrument an IFUNC resolver nor its callees H.J. Lu
2024-02-29 13:39 ` Jan Hubicka
2024-02-29 14:13   ` H.J. Lu
2024-02-29 14:34     ` Jan Hubicka
2024-02-29 14:40       ` H.J. Lu
2024-02-29 15:06         ` Jan Hubicka
2024-02-29 15:11           ` H.J. Lu
2024-03-05 21:46             ` H.J. Lu

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).