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