#include "cgraph.h"
#include "graph.h"
#include "cfgloop.h"
+#include "except.h"
/* Global variables used to communicate with passes. */
bool in_gimple_form;
/* The root of the compilation pass tree, once constructed. */
-static struct tree_opt_pass *all_passes, *all_ipa_passes;
-
-/* Pass: dump the gimplified, inlined, functions. */
-
-static struct tree_opt_pass pass_gimple =
-{
- "gimple", /* name */
- NULL, /* gate */
- NULL, /* execute */
- NULL, /* sub */
- NULL, /* next */
- 0, /* static_pass_number */
- 0, /* tv_id */
- 0, /* properties_required */
- PROP_gimple_any, /* properties_provided */
- 0, /* properties_destroyed */
- 0, /* todo_flags_start */
- TODO_dump_func, /* todo_flags_finish */
- 0 /* letter */
-};
+static struct tree_opt_pass *all_passes, *all_ipa_passes, * all_lowering_passes;
/* Gate: execute, or not, all of the non-trivial optimizations. */
0 /* letter */
};
+/* Pass: fixup_cfg - IPA passes or compilation of earlier functions might've
+ changed some properties - such as marked functions nothrow. Remove now
+ redundant edges and basic blocks. */
+
+static void
+execute_fixup_cfg (void)
+{
+ basic_block bb;
+ block_stmt_iterator bsi;
+
+ if (cfun->eh)
+ FOR_EACH_BB (bb)
+ {
+ for (bsi = bsi_start (bb); !bsi_end_p (bsi); bsi_next (&bsi))
+ {
+ tree stmt = bsi_stmt (bsi);
+ tree call = get_call_expr_in (stmt);
+
+ if (call && call_expr_flags (call) & (ECF_CONST | ECF_PURE))
+ TREE_SIDE_EFFECTS (call) = 0;
+ if (!tree_could_throw_p (stmt) && lookup_stmt_eh_region (stmt))
+ remove_stmt_from_eh_region (stmt);
+ }
+ tree_purge_dead_eh_edges (bb);
+ }
+
+ cleanup_tree_cfg ();
+}
+
+static struct tree_opt_pass pass_fixup_cfg =
+{
+ NULL, /* name */
+ NULL, /* gate */
+ execute_fixup_cfg, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ 0, /* tv_id */
+ PROP_cfg, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ 0, /* todo_flags_finish */
+ 0 /* letter */
+};
/* Do the actions required to initialize internal data structures used
in tree-ssa optimization passes. */
NEXT_PASS (pass_ipa_inline);
*p = NULL;
- p = &all_passes;
- NEXT_PASS (pass_gimple);
+ /* All passes needed to lower the function into shape optimizers can operate
+ on. These passes are performed before interprocedural passes, unlike rest
+ of local passes (all_passes). */
+ p = &all_lowering_passes;
NEXT_PASS (pass_remove_useless_stmts);
NEXT_PASS (pass_mudflap_1);
- NEXT_PASS (pass_lower_cf);
- NEXT_PASS (pass_lower_eh);
- NEXT_PASS (pass_build_cfg);
- NEXT_PASS (pass_pre_expand);
+ NEXT_PASS (pass_lower_cf);
+ NEXT_PASS (pass_lower_eh);
+ NEXT_PASS (pass_build_cfg);
+ NEXT_PASS (pass_lower_complex);
+ NEXT_PASS (pass_lower_vector);
+ NEXT_PASS (pass_warn_function_return);
NEXT_PASS (pass_tree_profile);
+ *p = NULL;
+
+ p = &all_passes;
+ NEXT_PASS (pass_fixup_cfg);
NEXT_PASS (pass_init_datastructures);
NEXT_PASS (pass_all_optimizations);
- NEXT_PASS (pass_warn_function_return);
+ NEXT_PASS (pass_warn_function_noreturn);
NEXT_PASS (pass_mudflap_2);
NEXT_PASS (pass_free_datastructures);
NEXT_PASS (pass_expand);
NEXT_PASS (pass_vrp);
NEXT_PASS (pass_copy_prop);
NEXT_PASS (pass_dce);
+ NEXT_PASS (pass_merge_phi);
NEXT_PASS (pass_dominator);
- NEXT_PASS (pass_merge_phi);
NEXT_PASS (pass_phiopt);
NEXT_PASS (pass_may_alias);
NEXT_PASS (pass_tail_recursion);
we add may_alias right after fold builtins
which can create arbitrary GIMPLE. */
NEXT_PASS (pass_may_alias);
+ NEXT_PASS (pass_cse_reciprocals);
NEXT_PASS (pass_split_crit_edges);
+ NEXT_PASS (pass_reassoc);
NEXT_PASS (pass_pre);
NEXT_PASS (pass_sink_code);
NEXT_PASS (pass_loop);
NEXT_PASS (pass_dominator);
NEXT_PASS (pass_copy_prop);
- NEXT_PASS (pass_dce);
+ NEXT_PASS (pass_cd_dce);
/* FIXME: If DCE is not run before checking for uninitialized uses,
we may get false warnings (e.g., testsuite/gcc.dg/uninit-5.c).
However, this also causes us to misdiagnose cases that should be
variable. Using a representation like Gated Single Assignment
may help. */
NEXT_PASS (pass_late_warn_uninitialized);
- NEXT_PASS (pass_cd_dce);
NEXT_PASS (pass_dse);
NEXT_PASS (pass_forwprop);
NEXT_PASS (pass_phiopt);
NEXT_PASS (pass_copy_prop);
NEXT_PASS (pass_lim);
NEXT_PASS (pass_unswitch);
+ NEXT_PASS (pass_scev_cprop);
NEXT_PASS (pass_record_bounds);
NEXT_PASS (pass_linear_transform);
NEXT_PASS (pass_iv_canon);
NEXT_PASS (pass_if_conversion);
NEXT_PASS (pass_vectorize);
+ /* NEXT_PASS (pass_may_alias) cannot be done again because the
+ vectorizer creates alias relations that are not supported by
+ pass_may_alias. */
NEXT_PASS (pass_lower_vector_ssa);
NEXT_PASS (pass_complete_unroll);
NEXT_PASS (pass_iv_optimize);
#undef NEXT_PASS
+ register_dump_files (all_lowering_passes, false, PROP_gimple_any);
register_dump_files (all_passes, false, PROP_gimple_any
| PROP_gimple_lcf
| PROP_gimple_leh
while (pass);
}
+void
+tree_lowering_passes (tree fn)
+{
+ tree saved_current_function_decl = current_function_decl;
+
+ current_function_decl = fn;
+ push_cfun (DECL_STRUCT_FUNCTION (fn));
+ tree_register_cfg_hooks ();
+ bitmap_obstack_initialize (NULL);
+ execute_pass_list (all_lowering_passes);
+ free_dominance_info (CDI_POST_DOMINATORS);
+ compact_blocks ();
+ current_function_decl = saved_current_function_decl;
+ bitmap_obstack_release (NULL);
+ pop_cfun ();
+}
+
/* Execute all IPA passes. */
void
ipa_passes (void)
{
- execute_pass_list (all_ipa_passes);
+ bitmap_obstack_initialize (NULL);
+ execute_pass_list (all_ipa_passes);
+ bitmap_obstack_release (NULL);
}
\f
{
struct cgraph_edge *e;
- saved_node = cgraph_clone_node (node);
+ saved_node = cgraph_clone_node (node, node->count, 1);
for (e = saved_node->callees; e; e = e->next_callee)
if (!e->inline_failed)
cgraph_clone_inlined_nodes (e, true);
}
cfun->saved_static_chain_decl = cfun->static_chain_decl;
- cfun->saved_tree = save_body (fndecl, &cfun->saved_args,
- &cfun->saved_static_chain_decl);
+ save_body (fndecl, &cfun->saved_args, &cfun->saved_static_chain_decl);
}
if (flag_inline_trees)
bitmap_obstack_initialize (NULL);
bitmap_obstack_initialize (®_obstack); /* FIXME, only at RTL generation*/
+ tree_register_cfg_hooks ();
/* Perform all tree transforms and optimizations. */
execute_pass_list (all_passes);
bitmap_obstack_release (NULL);
/* Restore original body if still needed. */
- if (cfun->saved_tree)
+ if (cfun->saved_cfg)
{
- DECL_SAVED_TREE (fndecl) = cfun->saved_tree;
DECL_ARGUMENTS (fndecl) = cfun->saved_args;
+ cfun->cfg = cfun->saved_cfg;
+ cfun->eh = cfun->saved_eh;
+ cfun->saved_cfg = NULL;
+ cfun->saved_eh = NULL;
+ cfun->saved_args = NULL_TREE;
cfun->static_chain_decl = cfun->saved_static_chain_decl;
-
+ cfun->saved_static_chain_decl = NULL;
/* When not in unit-at-a-time mode, we must preserve out of line copy
representing node before inlining. Restore original outgoing edges
using clone we created earlier. */
{
struct cgraph_edge *e;
+ node = cgraph_node (current_function_decl);
cgraph_node_remove_callees (node);
node->callees = saved_node->callees;
saved_node->callees = NULL;