Fix noreturn discovery

Message ID 20211111132756.GE17431@kam.mff.cuni.cz
State Committed
Commit 61396dfb2acfe956d420b279b2becec1c4f81ba2
Headers
Series Fix noreturn discovery |

Commit Message

Jan Hubicka Nov. 11, 2021, 1:27 p.m. UTC
  Hi,
this patch fixes ipa-pure-const handling of noreturn flags.  It is not
safe to set it for interposable symbols and we should also set it for
aliases (just like we do for other flags).  This patch merely copies other
flag handling and implements it here.

Bootstrapped/regtested x86_64-linux, will commit it shortly.

Honza

gcc/ChangeLog:

2021-11-11  Jan Hubicka  <hubicka@ucw.cz>

	* cgraph.c (set_noreturn_flag_1): New function.
	(cgraph_node::set_noreturn_flag): New member function
	* cgraph.h (cgraph_node::set_noreturn_flags): Declare.
	* ipa-pure-const.c (pass_local_pure_const::execute): Use it.
  

Patch

diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index c67d300e7a4..466b66d5ba5 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -2614,6 +2614,53 @@  cgraph_node::set_malloc_flag (bool malloc_p)
   return changed;
 }
 
+/* Worker to set noreturng flag.  */
+static void
+set_noreturn_flag_1 (cgraph_node *node, bool noreturn_p, bool *changed)
+{
+  if (noreturn_p && !TREE_THIS_VOLATILE (node->decl))
+    {
+      TREE_THIS_VOLATILE (node->decl) = true;
+      *changed = true;
+    }
+
+  ipa_ref *ref;
+  FOR_EACH_ALIAS (node, ref)
+    {
+      cgraph_node *alias = dyn_cast<cgraph_node *> (ref->referring);
+      if (!noreturn_p || alias->get_availability () > AVAIL_INTERPOSABLE)
+	set_noreturn_flag_1 (alias, noreturn_p, changed);
+    }
+
+  for (cgraph_edge *e = node->callers; e; e = e->next_caller)
+    if (e->caller->thunk
+	&& (!noreturn_p || e->caller->get_availability () > AVAIL_INTERPOSABLE))
+      set_noreturn_flag_1 (e->caller, noreturn_p, changed);
+}
+
+/* Set TREE_THIS_VOLATILE on NODE's decl and on NODE's aliases if any.  */
+
+bool
+cgraph_node::set_noreturn_flag (bool noreturn_p)
+{
+  bool changed = false;
+
+  if (!noreturn_p || get_availability () > AVAIL_INTERPOSABLE)
+    set_noreturn_flag_1 (this, noreturn_p, &changed);
+  else
+    {
+      ipa_ref *ref;
+
+      FOR_EACH_ALIAS (this, ref)
+	{
+	  cgraph_node *alias = dyn_cast<cgraph_node *> (ref->referring);
+	  if (!noreturn_p || alias->get_availability () > AVAIL_INTERPOSABLE)
+	    set_noreturn_flag_1 (alias, noreturn_p, &changed);
+	}
+    }
+  return changed;
+}
+
 /* Worker to set_const_flag.  */
 
 static void
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 0a1f7c8960e..e42e305cdb6 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -1167,6 +1167,10 @@  struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
      if any.  */
   bool set_malloc_flag (bool malloc_p);
 
+  /* SET TREE_THIS_VOLATILE on cgraph_node's decl and on aliases of the node
+     if any.  */
+  bool set_noreturn_flag (bool noreturn_p);
+
   /* If SET_CONST is true, mark function, aliases and thunks to be ECF_CONST.
     If SET_CONST if false, clear the flag.
 
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index 505ed4f8a3b..84a028bcf8e 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -2132,11 +2132,10 @@  pass_local_pure_const::execute (function *fun)
 		 current_function_name ());
 
       /* Update declaration and reduce profile to executed once.  */
-      TREE_THIS_VOLATILE (current_function_decl) = 1;
+      if (cgraph_node::get (current_function_decl)->set_noreturn_flag (true))
+	changed = true;
       if (node->frequency > NODE_FREQUENCY_EXECUTED_ONCE)
 	node->frequency = NODE_FREQUENCY_EXECUTED_ONCE;
-
-      changed = true;
     }
 
   switch (l->pure_const_state)