/* Top level of GCC compilers (cc1, cc1plus, etc.)
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
/* Don't output anything when a tentative file-scope definition
is seen. But at end of compilation, do output code for them.
- We do output all variables when unit-at-a-time is active and rely on
+ We do output all variables and rely on
callgraph code to defer them except for forward declarations
(see gcc.c-torture/compile/920624-1.c) */
if ((at_end
void
finish_optimization_passes (void)
{
- enum tree_dump_index i;
+ int i;
struct dump_file_info *dfi;
char *name;
{
{
GIMPLE_PASS,
- NULL, /* name */
+ "*rest_of_compilation", /* name */
gate_rest_of_compilation, /* gate */
NULL, /* execute */
NULL, /* sub */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- 0, /* tv_id */
+ TV_NONE, /* tv_id */
PROP_rtl, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
pass->static_pass_number = id;
if (passes_by_id_size <= id)
{
- passes_by_id = xrealloc (passes_by_id, (id + 1) * sizeof (void *));
+ passes_by_id = XRESIZEVEC (struct opt_pass *, passes_by_id, id + 1);
memset (passes_by_id + passes_by_id_size, 0,
(id + 1 - passes_by_id_size) * sizeof (void *));
passes_by_id_size = id + 1;
to do this depth first, and independent of whether the pass is
enabled or not. */
-static void
+void
register_one_dump_file (struct opt_pass *pass)
{
char *dot_name, *flag_name, *glob_name;
int new_properties = (properties | pass->properties_provided)
& ~pass->properties_destroyed;
- if (pass->name)
+ if (pass->name && pass->name[0] != '*')
register_one_dump_file (pass);
if (pass->sub)
pass is already in the list. */
if (pass->static_pass_number)
{
- struct opt_pass *new;
+ struct opt_pass *new_pass;
- new = xmalloc (sizeof (*new));
- memcpy (new, pass, sizeof (*new));
- new->next = NULL;
+ new_pass = XNEW (struct opt_pass);
+ memcpy (new_pass, pass, sizeof (*new_pass));
+ new_pass->next = NULL;
- new->todo_flags_start &= ~TODO_mark_first_instance;
+ new_pass->todo_flags_start &= ~TODO_mark_first_instance;
/* Indicate to register_dump_files that this pass has duplicates,
and so it should rename the dump file. The first instance will
if (pass->name)
{
pass->static_pass_number -= 1;
- new->static_pass_number = -pass->static_pass_number;
+ new_pass->static_pass_number = -pass->static_pass_number;
}
- *list = new;
+ *list = new_pass;
}
else
{
backend might produce already lowered functions that are not processed
by these passes. */
p = &all_lowering_passes;
+ NEXT_PASS (pass_warn_unused_result);
+ NEXT_PASS (pass_diagnose_omp_blocks);
NEXT_PASS (pass_remove_useless_stmts);
NEXT_PASS (pass_mudflap_1);
NEXT_PASS (pass_lower_omp);
NEXT_PASS (pass_inline_parameters);
*p = NULL;
- /* Interprocedural optimization passes.
- All these passes are ignored in -fno-unit-at-a-time
- except for subpasses of early_local_passes. */
+ /* Interprocedural optimization passes. */
p = &all_ipa_passes;
NEXT_PASS (pass_ipa_function_and_variable_visibility);
NEXT_PASS (pass_ipa_early_inline);
NEXT_PASS (pass_early_local_passes);
{
struct opt_pass **p = &pass_early_local_passes.pass.sub;
+ NEXT_PASS (pass_fixup_cfg);
NEXT_PASS (pass_tree_profile);
NEXT_PASS (pass_cleanup_cfg);
NEXT_PASS (pass_init_datastructures);
NEXT_PASS (pass_expand_omp);
+
+ NEXT_PASS (pass_referenced_vars);
+ NEXT_PASS (pass_build_ssa);
+ NEXT_PASS (pass_early_warn_uninitialized);
NEXT_PASS (pass_all_early_optimizations);
{
struct opt_pass **p = &pass_all_early_optimizations.pass.sub;
- NEXT_PASS (pass_referenced_vars);
- NEXT_PASS (pass_reset_cc_flags);
- NEXT_PASS (pass_build_ssa);
- NEXT_PASS (pass_expand_omp_ssa);
- NEXT_PASS (pass_early_warn_uninitialized);
NEXT_PASS (pass_rebuild_cgraph_edges);
NEXT_PASS (pass_early_inline);
- NEXT_PASS (pass_cleanup_cfg);
+ NEXT_PASS (pass_remove_cgraph_callee_edges);
NEXT_PASS (pass_rename_ssa_copies);
NEXT_PASS (pass_ccp);
NEXT_PASS (pass_forwprop);
- NEXT_PASS (pass_update_address_taken);
- NEXT_PASS (pass_simple_dse);
+ /* pass_build_ealias is a dummy pass that ensures that we
+ execute TODO_rebuild_alias at this point. Re-building
+ alias information also rewrites no longer addressed
+ locals into SSA form if possible. */
+ NEXT_PASS (pass_build_ealias);
NEXT_PASS (pass_sra_early);
NEXT_PASS (pass_copy_prop);
NEXT_PASS (pass_merge_phi);
- NEXT_PASS (pass_dce);
- NEXT_PASS (pass_update_address_taken);
- NEXT_PASS (pass_simple_dse);
+ NEXT_PASS (pass_cd_dce);
NEXT_PASS (pass_tail_recursion);
+ NEXT_PASS (pass_convert_switch);
+ NEXT_PASS (pass_cleanup_eh);
NEXT_PASS (pass_profile);
- NEXT_PASS (pass_release_ssa_names);
+ NEXT_PASS (pass_local_pure_const);
}
+ NEXT_PASS (pass_release_ssa_names);
NEXT_PASS (pass_rebuild_cgraph_edges);
+ NEXT_PASS (pass_inline_parameters);
}
NEXT_PASS (pass_ipa_increase_alignment);
NEXT_PASS (pass_ipa_matrix_reorg);
/* These passes are run after IPA passes on every function that is being
output to the assembler file. */
p = &all_passes;
- NEXT_PASS (pass_O0_always_inline);
NEXT_PASS (pass_all_optimizations);
{
struct opt_pass **p = &pass_all_optimizations.pass.sub;
- /* pass_build_alias is a dummy pass that ensures that we
- execute TODO_rebuild_alias at this point. */
- NEXT_PASS (pass_build_alias);
- NEXT_PASS (pass_return_slot);
+ NEXT_PASS (pass_remove_cgraph_callee_edges);
+ /* Initial scalar cleanups before alias computation.
+ They ensure memory accesses are not indirect wherever possible. */
+ NEXT_PASS (pass_strip_predict_hints);
+ NEXT_PASS (pass_update_address_taken);
NEXT_PASS (pass_rename_ssa_copies);
-
- /* Initial scalar cleanups. */
NEXT_PASS (pass_complete_unrolli);
NEXT_PASS (pass_ccp);
+ NEXT_PASS (pass_forwprop);
+ NEXT_PASS (pass_call_cdce);
+ /* pass_build_alias is a dummy pass that ensures that we
+ execute TODO_rebuild_alias at this point. Re-building
+ alias information also rewrites no longer addressed
+ locals into SSA form if possible. */
+ NEXT_PASS (pass_build_alias);
+ NEXT_PASS (pass_return_slot);
NEXT_PASS (pass_phiprop);
NEXT_PASS (pass_fre);
- NEXT_PASS (pass_dce);
- NEXT_PASS (pass_forwprop);
NEXT_PASS (pass_copy_prop);
NEXT_PASS (pass_merge_phi);
NEXT_PASS (pass_vrp);
NEXT_PASS (pass_dce);
NEXT_PASS (pass_cselim);
- NEXT_PASS (pass_dominator);
- /* The only const/copy propagation opportunities left after
- DOM should be due to degenerate PHI nodes. So rather than
- run the full propagators, run a specialized pass which
- only examines PHIs to discover const/copy propagation
- opportunities. */
- NEXT_PASS (pass_phi_only_cprop);
NEXT_PASS (pass_tree_ifcombine);
NEXT_PASS (pass_phiopt);
NEXT_PASS (pass_tail_recursion);
NEXT_PASS (pass_sra);
NEXT_PASS (pass_rename_ssa_copies);
NEXT_PASS (pass_dominator);
-
/* The only const/copy propagation opportunities left after
DOM should be due to degenerate PHI nodes. So rather than
run the full propagators, run a specialized pass which
only examines PHIs to discover const/copy propagation
opportunities. */
NEXT_PASS (pass_phi_only_cprop);
-
+ NEXT_PASS (pass_dse);
NEXT_PASS (pass_reassoc);
NEXT_PASS (pass_dce);
- NEXT_PASS (pass_dse);
NEXT_PASS (pass_forwprop);
NEXT_PASS (pass_phiopt);
NEXT_PASS (pass_object_sizes);
- NEXT_PASS (pass_store_ccp);
+ NEXT_PASS (pass_ccp);
NEXT_PASS (pass_copy_prop);
NEXT_PASS (pass_fold_builtins);
NEXT_PASS (pass_cse_sincos);
+ NEXT_PASS (pass_optimize_bswap);
NEXT_PASS (pass_split_crit_edges);
NEXT_PASS (pass_pre);
NEXT_PASS (pass_sink_code);
NEXT_PASS (pass_copy_prop);
NEXT_PASS (pass_dce_loop);
NEXT_PASS (pass_lim);
- NEXT_PASS (pass_predcom);
NEXT_PASS (pass_tree_unswitch);
NEXT_PASS (pass_scev_cprop);
- NEXT_PASS (pass_empty_loop);
NEXT_PASS (pass_record_bounds);
NEXT_PASS (pass_check_data_deps);
NEXT_PASS (pass_loop_distribution);
NEXT_PASS (pass_linear_transform);
+ NEXT_PASS (pass_graphite_transforms);
+ {
+ struct opt_pass **p = &pass_graphite_transforms.pass.sub;
+ NEXT_PASS (pass_dce_loop);
+ NEXT_PASS (pass_lim);
+ }
NEXT_PASS (pass_iv_canon);
NEXT_PASS (pass_if_conversion);
NEXT_PASS (pass_vectorize);
NEXT_PASS (pass_lower_vector_ssa);
NEXT_PASS (pass_dce_loop);
}
+ NEXT_PASS (pass_predcom);
NEXT_PASS (pass_complete_unroll);
+ NEXT_PASS (pass_slp_vectorize);
NEXT_PASS (pass_parallelize_loops);
NEXT_PASS (pass_loop_prefetch);
NEXT_PASS (pass_iv_optimize);
NEXT_PASS (pass_reassoc);
NEXT_PASS (pass_vrp);
NEXT_PASS (pass_dominator);
-
/* The only const/copy propagation opportunities left after
DOM should be due to degenerate PHI nodes. So rather than
run the full propagators, run a specialized pass which
only examines PHIs to discover const/copy propagation
opportunities. */
NEXT_PASS (pass_phi_only_cprop);
-
NEXT_PASS (pass_cd_dce);
NEXT_PASS (pass_tracer);
NEXT_PASS (pass_tail_calls);
NEXT_PASS (pass_rename_ssa_copies);
NEXT_PASS (pass_uncprop);
- NEXT_PASS (pass_del_ssa);
- NEXT_PASS (pass_nrv);
- NEXT_PASS (pass_mark_used_blocks);
- NEXT_PASS (pass_cleanup_cfg_post_optimizing);
+ NEXT_PASS (pass_local_pure_const);
}
- NEXT_PASS (pass_warn_function_noreturn);
- NEXT_PASS (pass_free_datastructures);
+ NEXT_PASS (pass_cleanup_eh);
+ NEXT_PASS (pass_nrv);
NEXT_PASS (pass_mudflap_2);
- NEXT_PASS (pass_free_cfg_annotations);
+ NEXT_PASS (pass_cleanup_cfg_post_optimizing);
+ NEXT_PASS (pass_warn_function_noreturn);
+
NEXT_PASS (pass_expand);
+
NEXT_PASS (pass_rest_of_compilation);
{
struct opt_pass **p = &pass_rest_of_compilation.pass.sub;
NEXT_PASS (pass_df_initialize_opt);
NEXT_PASS (pass_cse);
NEXT_PASS (pass_rtl_fwprop);
- NEXT_PASS (pass_gcse);
+ NEXT_PASS (pass_rtl_cprop);
+ NEXT_PASS (pass_rtl_pre);
+ NEXT_PASS (pass_rtl_hoist);
+ NEXT_PASS (pass_rtl_cprop);
+ NEXT_PASS (pass_rtl_store_motion);
+ NEXT_PASS (pass_cse_after_global_opts);
NEXT_PASS (pass_rtl_ifcvt);
/* Perform loop optimizations. It might be better to do them a bit
sooner, but we want the profile feedback to work more
*p = NULL;
}
NEXT_PASS (pass_web);
- NEXT_PASS (pass_jump_bypass);
+ NEXT_PASS (pass_rtl_cprop);
NEXT_PASS (pass_cse2);
NEXT_PASS (pass_rtl_dse1);
NEXT_PASS (pass_rtl_fwprop_addr);
- NEXT_PASS (pass_regclass_init);
+ NEXT_PASS (pass_reginfo_init);
NEXT_PASS (pass_inc_dec);
NEXT_PASS (pass_initialize_regs);
- NEXT_PASS (pass_outof_cfg_layout_mode);
NEXT_PASS (pass_ud_rtl_dce);
NEXT_PASS (pass_combine);
NEXT_PASS (pass_if_after_combine);
NEXT_PASS (pass_partition_blocks);
NEXT_PASS (pass_regmove);
+ NEXT_PASS (pass_outof_cfg_layout_mode);
NEXT_PASS (pass_split_all_insns);
NEXT_PASS (pass_lower_subreg2);
NEXT_PASS (pass_df_initialize_no_opt);
NEXT_PASS (pass_stack_ptr_mod);
NEXT_PASS (pass_mode_switching);
- NEXT_PASS (pass_see);
NEXT_PASS (pass_match_asm_constraints);
NEXT_PASS (pass_sms);
NEXT_PASS (pass_sched);
NEXT_PASS (pass_subregs_of_mode_init);
- NEXT_PASS (pass_local_alloc);
- NEXT_PASS (pass_global_alloc);
+ NEXT_PASS (pass_ira);
NEXT_PASS (pass_subregs_of_mode_finish);
NEXT_PASS (pass_postreload);
{
NEXT_PASS (pass_branch_target_load_optimize1);
NEXT_PASS (pass_thread_prologue_and_epilogue);
NEXT_PASS (pass_rtl_dse2);
- NEXT_PASS (pass_rtl_seqabstr);
NEXT_PASS (pass_stack_adjustments);
NEXT_PASS (pass_peephole2);
NEXT_PASS (pass_if_after_reload);
/* Register the passes with the tree dump code. */
register_dump_files (all_lowering_passes, PROP_gimple_any);
- all_lowering_passes->todo_flags_start |= TODO_set_props;
register_dump_files (all_ipa_passes,
PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
| PROP_cfg);
{
struct cgraph_node *node;
for (node = cgraph_nodes; node; node = node->next)
- if (node->analyzed)
+ if (node->analyzed && gimple_has_body_p (node->decl)
+ && (!node->clone_of || node->decl != node->clone_of->decl))
{
push_cfun (DECL_STRUCT_FUNCTION (node->decl));
current_function_decl = node->decl;
else
{
gcc_assert (!order);
- order = ggc_alloc (sizeof (*order) * cgraph_n_nodes);
+ order = GGC_NEWVEC (struct cgraph_node *, cgraph_n_nodes);
nnodes = cgraph_postorder (order);
for (i = nnodes - 1; i >= 0; i--)
+ order[i]->process = 1;
+ for (i = nnodes - 1; i >= 0; i--)
{
struct cgraph_node *node = order[i];
/* Allow possibly removed nodes to be garbage collected. */
order[i] = NULL;
+ node->process = 0;
if (node->analyzed && (node->needed || node->reachable))
{
push_cfun (DECL_STRUCT_FUNCTION (node->decl));
SSA form to become out-of-date (see PR 22037). So, even
if the parent pass had not scheduled an SSA update, we may
still need to do one. */
- if (!(flags & TODO_update_ssa_any) && need_ssa_update_p ())
+ if (!(flags & TODO_update_ssa_any) && need_ssa_update_p (cfun))
flags |= TODO_update_ssa;
}
cfun->last_verified &= ~TODO_verify_ssa;
}
+ if (flags & TODO_update_address_taken)
+ execute_update_addresses_taken (true);
+
if (flags & TODO_rebuild_alias)
{
+ if (!(flags & TODO_update_address_taken))
+ execute_update_addresses_taken (true);
compute_may_aliases ();
- cfun->curr_properties |= PROP_alias;
}
if (flags & TODO_remove_unused_locals)
remove_unused_locals ();
- if ((flags & TODO_dump_func)
- && dump_file && current_function_decl)
+ if ((flags & TODO_dump_func) && dump_file && current_function_decl)
{
if (cfun->curr_properties & PROP_trees)
- dump_function_to_file (current_function_decl,
- dump_file, dump_flags);
+ dump_function_to_file (current_function_decl, dump_file, dump_flags);
else
{
if (dump_flags & TDF_SLIM)
else
print_rtl (dump_file, get_insns ());
- if (cfun->curr_properties & PROP_cfg
+ if ((cfun->curr_properties & PROP_cfg)
&& graph_dump_format != no_graph
&& (dump_flags & TDF_GRAPH))
print_rtl_graph_with_bb (dump_file_name, get_insns ());
execute_todo (unsigned int flags)
{
#if defined ENABLE_CHECKING
- if (need_ssa_update_p ())
+ if (cfun
+ && need_ssa_update_p (cfun))
gcc_assert (flags & TODO_update_ssa_any);
#endif
cgraph_remove_unreachable_nodes (true, dump_file);
}
- if ((flags & TODO_dump_cgraph)
- && dump_file && !current_function_decl)
+ if ((flags & TODO_dump_cgraph) && dump_file && !current_function_decl)
{
gcc_assert (!cfun);
dump_cgraph (dump_file);
}
if (flags & TODO_ggc_collect)
- {
- ggc_collect ();
- }
+ ggc_collect ();
/* Now that the dumping has been done, we can get rid of the optional
df problems. */
static void
update_properties_after_pass (void *data)
{
- struct opt_pass *pass = data;
+ struct opt_pass *pass = (struct opt_pass *) data;
cfun->curr_properties = (cfun->curr_properties | pass->properties_provided)
& ~pass->properties_destroyed;
}
static void
add_ipa_transform_pass (void *data)
{
- struct ipa_opt_pass *ipa_pass = (struct ipa_opt_pass *) data;
+ struct ipa_opt_pass_d *ipa_pass = (struct ipa_opt_pass_d *) data;
VEC_safe_push (ipa_opt_pass, heap, cfun->ipa_transforms_to_apply, ipa_pass);
}
/* Execute summary generation for all of the passes in IPA_PASS. */
static void
-execute_ipa_summary_passes (struct ipa_opt_pass *ipa_pass)
+execute_ipa_summary_passes (struct ipa_opt_pass_d *ipa_pass)
{
while (ipa_pass)
{
ipa_pass->generate_summary ();
pass_fini_dump_file (pass);
}
- ipa_pass = (struct ipa_opt_pass *)ipa_pass->pass.next;
+ ipa_pass = (struct ipa_opt_pass_d *)ipa_pass->pass.next;
}
}
static void
execute_one_ipa_transform_pass (struct cgraph_node *node,
- struct ipa_opt_pass *ipa_pass)
+ struct ipa_opt_pass_d *ipa_pass)
{
struct opt_pass *pass = &ipa_pass->pass;
unsigned int todo_after = 0;
execute_todo (ipa_pass->function_transform_todo_flags_start);
/* If a timevar is present, start it. */
- if (pass->tv_id)
+ if (pass->tv_id != TV_NONE)
timevar_push (pass->tv_id);
/* Do it! */
todo_after = ipa_pass->function_transform (node);
/* Stop timevar. */
- if (pass->tv_id)
+ if (pass->tv_id != TV_NONE)
timevar_pop (pass->tv_id);
/* Run post-pass cleanup and verification. */
pass_fini_dump_file (pass);
current_pass = NULL;
- /* Reset in_gimple_form to not break non-unit-at-a-time mode. */
- in_gimple_form = false;
}
static bool
unsigned int todo_after = 0;
/* IPA passes are executed on whole program, so cfun should be NULL.
- Ohter passes needs function context set. */
+ Other passes need function context set. */
if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS)
gcc_assert (!cfun && !current_function_decl);
else
}
current_pass = pass;
+
/* See if we're supposed to run this pass. */
if (pass->gate && !pass->gate ())
return false;
if (!quiet_flag && !cfun)
fprintf (stderr, " <%s>", pass->name ? pass->name : "");
- if (pass->todo_flags_start & TODO_set_props)
- cfun->curr_properties = pass->properties_required;
-
/* Note that the folders should only create gimple expressions.
This is a hack until the new folder is ready. */
in_gimple_form = (cfun && (cfun->curr_properties & PROP_trees)) != 0;
+ initializing_dump = pass_init_dump_file (pass);
+
/* Run pre-pass verification. */
execute_todo (pass->todo_flags_start);
(void *)(size_t)pass->properties_required);
#endif
- initializing_dump = pass_init_dump_file (pass);
-
/* If a timevar is present, start it. */
- if (pass->tv_id)
+ if (pass->tv_id != TV_NONE)
timevar_push (pass->tv_id);
/* Do it! */
}
/* Stop timevar. */
- if (pass->tv_id)
+ if (pass->tv_id != TV_NONE)
timevar_pop (pass->tv_id);
do_per_function (update_properties_after_pass, pass);
if (initializing_dump
&& dump_file
&& graph_dump_format != no_graph
+ && cfun
&& (cfun->curr_properties & (PROP_cfg | PROP_rtl))
== (PROP_cfg | PROP_rtl))
{
|| pass->type != RTL_PASS);
current_pass = NULL;
- /* Reset in_gimple_form to not break non-unit-at-a-time mode. */
- in_gimple_form = false;
return true;
}
{
if (!quiet_flag && !cfun)
fprintf (stderr, " <summary generate>");
- execute_ipa_summary_passes ((struct ipa_opt_pass *) pass);
+ execute_ipa_summary_passes ((struct ipa_opt_pass_d *) pass);
}
summaries_generated = true;
}
- else
- summaries_generated = false;
if (execute_one_pass (pass) && pass->sub)
{
if (pass->sub->type == GIMPLE_PASS)
while (pass);
}
+/* Called by local passes to see if function is called by already processed nodes.
+ Because we process nodes in topological order, this means that function is
+ in recursive cycle or we introduced new direct calls. */
+bool
+function_called_by_processed_nodes_p (void)
+{
+ struct cgraph_edge *e;
+ for (e = cgraph_node (current_function_decl)->callers; e; e = e->next_caller)
+ {
+ if (e->caller->decl == current_function_decl)
+ continue;
+ if (!e->caller->analyzed || (!e->caller->needed && !e->caller->reachable))
+ continue;
+ if (TREE_ASM_WRITTEN (e->caller->decl))
+ continue;
+ if (!e->caller->process && !e->caller->global.inlined_to)
+ break;
+ }
+ if (dump_file && e)
+ {
+ fprintf (dump_file, "Already processed call to:\n");
+ dump_cgraph_node (dump_file, e->caller);
+ }
+ return e != NULL;
+}
+
#include "gt-passes.h"