/* 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, 2008, 2009, 2010
- Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+ 2011, 2012 Free Software Foundation, Inc.
This file is part of GCC.
{
alias = TREE_VALUE (TREE_VALUE (alias));
alias = get_identifier (TREE_STRING_POINTER (alias));
+ /* A quirk of the initial implementation of aliases required that the
+ user add "extern" to all of them. Which is silly, but now
+ historical. Do note that the symbol is in fact locally defined. */
+ if (!lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
+ DECL_EXTERNAL (decl) = 0;
assemble_alias (decl, alias);
}
}
/* The root of the compilation pass tree, once constructed. */
struct opt_pass *all_passes, *all_small_ipa_passes, *all_lowering_passes,
- *all_regular_ipa_passes, *all_lto_gen_passes;
+ *all_regular_ipa_passes, *all_late_ipa_passes, *all_lto_gen_passes;
/* This is used by plugins, and should also be used in register_pass. */
#define DEF_PASS_LIST(LIST) &LIST,
set_pass_for_id (id, pass);
full_name = concat (prefix, pass->name, num, NULL);
register_pass_name (pass, full_name);
+ free (CONST_CAST (char *, full_name));
}
/* Recursive worker function for register_dump_files. */
return !strcmp (s1->unique_name, s2->unique_name);
}
-static htab_t pass_name_tab = NULL;
+static htab_t name_to_pass_map = NULL;
/* Register PASS with NAME. */
struct pass_registry **slot;
struct pass_registry pr;
- if (!pass_name_tab)
- pass_name_tab = htab_create (256, passr_hash, passr_eq, NULL);
+ if (!name_to_pass_map)
+ name_to_pass_map = htab_create (256, passr_hash, passr_eq, NULL);
pr.unique_name = name;
- slot = (struct pass_registry **) htab_find_slot (pass_name_tab, &pr, INSERT);
+ slot = (struct pass_registry **) htab_find_slot (name_to_pass_map, &pr, INSERT);
if (!*slot)
{
struct pass_registry *new_pr;
return; /* Ignore plugin passes. */
}
+/* Map from pass id to canonicalized pass name. */
+
+typedef const char *char_ptr;
+DEF_VEC_P(char_ptr);
+DEF_VEC_ALLOC_P(char_ptr, heap);
+static VEC(char_ptr, heap) *pass_tab = NULL;
+
+/* Callback function for traversing NAME_TO_PASS_MAP. */
+
+static int
+pass_traverse (void **slot, void *data ATTRIBUTE_UNUSED)
+{
+ struct pass_registry **p = (struct pass_registry **)slot;
+ struct opt_pass *pass = (*p)->pass;
+
+ gcc_assert (pass->static_pass_number > 0);
+ gcc_assert (pass_tab);
+
+ VEC_replace (char_ptr, pass_tab, pass->static_pass_number,
+ (*p)->unique_name);
+
+ return 1;
+}
+
+/* The function traverses NAME_TO_PASS_MAP and creates a pass info
+ table for dumping purpose. */
+
+static void
+create_pass_tab (void)
+{
+ if (!flag_dump_passes)
+ return;
+
+ VEC_safe_grow_cleared (char_ptr, heap,
+ pass_tab, passes_by_id_size + 1);
+ htab_traverse (name_to_pass_map, pass_traverse, NULL);
+}
+
+static bool override_gate_status (struct opt_pass *, tree, bool);
+
+/* Dump the instantiated name for PASS. IS_ON indicates if PASS
+ is turned on or not. */
+
+static void
+dump_one_pass (struct opt_pass *pass, int pass_indent)
+{
+ int indent = 3 * pass_indent;
+ const char *pn;
+ bool is_on, is_really_on;
+
+ is_on = (pass->gate == NULL) ? true : pass->gate();
+ is_really_on = override_gate_status (pass, current_function_decl, is_on);
+
+ if (pass->static_pass_number <= 0)
+ pn = pass->name;
+ else
+ pn = VEC_index (char_ptr, pass_tab, pass->static_pass_number);
+
+ fprintf (stderr, "%*s%-40s%*s:%s%s\n", indent, " ", pn,
+ (15 - indent < 0 ? 0 : 15 - indent), " ",
+ is_on ? " ON" : " OFF",
+ ((!is_on) == (!is_really_on) ? ""
+ : (is_really_on ? " (FORCED_ON)" : " (FORCED_OFF)")));
+}
+
+/* Dump pass list PASS with indentation INDENT. */
+
+static void
+dump_pass_list (struct opt_pass *pass, int indent)
+{
+ do
+ {
+ dump_one_pass (pass, indent);
+ if (pass->sub)
+ dump_pass_list (pass->sub, indent + 1);
+ pass = pass->next;
+ }
+ while (pass);
+}
+
+/* Dump all optimization passes. */
+
+void
+dump_passes (void)
+{
+ struct cgraph_node *n, *node = NULL;
+ tree save_fndecl = current_function_decl;
+
+ create_pass_tab();
+
+ n = cgraph_nodes;
+ while (n)
+ {
+ if (DECL_STRUCT_FUNCTION (n->decl))
+ {
+ node = n;
+ break;
+ }
+ n = n->next;
+ }
+
+ if (!node)
+ return;
+
+ push_cfun (DECL_STRUCT_FUNCTION (node->decl));
+ current_function_decl = node->decl;
+
+ dump_pass_list (all_lowering_passes, 1);
+ dump_pass_list (all_small_ipa_passes, 1);
+ dump_pass_list (all_regular_ipa_passes, 1);
+ dump_pass_list (all_lto_gen_passes, 1);
+ dump_pass_list (all_late_ipa_passes, 1);
+ dump_pass_list (all_passes, 1);
+
+ pop_cfun ();
+ current_function_decl = save_fndecl;
+}
+
+
/* Returns the pass with NAME. */
static struct opt_pass *
{
struct pass_registry **slot, pr;
- gcc_assert (pass_name_tab);
pr.unique_name = name;
- slot = (struct pass_registry **) htab_find_slot (pass_name_tab,
+ slot = (struct pass_registry **) htab_find_slot (name_to_pass_map,
&pr, NO_INSERT);
if (!slot || !*slot)
if (!success || all_instances)
success |= position_pass (pass_info, &all_lto_gen_passes);
if (!success || all_instances)
+ success |= position_pass (pass_info, &all_late_ipa_passes);
+ if (!success || all_instances)
success |= position_pass (pass_info, &all_passes);
if (!success)
fatal_error
p = &all_lowering_passes;
NEXT_PASS (pass_warn_unused_result);
NEXT_PASS (pass_diagnose_omp_blocks);
+ NEXT_PASS (pass_diagnose_tm_blocks);
NEXT_PASS (pass_mudflap_1);
NEXT_PASS (pass_lower_omp);
NEXT_PASS (pass_lower_cf);
+ NEXT_PASS (pass_lower_tm);
NEXT_PASS (pass_refactor_eh);
NEXT_PASS (pass_lower_eh);
NEXT_PASS (pass_build_cfg);
}
NEXT_PASS (pass_ipa_increase_alignment);
NEXT_PASS (pass_ipa_matrix_reorg);
+ NEXT_PASS (pass_ipa_tm);
NEXT_PASS (pass_ipa_lower_emutls);
*p = NULL;
NEXT_PASS (pass_ipa_inline);
NEXT_PASS (pass_ipa_pure_const);
NEXT_PASS (pass_ipa_reference);
- NEXT_PASS (pass_ipa_pta);
*p = NULL;
p = &all_lto_gen_passes;
NEXT_PASS (pass_ipa_lto_finish_out); /* This must be the last LTO pass. */
*p = NULL;
+ /* Simple IPA passes executed after the regular passes. In WHOPR mode the
+ passes are executed after partitioning and thus see just parts of the
+ compiled unit. */
+ p = &all_late_ipa_passes;
+ NEXT_PASS (pass_ipa_pta);
+ *p = NULL;
/* These passes are run after IPA passes on every function that is being
output to the assembler file. */
p = &all_passes;
+ NEXT_PASS (pass_fixup_cfg);
NEXT_PASS (pass_lower_eh_dispatch);
NEXT_PASS (pass_all_optimizations);
{
NEXT_PASS (pass_forwprop);
NEXT_PASS (pass_phiopt);
NEXT_PASS (pass_object_sizes);
+ NEXT_PASS (pass_strlen);
NEXT_PASS (pass_ccp);
NEXT_PASS (pass_copy_prop);
NEXT_PASS (pass_cse_sincos);
NEXT_PASS (pass_vectorize);
{
struct opt_pass **p = &pass_vectorize.pass.sub;
- NEXT_PASS (pass_lower_vector_ssa);
NEXT_PASS (pass_dce_loop);
}
NEXT_PASS (pass_predcom);
NEXT_PASS (pass_parallelize_loops);
NEXT_PASS (pass_loop_prefetch);
NEXT_PASS (pass_iv_optimize);
+ NEXT_PASS (pass_lim);
NEXT_PASS (pass_tree_loop_done);
}
+ NEXT_PASS (pass_lower_vector_ssa);
NEXT_PASS (pass_cse_reciprocals);
NEXT_PASS (pass_reassoc);
NEXT_PASS (pass_vrp);
NEXT_PASS (pass_uncprop);
NEXT_PASS (pass_local_pure_const);
}
+ NEXT_PASS (pass_tm_init);
+ {
+ struct opt_pass **p = &pass_tm_init.pass.sub;
+ NEXT_PASS (pass_tm_mark);
+ NEXT_PASS (pass_tm_memopt);
+ NEXT_PASS (pass_tm_edges);
+ }
NEXT_PASS (pass_lower_complex_O0);
NEXT_PASS (pass_cleanup_eh);
NEXT_PASS (pass_lower_resx);
NEXT_PASS (pass_sms);
NEXT_PASS (pass_sched);
NEXT_PASS (pass_ira);
+ NEXT_PASS (pass_reload);
NEXT_PASS (pass_postreload);
{
struct opt_pass **p = &pass_postreload.pass.sub;
NEXT_PASS (pass_postreload_cse);
NEXT_PASS (pass_gcse2);
NEXT_PASS (pass_split_after_reload);
- NEXT_PASS (pass_implicit_zee);
+ NEXT_PASS (pass_ree);
NEXT_PASS (pass_compare_elim_after_reload);
NEXT_PASS (pass_branch_target_load_optimize1);
NEXT_PASS (pass_thread_prologue_and_epilogue);
NEXT_PASS (pass_convert_to_eh_region_ranges);
NEXT_PASS (pass_shorten_branches);
NEXT_PASS (pass_set_nothrow_function_flags);
+ NEXT_PASS (pass_dwarf2_frame);
NEXT_PASS (pass_final);
}
NEXT_PASS (pass_df_finish);
register_dump_files (all_lto_gen_passes,
PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
| PROP_cfg);
+ register_dump_files (all_late_ipa_passes,
+ PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
+ | PROP_cfg);
register_dump_files (all_passes,
PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
| PROP_cfg);
nnodes = 0;
}
+/* Helper function to perform function body dump. */
+
+static void
+execute_function_dump (void *data ATTRIBUTE_UNUSED)
+{
+ if (dump_file && current_function_decl)
+ {
+ if (cfun->curr_properties & PROP_trees)
+ dump_function_to_file (current_function_decl, dump_file, dump_flags);
+ else
+ {
+ if (dump_flags & TDF_SLIM)
+ print_rtl_slim_with_bb (dump_file, get_insns (), dump_flags);
+ else if ((cfun->curr_properties & PROP_cfg)
+ && (dump_flags & TDF_BLOCKS))
+ print_rtl_with_bb (dump_file, get_insns ());
+ else
+ print_rtl (dump_file, get_insns ());
+
+ 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 ());
+ }
+
+ /* Flush the file. If verification fails, we won't be able to
+ close the file before aborting. */
+ fflush (dump_file);
+ }
+}
+
/* Perform all TODO actions that ought to be done on each function. */
static void
if (flags & TODO_remove_unused_locals)
remove_unused_locals ();
- 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);
- else
- {
- if (dump_flags & TDF_SLIM)
- print_rtl_slim_with_bb (dump_file, get_insns (), dump_flags);
- else if ((cfun->curr_properties & PROP_cfg)
- && (dump_flags & TDF_BLOCKS))
- print_rtl_with_bb (dump_file, get_insns ());
- else
- print_rtl (dump_file, get_insns ());
-
- 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 ());
- }
-
- /* Flush the file. If verification fails, we won't be able to
- close the file before aborting. */
- fflush (dump_file);
- }
-
if (flags & TODO_rebuild_frequencies)
rebuild_frequencies ();
execute_todo (todo_after);
verify_interpass_invariants ();
+ do_per_function (execute_function_dump, NULL);
pass_fini_dump_file (pass);
current_pass = NULL;
}
}
+/* Callback for do_per_function to apply all IPA transforms. */
+
+static void
+apply_ipa_transforms (void *data)
+{
+ struct cgraph_node *node = cgraph_get_node (current_function_decl);
+ if (!node->global.inlined_to && node->ipa_transforms_to_apply)
+ {
+ *(bool *)data = true;
+ execute_all_ipa_transforms();
+ rebuild_cgraph_edges ();
+ }
+}
+
/* Check if PASS is explicitly disabled or enabled and return
the gate status. FUNC is the function to be processed, and
GATE_STATUS is the gate status determined by pass manager by
executed. */
invoke_plugin_callbacks (PLUGIN_PASS_EXECUTION, pass);
+ /* SIPLE IPA passes do not handle callgraphs with IPA transforms in it.
+ Apply all trnasforms first. */
+ if (pass->type == SIMPLE_IPA_PASS)
+ {
+ bool applied = false;
+ do_per_function (apply_ipa_transforms, (void *)&applied);
+ if (applied)
+ cgraph_remove_unreachable_nodes (true, dump_file);
+ /* Restore current_pass. */
+ current_pass = pass;
+ }
+
if (!quiet_flag && !cfun)
fprintf (stderr, " <%s>", pass->name ? pass->name : "");
/* Run post-pass cleanup and verification. */
execute_todo (todo_after | pass->todo_flags_finish);
verify_interpass_invariants ();
+ do_per_function (execute_function_dump, NULL);
if (pass->type == IPA_PASS)
{
struct cgraph_node *node;
vset = varpool_node_set_new ();
for (vnode = varpool_nodes; vnode; vnode = vnode->next)
- if (vnode->needed && !vnode->alias)
+ if (vnode->needed && (!vnode->alias || vnode->alias_of))
varpool_node_set_add (vset, vnode);
ipa_write_summaries_1 (set, vset);