*first = node;
}
+/* Return true if NODE may get inlined later.
+ This is used to keep DECL_EXTERNAL function bodies around long enough
+ so inliner can proces them. */
+
+static bool
+possible_inline_candidate_p (symtab_node *node)
+{
+ if (symtab->state >= IPA_SSA_AFTER_INLINING)
+ return false;
+ cgraph_node *cnode = dyn_cast <cgraph_node *> (node);
+ if (!cnode)
+ return false;
+ if (DECL_UNINLINABLE (cnode->decl))
+ return false;
+ if (opt_for_fn (cnode->decl, optimize))
+ return true;
+ if (symtab->state >= IPA_SSA)
+ return false;
+ return lookup_attribute ("always_inline", DECL_ATTRIBUTES (node->decl));
+}
+
/* Process references. */
static void
process_references (symtab_node *snode,
symtab_node **first,
- bool before_inlining_p,
hash_set<symtab_node *> *reachable)
{
int i;
if (node->definition && !node->in_other_partition
&& ((!DECL_EXTERNAL (node->decl) || node->alias)
- || (((before_inlining_p
- && (TREE_CODE (node->decl) != FUNCTION_DECL
- || (TREE_CODE (node->decl) == FUNCTION_DECL
- && opt_for_fn (body->decl, optimize))
- || (symtab->state < IPA_SSA
- && lookup_attribute
- ("always_inline",
- DECL_ATTRIBUTES (body->decl))))))
+ || (possible_inline_candidate_p (node)
/* We use variable constructors during late compilation for
constant folding. Keep references alive so partitioning
knows about potential references. */
body. */
if (DECL_EXTERNAL (node->decl)
&& node->alias
- && before_inlining_p)
+ && symtab->state < IPA_SSA_AFTER_INLINING)
reachable->add (body);
reachable->add (node);
}
walk_polymorphic_call_targets (hash_set<void *> *reachable_call_targets,
struct cgraph_edge *edge,
symtab_node **first,
- hash_set<symtab_node *> *reachable,
- bool before_inlining_p)
+ hash_set<symtab_node *> *reachable)
{
unsigned int i;
void *cache_token;
/* Prior inlining, keep alive bodies of possible targets for
devirtualization. */
if (n->definition
- && (before_inlining_p
- && opt_for_fn (body->decl, optimize)
+ && (possible_inline_candidate_p (body)
&& opt_for_fn (body->decl, flag_devirtualize)))
{
/* Be sure that we will not optimize out alias target
body. */
if (DECL_EXTERNAL (n->decl)
&& n->alias
- && before_inlining_p)
+ && symtab->state < IPA_SSA_AFTER_INLINING)
reachable->add (body);
reachable->add (n);
}
hash_set<symtab_node *> reachable;
hash_set<tree> body_needed_for_clonning;
hash_set<void *> reachable_call_targets;
- bool before_inlining_p = symtab->state < (!optimize && !in_lto_p ? IPA_SSA
- : IPA_SSA_AFTER_INLINING);
timevar_push (TV_IPA_UNREACHABLE);
build_type_inheritance_graph ();
enqueue_node (next, &first, &reachable);
}
/* Mark references as reachable. */
- process_references (node, &first, before_inlining_p, &reachable);
+ process_references (node, &first, &reachable);
}
if (cgraph_node *cnode = dyn_cast <cgraph_node *> (node))
next = e->next_callee;
if (e->indirect_info->polymorphic)
walk_polymorphic_call_targets (&reachable_call_targets,
- e, &first, &reachable,
- before_inlining_p);
+ e, &first, &reachable);
}
}
for (e = cnode->callees; e; e = e->next_callee)
&& (!e->inline_failed
|| !DECL_EXTERNAL (e->callee->decl)
|| e->callee->alias
- || (before_inlining_p
- && (opt_for_fn (body->decl, optimize)
- || (symtab->state < IPA_SSA
- && lookup_attribute
- ("always_inline",
- DECL_ATTRIBUTES (body->decl)))))))
+ || possible_inline_candidate_p (e->callee)))
{
/* Be sure that we will not optimize out alias target
body. */
if (DECL_EXTERNAL (e->callee->decl)
&& e->callee->alias
- && before_inlining_p)
+ && symtab->state < IPA_SSA_AFTER_INLINING)
reachable.add (body);
reachable.add (e->callee);
}
of possible later devirtualization. Do not mark them as
local too early so we won't optimize them out before
we are done with polymorphic call analysis. */
- && (!before_inlining_p
+ && (symtab->state >= IPA_SSA_AFTER_INLINING
|| !node->call_for_symbol_and_aliases
(is_indirect_call_target_p, NULL, true)))
{
}; // class pass_local_optimization_passes
+const pass_data pass_data_ipa_remove_symbols =
+{
+ SIMPLE_IPA_PASS, /* type */
+ "remove_symbols", /* name */
+ OPTGROUP_NONE, /* optinfo_flags */
+ TV_NONE, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_remove_functions | TODO_dump_symtab, /* todo_flags_finish */
+};
+
+class pass_ipa_remove_symbols : public simple_ipa_opt_pass
+{
+public:
+ pass_ipa_remove_symbols (gcc::context *ctxt)
+ : simple_ipa_opt_pass (pass_data_ipa_remove_symbols, ctxt)
+ {}
+
+ /* opt_pass methods: */
+ virtual bool gate (function *)
+ {
+ /* Don't bother doing anything if the program has errors. */
+ return (!seen_error () && !in_lto_p);
+ }
+
+}; // class pass_local_optimization_passes
+
} // anon namespace
simple_ipa_opt_pass *
return new pass_local_optimization_passes (ctxt);
}
+simple_ipa_opt_pass *
+make_pass_ipa_remove_symbols (gcc::context *ctxt)
+{
+ return new pass_ipa_remove_symbols (ctxt);
+}
+
namespace {
const pass_data pass_data_all_early_optimizations =