/* Localize comdats.
- Copyright (C) 2014 Free Software Foundation, Inc.
+ Copyright (C) 2014-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "system.h"
#include "coretypes.h"
#include "tm.h"
+#include "alias.h"
#include "tree.h"
+#include "hard-reg-set.h"
+#include "function.h"
#include "cgraph.h"
#include "tree-pass.h"
-#include "pointer-set.h"
/* Main dataflow loop propagating comdat groups across
the symbol table. All references to SYMBOL are examined
tree
propagate_comdat_group (struct symtab_node *symbol,
- tree newgroup, pointer_map <tree> &map)
+ tree newgroup, hash_map<symtab_node *, tree> &map)
{
int i;
struct ipa_ref *ref;
/* Walk all references to SYMBOL, recursively dive into aliases. */
for (i = 0;
- ipa_ref_list_referring_iterate (&symbol->ref_list, i, ref)
+ symbol->iterate_referring (i, ref)
&& newgroup != error_mark_node; i++)
{
struct symtab_node *symbol2 = ref->referring;
/* The actual merge operation. */
- tree *val2 = map.contains (symbol2);
+ tree *val2 = map.get (symbol2);
if (val2 && *val2 != newgroup)
{
{
struct symtab_node *symbol2 = edge->caller;
- /* If we see inline clone, its comdat group actually
- corresponds to the comdat group of the function it is inlined
- to. */
-
if (cgraph_node * cn = dyn_cast <cgraph_node *> (symbol2))
{
+ /* Thunks can not call across section boundary. */
+ if (cn->thunk.thunk_p)
+ newgroup = propagate_comdat_group (symbol2, newgroup, map);
+ /* If we see inline clone, its comdat group actually
+ corresponds to the comdat group of the function it
+ is inlined to. */
if (cn->global.inlined_to)
symbol2 = cn->global.inlined_to;
}
/* The actual merge operation. */
- tree *val2 = map.contains (symbol2);
+ tree *val2 = map.get (symbol2);
if (val2 && *val2 != newgroup)
{
symtab_node *symbol)
{
int i;
- struct ipa_ref *ref;
+ struct ipa_ref *ref = NULL;
- for (i = 0; ipa_ref_list_reference_iterate (&symbol->ref_list, i, ref); i++)
+ for (i = 0; symbol->iterate_reference (i, ref); i++)
{
- symtab_node *node = symtab_alias_ultimate_target (ref->referred, NULL);
+ symtab_node *node = ref->referred->ultimate_alias_target ();
+
+ /* Always keep thunks in same sections as target function. */
+ if (is_a <cgraph_node *>(node))
+ node = dyn_cast <cgraph_node *> (node)->function_symbol ();
if (!node->aux && node->definition)
{
node->aux = *first;
enqueue_references (first, edge->callee);
else
{
- symtab_node *node = symtab_alias_ultimate_target (edge->callee,
- NULL);
+ symtab_node *node = edge->callee->ultimate_alias_target ();
+
+ /* Always keep thunks in same sections as target function. */
+ if (is_a <cgraph_node *>(node))
+ node = dyn_cast <cgraph_node *> (node)->function_symbol ();
if (!node->aux && node->definition)
{
node->aux = *first;
}
/* Set comdat group of SYMBOL to GROUP.
- Callback for symtab_for_node_and_aliases. */
+ Callback for for_node_and_aliases. */
bool
set_comdat_group (symtab_node *symbol,
gcc_assert (!symbol->get_comdat_group ());
symbol->set_comdat_group (head->get_comdat_group ());
- symtab_add_to_same_comdat_group (symbol, head);
+ symbol->add_to_same_comdat_group (head);
return false;
}
+/* Set comdat group of SYMBOL to GROUP.
+ Callback for for_node_thunks_and_aliases. */
+
+bool
+set_comdat_group_1 (cgraph_node *symbol,
+ void *head_p)
+{
+ return set_comdat_group (symbol, head_p);
+}
+
/* The actual pass with the main dataflow loop. */
static unsigned int
ipa_comdats (void)
{
- pointer_map<tree> map;
- pointer_map<symtab_node *> comdat_head_map;
+ hash_map<symtab_node *, tree> map (251);
+ hash_map<tree, symtab_node *> comdat_head_map (251);
symtab_node *symbol;
bool comdat_group_seen = false;
symtab_node *first = (symtab_node *) (void *) 1;
ERROR_MARK_NODE as bottom for the propagation. */
FOR_EACH_DEFINED_SYMBOL (symbol)
- if (!symtab_real_symbol_p (symbol))
+ if (!symbol->real_symbol_p ())
;
else if ((group = symbol->get_comdat_group ()) != NULL)
{
- *map.insert (symbol) = group;
- *comdat_head_map.insert (group) = symbol;
+ map.put (symbol, group);
+ comdat_head_map.put (group, symbol);
comdat_group_seen = true;
/* Mark the symbol so we won't waste time visiting it for dataflow. */
&& (DECL_STATIC_CONSTRUCTOR (symbol->decl)
|| DECL_STATIC_DESTRUCTOR (symbol->decl))))
{
- *map.insert (symtab_alias_ultimate_target (symbol, NULL)) = error_mark_node;
+ symtab_node *target = symbol->ultimate_alias_target ();
+
+ /* Always keep thunks in same sections as target function. */
+ if (is_a <cgraph_node *>(target))
+ target = dyn_cast <cgraph_node *> (target)->function_symbol ();
+ map.put (target, error_mark_node);
/* Mark the symbol so we won't waste time visiting it for dataflow. */
symbol->aux = (symtab_node *) (void *) 1;
first = (symtab_node *)first->aux;
/* Get current lattice value of SYMBOL. */
- val = map.contains (symbol);
+ val = map.get (symbol);
if (val)
group = *val;
if (val)
*val = newgroup;
else
- *map.insert (symbol) = newgroup;
+ map.put (symbol, newgroup);
enqueue_references (&first, symbol);
/* We may need to revisit the symbol unless it is BOTTOM. */
FOR_EACH_DEFINED_SYMBOL (symbol)
{
+ struct cgraph_node *fun;
symbol->aux = NULL;
if (!symbol->get_comdat_group ()
&& !symbol->alias
- && symtab_real_symbol_p (symbol))
+ && (!(fun = dyn_cast <cgraph_node *> (symbol))
+ || !fun->thunk.thunk_p)
+ && symbol->real_symbol_p ())
{
- tree group = *map.contains (symbol);
+ tree *val = map.get (symbol);
+
+ /* A NULL here means that SYMBOL is unreachable in the definition
+ of ipa-comdats. Either ipa-comdats is wrong about this or someone
+ forgot to cleanup and remove unreachable functions earlier. */
+ gcc_assert (val);
+
+ tree group = *val;
if (group == error_mark_node)
continue;
if (dump_file)
{
fprintf (dump_file, "Localizing symbol\n");
- dump_symtab_node (dump_file, symbol);
+ symbol->dump (dump_file);
fprintf (dump_file, "To group: %s\n", IDENTIFIER_POINTER (group));
}
- symtab_for_node_and_aliases (symbol, set_comdat_group,
- *comdat_head_map.contains (group), true);
+ if (is_a <cgraph_node *> (symbol))
+ dyn_cast <cgraph_node *>(symbol)->call_for_symbol_thunks_and_aliases
+ (set_comdat_group_1,
+ *comdat_head_map.get (group),
+ true);
+ else
+ symbol->call_for_symbol_and_aliases
+ (set_comdat_group,
+ *comdat_head_map.get (group),
+ true);
}
}
return 0;
IPA_PASS, /* type */
"comdats", /* name */
OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_execute */
TV_IPA_COMDATS, /* tv_id */
0, /* properties_required */
0, /* properties_provided */