]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fix noreturn discovery.
authorJan Hubicka <jh@suse.cz>
Thu, 11 Nov 2021 13:35:10 +0000 (14:35 +0100)
committerJan Hubicka <jh@suse.cz>
Thu, 11 Nov 2021 13:35:10 +0000 (14:35 +0100)
Fix 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.

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.

gcc/cgraph.c
gcc/cgraph.h
gcc/ipa-pure-const.c

index c67d300e7a4a2c2929c7c5ce6a9e9665d54ebb3d..466b66d5ba5e975ef11d3a9b99a6a96dc716aade 100644 (file)
@@ -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
index 0a1f7c8960eb8fd77967d7fad5bf80c8a6026788..e42e305cdb62b733b62733cfd3ebb982612b8597 100644 (file)
@@ -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.
 
index 505ed4f8a3bc83b7a83f1e1dc702de07a3556004..84a028bcf8e8d5217ba44ae0f05dc895c43d0f7e 100644 (file)
@@ -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)