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)
