From 0921507773eedadca1216a9edca954af240b7a49 Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Thu, 22 Oct 2015 12:46:16 +0200
Subject: [PATCH] Pass manager: add support for termination of pass list
gcc/ChangeLog:
2015-10-30 Martin Liska <mliska@suse.cz>
* function.c (pop_cfun): Set cfun and current_function_decl to
NULL if the cfun_stack is empty.
* passes.c (do_per_function_toporder): Push to cfun before
calling the pass manager.
(execute_one_pass): Handle TODO_discard_function.
(execute_pass_list_1): Terminate if current function is null.
(execute_pass_list): Do not push and pop function.
* tree-pass.h: Define new TODO_discard_function.
---
gcc/function.c | 7 +++++++
gcc/passes.c | 32 ++++++++++++++++++++++++++++----
gcc/tree-pass.h | 3 +++
4 files changed, 39 insertions(+), 6 deletions(-)
@@ -4756,6 +4756,13 @@ push_cfun (struct function *new_cfun)
void
pop_cfun (void)
{
+ if (cfun_stack.is_empty ())
+ {
+ set_cfun (NULL);
+ current_function_decl = NULL_TREE;
+ return;
+ }
+
struct function *new_cfun = cfun_stack.pop ();
/* When in_dummy_function, we do have a cfun but current_function_decl is
NULL. We also allow pushing NULL cfun and subsequently changing
@@ -1706,7 +1706,12 @@ do_per_function_toporder (void (*callback) (function *, void *data), void *data)
order[i] = NULL;
node->process = 0;
if (node->has_gimple_body_p ())
- callback (DECL_STRUCT_FUNCTION (node->decl), data);
+ {
+ struct function *fn = DECL_STRUCT_FUNCTION (node->decl);
+ push_cfun (fn);
+ callback (fn, data);
+ pop_cfun ();
+ }
}
symtab->remove_cgraph_removal_hook (hook);
}
@@ -2347,6 +2352,23 @@ execute_one_pass (opt_pass *pass)
current_pass = NULL;
+ if (todo_after & TODO_discard_function)
+ {
+ gcc_assert (cfun);
+ /* As cgraph_node::release_body expects release dominators info,
+ we have to release it. */
+ if (dom_info_available_p (CDI_DOMINATORS))
+ free_dominance_info (CDI_DOMINATORS);
+
+ if (dom_info_available_p (CDI_POST_DOMINATORS))
+ free_dominance_info (CDI_POST_DOMINATORS);
+
+ tree fn = cfun->decl;
+ pop_cfun ();
+ gcc_assert (!cfun);
+ cgraph_node::get (fn)->release_body ();
+ }
+
/* Signal this is a suitable GC collection point. */
if (!((todo_after | pass->todo_flags_finish) & TODO_do_not_ggc_collect))
ggc_collect ();
@@ -2361,6 +2383,9 @@ execute_pass_list_1 (opt_pass *pass)
{
gcc_assert (pass->type == GIMPLE_PASS
|| pass->type == RTL_PASS);
+
+ if (cfun == NULL)
+ return;
if (execute_one_pass (pass) && pass->sub)
execute_pass_list_1 (pass->sub);
@@ -2372,14 +2397,13 @@ execute_pass_list_1 (opt_pass *pass)
void
execute_pass_list (function *fn, opt_pass *pass)
{
- push_cfun (fn);
+ gcc_assert (fn == cfun);
execute_pass_list_1 (pass);
- if (fn->cfg)
+ if (cfun && fn->cfg)
{
free_dominance_info (CDI_DOMINATORS);
free_dominance_info (CDI_POST_DOMINATORS);
}
- pop_cfun ();
}
/* Write out all LTO data. */
@@ -300,6 +300,9 @@ protected:
/* Rebuild the callgraph edges. */
#define TODO_rebuild_cgraph_edges (1 << 22)
+/* Release function body and stop pass manager. */
+#define TODO_discard_function (1 << 23)
+
/* Internally used in execute_function_todo(). */
#define TODO_update_ssa_any \
(TODO_update_ssa \
--
2.6.2