Move clone_info to summary
* Makefile.in: (OBJS): Add symtab-clones.o (GTFILES): Add symtab-clones.h * cgraph.c: Include symtab-clones.h. (cgraph_edge::resolve_speculation): Fix formating (cgraph_edge::redirect_call_stmt_to_callee): Update. (cgraph_update_edges_for_call_stmt): Update (release_function_body): Fix formating. (cgraph_node::remove): Fix formating. (cgraph_node::dump): Fix formating. (cgraph_node::get_availability): Fix formating. (cgraph_node::call_for_symbol_thunks_and_aliases): Fix formating. (set_const_flag_1): Fix formating. (set_pure_flag_1): Fix formating. (cgraph_node::can_remove_if_no_direct_calls_p): Fix formating. (collect_callers_of_node_1): Fix formating. (clone_of_p): Update. (cgraph_node::verify_node): Update. (cgraph_c_finalize): Call clone_info::release (). * cgraph.h (struct cgraph_clone_info): Move to symtab-clones.h. (cgraph_node): Remove clone_info. (symbol_table): Add m_clones. * cgraphclones.c: Include symtab-clone.h. (duplicate_thunk_for_node): Update. (cgraph_node::create_clone): Update. (cgraph_node::create_virtual_clone): Update. (cgraph_node::find_replacement): Update. (cgraph_node::materialize_clone): Update. * gengtype.c (open_base_files): Include symtab-clones.h. * ipa-cp.c: Include symtab-clones.h. (initialize_node_lattices): Update. (want_remove_some_param_p): Update. (create_specialized_node): Update. * ipa-fnsummary.c: Include symtab-clones.h. (ipa_fn_summary_t::duplicate): Update. * ipa-modref.c: Include symtab-clones.h. (update_signature): Update. * ipa-param-manipulation.c: Include symtab-clones.h. (ipa_param_body_adjustments::common_initialization): Update. * ipa-prop.c: Include symtab-clones.h. (adjust_agg_replacement_values): Update. (ipcp_get_parm_bits): Update. (ipcp_update_bits): Update. (ipcp_update_vr): Update. * ipa-sra.c: Include symtab-clones.h. (process_isra_node_results): Update. (disable_unavailable_parameters): Update. * lto-cgraph.c: Include symtab-clone.h. (output_cgraph_opt_summary_p): Update. (output_node_opt_summary): Update. (input_node_opt_summary): Update. * symtab-clones.cc: New file. * symtab-clones.h: New file. * tree-inline.c (expand_call_inline): Update. (update_clone_info): Update. (tree_function_versioning): Update.
This commit is contained in:
parent
617695cdc2
commit
ae7a23a3fa
@ -1299,6 +1299,7 @@ OBJS = \
|
||||
cfgrtl.o \
|
||||
symtab.o \
|
||||
symtab-thunks.o \
|
||||
symtab-clones.o \
|
||||
cgraph.o \
|
||||
cgraphbuild.o \
|
||||
cgraphunit.o \
|
||||
@ -2594,6 +2595,7 @@ GTFILES = $(CPPLIB_H) $(srcdir)/input.h $(srcdir)/coretypes.h \
|
||||
$(srcdir)/output.h $(srcdir)/cfgloop.h $(srcdir)/cfg.h $(srcdir)/profile-count.h \
|
||||
$(srcdir)/cselib.h $(srcdir)/basic-block.h $(srcdir)/ipa-ref.h $(srcdir)/cgraph.h \
|
||||
$(srcdir)/symtab-thunks.h $(srcdir)/symtab-thunks.cc \
|
||||
$(srcdir)/symtab-clones.h \
|
||||
$(srcdir)/reload.h $(srcdir)/caller-save.c $(srcdir)/symtab.c \
|
||||
$(srcdir)/alias.c $(srcdir)/bitmap.c $(srcdir)/cselib.c $(srcdir)/cgraph.c \
|
||||
$(srcdir)/ipa-prop.c $(srcdir)/ipa-cp.c $(srcdir)/ipa-utils.h \
|
||||
|
||||
96
gcc/cgraph.c
96
gcc/cgraph.c
@ -66,6 +66,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "ipa-inline.h"
|
||||
#include "tree-nested.h"
|
||||
#include "symtab-thunks.h"
|
||||
#include "symtab-clones.h"
|
||||
|
||||
/* FIXME: Only for PROP_loops, but cgraph shouldn't have to know about this. */
|
||||
#include "tree-pass.h"
|
||||
@ -1236,7 +1237,7 @@ cgraph_edge::resolve_speculation (cgraph_edge *edge, tree callee_decl)
|
||||
{
|
||||
cgraph_edge *tmp = edge;
|
||||
if (dump_file)
|
||||
fprintf (dump_file, "Speculative call turned into direct call.\n");
|
||||
fprintf (dump_file, "Speculative call turned into direct call.\n");
|
||||
edge = e2;
|
||||
e2 = tmp;
|
||||
/* FIXME: If EDGE is inlined, we should scale up the frequencies
|
||||
@ -1488,38 +1489,43 @@ cgraph_edge::redirect_call_stmt_to_callee (cgraph_edge *e)
|
||||
return e->call_stmt;
|
||||
}
|
||||
}
|
||||
|
||||
if (flag_checking && decl)
|
||||
{
|
||||
cgraph_node *node = cgraph_node::get (decl);
|
||||
gcc_assert (!node || !node->clone.param_adjustments);
|
||||
clone_info *info = clone_info::get (node);
|
||||
gcc_assert (!node || !info || !info->param_adjustments);
|
||||
}
|
||||
|
||||
clone_info *callee_info = clone_info::get (e->callee);
|
||||
clone_info *caller_info = clone_info::get (e->caller);
|
||||
|
||||
if (symtab->dump_file)
|
||||
{
|
||||
|
||||
fprintf (symtab->dump_file, "updating call of %s -> %s: ",
|
||||
e->caller->dump_name (), e->callee->dump_name ());
|
||||
print_gimple_stmt (symtab->dump_file, e->call_stmt, 0, dump_flags);
|
||||
if (e->callee->clone.param_adjustments)
|
||||
e->callee->clone.param_adjustments->dump (symtab->dump_file);
|
||||
if (callee_info && callee_info->param_adjustments)
|
||||
callee_info->param_adjustments->dump (symtab->dump_file);
|
||||
unsigned performed_len
|
||||
= vec_safe_length (e->caller->clone.performed_splits);
|
||||
= vec_safe_length (caller_info->performed_splits);
|
||||
if (performed_len > 0)
|
||||
fprintf (symtab->dump_file, "Performed splits records:\n");
|
||||
for (unsigned i = 0; i < performed_len; i++)
|
||||
{
|
||||
ipa_param_performed_split *sm
|
||||
= &(*e->caller->clone.performed_splits)[i];
|
||||
= &(*caller_info->performed_splits)[i];
|
||||
print_node_brief (symtab->dump_file, " dummy_decl: ", sm->dummy_decl,
|
||||
TDF_UID);
|
||||
fprintf (symtab->dump_file, ", unit_offset: %u\n", sm->unit_offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (ipa_param_adjustments *padjs = e->callee->clone.param_adjustments)
|
||||
if (ipa_param_adjustments *padjs
|
||||
= callee_info ? callee_info->param_adjustments : NULL)
|
||||
{
|
||||
/* We need to defer cleaning EH info on the new statement to
|
||||
fixup-cfg. We may not have dominator information at this point
|
||||
fixup-cfg. We may not have dominator information at this point
|
||||
and thus would end up with unreachable blocks and have no way
|
||||
to communicate that we need to run CFG cleanup then. */
|
||||
int lp_nr = lookup_stmt_eh_lp (e->call_stmt);
|
||||
@ -1528,7 +1534,8 @@ cgraph_edge::redirect_call_stmt_to_callee (cgraph_edge *e)
|
||||
|
||||
tree old_fntype = gimple_call_fntype (e->call_stmt);
|
||||
new_stmt = padjs->modify_call (e->call_stmt,
|
||||
e->caller->clone.performed_splits,
|
||||
caller_info
|
||||
? caller_info->performed_splits : NULL,
|
||||
e->callee->decl, false);
|
||||
cgraph_node *origin = e->callee;
|
||||
while (origin->clone_of)
|
||||
@ -1577,7 +1584,7 @@ cgraph_edge::redirect_call_stmt_to_callee (cgraph_edge *e)
|
||||
var = get_or_create_ssa_default_def
|
||||
(DECL_STRUCT_FUNCTION (e->caller->decl), var);
|
||||
gimple *set_stmt = gimple_build_assign (lhs, var);
|
||||
gsi = gsi_for_stmt (new_stmt);
|
||||
gsi = gsi_for_stmt (new_stmt);
|
||||
gsi_insert_before_without_update (&gsi, set_stmt, GSI_SAME_STMT);
|
||||
update_stmt_fn (DECL_STRUCT_FUNCTION (e->caller->decl), set_stmt);
|
||||
}
|
||||
@ -1703,7 +1710,8 @@ cgraph_update_edges_for_call_stmt (gimple *old_stmt, tree old_decl,
|
||||
if (orig->clones)
|
||||
for (node = orig->clones; node != orig;)
|
||||
{
|
||||
cgraph_update_edges_for_call_stmt_node (node, old_stmt, old_decl, new_stmt);
|
||||
cgraph_update_edges_for_call_stmt_node (node, old_stmt, old_decl,
|
||||
new_stmt);
|
||||
if (node->clones)
|
||||
node = node->clones;
|
||||
else if (node->next_sibling_clone)
|
||||
@ -1809,7 +1817,7 @@ release_function_body (tree decl)
|
||||
free_histograms (fn);
|
||||
gimple_set_body (decl, NULL);
|
||||
/* Struct function hangs a lot of data that would leak if we didn't
|
||||
removed all pointers to it. */
|
||||
removed all pointers to it. */
|
||||
ggc_free (fn);
|
||||
DECL_STRUCT_FUNCTION (decl) = NULL;
|
||||
}
|
||||
@ -1880,7 +1888,7 @@ cgraph_node::remove (void)
|
||||
cgraph_node *n, *next;
|
||||
|
||||
if (clone_of)
|
||||
{
|
||||
{
|
||||
for (n = clones; n->next_sibling_clone; n = n->next_sibling_clone)
|
||||
n->clone_of = clone_of;
|
||||
n->clone_of = clone_of;
|
||||
@ -1890,7 +1898,7 @@ cgraph_node::remove (void)
|
||||
clone_of->clones = clones;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
/* We are removing node with clones. This makes clones inconsistent,
|
||||
but assume they will be removed subsequently and just keep clone
|
||||
tree intact. This can happen in unreachable function removal since
|
||||
@ -2248,12 +2256,12 @@ cgraph_node::dump (FILE *f)
|
||||
{
|
||||
if (edge->indirect_info->polymorphic)
|
||||
{
|
||||
fprintf (f, " Polymorphic indirect call of type ");
|
||||
fprintf (f, " Polymorphic indirect call of type ");
|
||||
print_generic_expr (f, edge->indirect_info->otr_type, TDF_SLIM);
|
||||
fprintf (f, " token:%i", (int) edge->indirect_info->otr_token);
|
||||
}
|
||||
else
|
||||
fprintf (f, " Indirect call");
|
||||
fprintf (f, " Indirect call");
|
||||
edge->dump_edge_flags (f);
|
||||
if (edge->indirect_info->param_index != -1)
|
||||
{
|
||||
@ -2350,8 +2358,8 @@ cgraph_node::get_availability (symtab_node *ref)
|
||||
|
||||
Also comdat groups are always resolved in groups. */
|
||||
else if ((this == ref && !has_aliases_p ())
|
||||
|| (ref && get_comdat_group ()
|
||||
&& get_comdat_group () == ref->get_comdat_group ()))
|
||||
|| (ref && get_comdat_group ()
|
||||
&& get_comdat_group () == ref->get_comdat_group ()))
|
||||
avail = AVAIL_AVAILABLE;
|
||||
/* Inline functions are safe to be analyzed even if their symbol can
|
||||
be overwritten at runtime. It is not meaningful to enforce any sane
|
||||
@ -2419,7 +2427,7 @@ cgraph_node::call_for_symbol_thunks_and_aliases (bool (*callback)
|
||||
|| (avail = get_availability ()) > AVAIL_INTERPOSABLE)
|
||||
{
|
||||
if (callback (this, data))
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
FOR_EACH_ALIAS (this, ref)
|
||||
{
|
||||
@ -2614,8 +2622,8 @@ set_const_flag_1 (cgraph_node *node, bool set_const, bool looping,
|
||||
{
|
||||
if (TREE_READONLY (node->decl))
|
||||
{
|
||||
TREE_READONLY (node->decl) = 0;
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
|
||||
TREE_READONLY (node->decl) = 0;
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
|
||||
*changed = true;
|
||||
}
|
||||
}
|
||||
@ -2642,14 +2650,14 @@ set_const_flag_1 (cgraph_node *node, bool set_const, bool looping,
|
||||
{
|
||||
if (!looping && DECL_LOOPING_CONST_OR_PURE_P (node->decl))
|
||||
{
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
|
||||
*changed = true;
|
||||
}
|
||||
}
|
||||
else if (node->binds_to_current_def_p ())
|
||||
{
|
||||
TREE_READONLY (node->decl) = true;
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping;
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping;
|
||||
DECL_PURE_P (node->decl) = false;
|
||||
*changed = true;
|
||||
}
|
||||
@ -2661,12 +2669,12 @@ set_const_flag_1 (cgraph_node *node, bool set_const, bool looping,
|
||||
if (!DECL_PURE_P (node->decl))
|
||||
{
|
||||
DECL_PURE_P (node->decl) = true;
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping;
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = looping;
|
||||
*changed = true;
|
||||
}
|
||||
else if (!looping && DECL_LOOPING_CONST_OR_PURE_P (node->decl))
|
||||
{
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
|
||||
*changed = true;
|
||||
}
|
||||
}
|
||||
@ -2685,9 +2693,9 @@ set_const_flag_1 (cgraph_node *node, bool set_const, bool looping,
|
||||
{
|
||||
/* Virtual thunks access virtual offset in the vtable, so they can
|
||||
only be pure, never const. */
|
||||
if (set_const
|
||||
if (set_const
|
||||
&& (thunk_info::get (e->caller)->virtual_offset_p
|
||||
|| !node->binds_to_current_def_p (e->caller)))
|
||||
|| !node->binds_to_current_def_p (e->caller)))
|
||||
*changed |= e->caller->set_pure_flag (true, looping);
|
||||
else
|
||||
set_const_flag_1 (e->caller, set_const, looping, changed);
|
||||
@ -2757,14 +2765,14 @@ set_pure_flag_1 (cgraph_node *node, void *data)
|
||||
{
|
||||
if (!DECL_PURE_P (node->decl) && !TREE_READONLY (node->decl))
|
||||
{
|
||||
DECL_PURE_P (node->decl) = true;
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = info->looping;
|
||||
DECL_PURE_P (node->decl) = true;
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = info->looping;
|
||||
info->changed = true;
|
||||
}
|
||||
else if (DECL_LOOPING_CONST_OR_PURE_P (node->decl)
|
||||
&& !info->looping)
|
||||
{
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
|
||||
info->changed = true;
|
||||
}
|
||||
}
|
||||
@ -2772,8 +2780,8 @@ set_pure_flag_1 (cgraph_node *node, void *data)
|
||||
{
|
||||
if (DECL_PURE_P (node->decl))
|
||||
{
|
||||
DECL_PURE_P (node->decl) = false;
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
|
||||
DECL_PURE_P (node->decl) = false;
|
||||
DECL_LOOPING_CONST_OR_PURE_P (node->decl) = false;
|
||||
info->changed = true;
|
||||
}
|
||||
}
|
||||
@ -2927,7 +2935,7 @@ cgraph_node::can_remove_if_no_direct_calls_p (bool will_inline)
|
||||
/* If function is not being inlined, we care only about
|
||||
references outside of the comdat group. */
|
||||
if (!will_inline)
|
||||
for (int i = 0; next->iterate_referring (i, ref); i++)
|
||||
for (int i = 0; next->iterate_referring (i, ref); i++)
|
||||
if (ref->referring->get_comdat_group () != get_comdat_group ())
|
||||
return false;
|
||||
}
|
||||
@ -3031,7 +3039,7 @@ collect_callers_of_node_1 (cgraph_node *node, void *data)
|
||||
for (cs = node->callers; cs != NULL; cs = cs->next_caller)
|
||||
if (!cs->indirect_inlining_edge
|
||||
&& !cs->caller->thunk)
|
||||
redirect_callers->safe_push (cs);
|
||||
redirect_callers->safe_push (cs);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -3083,8 +3091,9 @@ clone_of_p (cgraph_node *node, cgraph_node *node2)
|
||||
return true;
|
||||
node = node->callees->callee->ultimate_alias_target ();
|
||||
|
||||
if (!node2->clone.param_adjustments
|
||||
|| node2->clone.param_adjustments->first_param_intact_p ())
|
||||
clone_info *info = clone_info::get (node2);
|
||||
if (!info || !info->param_adjustments
|
||||
|| info->param_adjustments->first_param_intact_p ())
|
||||
return false;
|
||||
if (node2->former_clone_of == node->decl
|
||||
|| node2->former_clone_of == node->former_clone_of)
|
||||
@ -3615,7 +3624,7 @@ cgraph_node::verify_node (void)
|
||||
if (callees)
|
||||
{
|
||||
error ("Alias has call edges");
|
||||
error_found = true;
|
||||
error_found = true;
|
||||
}
|
||||
for (i = 0; iterate_reference (i, ref); i++)
|
||||
if (ref->use != IPA_REF_ALIAS)
|
||||
@ -3642,18 +3651,18 @@ cgraph_node::verify_node (void)
|
||||
if (!callees)
|
||||
{
|
||||
error ("No edge out of thunk node");
|
||||
error_found = true;
|
||||
error_found = true;
|
||||
}
|
||||
else if (callees->next_callee)
|
||||
{
|
||||
error ("More than one edge out of thunk node");
|
||||
error_found = true;
|
||||
error_found = true;
|
||||
}
|
||||
if (gimple_has_body_p (decl) && !inlined_to)
|
||||
{
|
||||
{
|
||||
error ("Thunk is not supposed to have body");
|
||||
error_found = true;
|
||||
}
|
||||
error_found = true;
|
||||
}
|
||||
}
|
||||
else if (analyzed && gimple_has_body_p (decl)
|
||||
&& !TREE_ASM_WRITTEN (decl)
|
||||
@ -3998,6 +4007,7 @@ cgraph_c_finalize (void)
|
||||
{
|
||||
nested_function_info::release ();
|
||||
thunk_info::release ();
|
||||
clone_info::release ();
|
||||
symtab = NULL;
|
||||
|
||||
x_cgraph_nodes_queue = NULL;
|
||||
|
||||
35
gcc/cgraph.h
35
gcc/cgraph.h
@ -691,27 +691,6 @@ struct GTY(()) ipa_replace_map
|
||||
int parm_num;
|
||||
};
|
||||
|
||||
struct GTY(()) cgraph_clone_info
|
||||
{
|
||||
/* Constants discovered by IPA-CP, i.e. which parameter should be replaced
|
||||
with what. */
|
||||
vec<ipa_replace_map *, va_gc> *tree_map;
|
||||
/* Parameter modification that IPA-SRA decided to perform. */
|
||||
ipa_param_adjustments *param_adjustments;
|
||||
/* Lists of dummy-decl and offset pairs representing split formal parameters
|
||||
in the caller. Offsets of all new replacements are enumerated, those
|
||||
coming from the same original parameter have the same dummy decl stored
|
||||
along with them.
|
||||
|
||||
Dummy decls sit in call statement arguments followed by new parameter
|
||||
decls (or their SSA names) in between (caller) clone materialization and
|
||||
call redirection. Redirection then recognizes the dummy variable and
|
||||
together with the stored offsets can reconstruct what exactly the new
|
||||
parameter decls represent and can leave in place only those that the
|
||||
callee expects. */
|
||||
vec<ipa_param_performed_split, va_gc> *performed_splits;
|
||||
};
|
||||
|
||||
enum cgraph_simd_clone_arg_type
|
||||
{
|
||||
SIMD_CLONE_ARG_TYPE_VECTOR,
|
||||
@ -879,7 +858,7 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
|
||||
next_sibling_clone (NULL), prev_sibling_clone (NULL), clones (NULL),
|
||||
clone_of (NULL), call_site_hash (NULL), former_clone_of (NULL),
|
||||
simdclone (NULL), simd_clones (NULL), ipa_transforms_to_apply (vNULL),
|
||||
inlined_to (NULL), rtl (NULL), clone (),
|
||||
inlined_to (NULL), rtl (NULL),
|
||||
count (profile_count::uninitialized ()),
|
||||
count_materialization_scale (REG_BR_PROB_BASE), profile_id (0),
|
||||
unit_id (0), tp_first_run (0), thunk (false),
|
||||
@ -1409,7 +1388,6 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
|
||||
cgraph_node *inlined_to;
|
||||
|
||||
struct cgraph_rtl_info *rtl;
|
||||
cgraph_clone_info clone;
|
||||
|
||||
/* Expected number of executions: calculated in profile.c. */
|
||||
profile_count count;
|
||||
@ -2190,10 +2168,16 @@ struct asmname_hasher : ggc_ptr_hash <symtab_node>
|
||||
static bool equal (symtab_node *n, const_tree t);
|
||||
};
|
||||
|
||||
/* Core summaries maintained about symbols. */
|
||||
|
||||
struct thunk_info;
|
||||
template <class T> class function_summary;
|
||||
typedef function_summary <thunk_info *> thunk_summary;
|
||||
|
||||
struct clone_info;
|
||||
template <class T> class function_summary;
|
||||
typedef function_summary <clone_info *> clone_summary;
|
||||
|
||||
class GTY((tag ("SYMTAB"))) symbol_table
|
||||
{
|
||||
public:
|
||||
@ -2210,7 +2194,7 @@ public:
|
||||
function_flags_ready (false), cpp_implicit_aliases_done (false),
|
||||
section_hash (NULL), assembler_name_hash (NULL), init_priority_hash (NULL),
|
||||
dump_file (NULL), ipa_clones_dump_file (NULL), cloned_nodes (),
|
||||
m_thunks (NULL),
|
||||
m_thunks (NULL), m_clones (NULL),
|
||||
m_first_edge_removal_hook (NULL), m_first_cgraph_removal_hook (NULL),
|
||||
m_first_edge_duplicated_hook (NULL), m_first_cgraph_duplicated_hook (NULL),
|
||||
m_first_cgraph_insertion_hook (NULL), m_first_varpool_insertion_hook (NULL),
|
||||
@ -2495,6 +2479,9 @@ public:
|
||||
/* Thunk annotations. */
|
||||
thunk_summary *m_thunks;
|
||||
|
||||
/* Virtual clone annotations. */
|
||||
clone_summary *m_clones;
|
||||
|
||||
private:
|
||||
/* Allocate a cgraph_edge structure and fill it with data according to the
|
||||
parameters of which only CALLEE can be NULL (when creating an indirect
|
||||
|
||||
@ -86,6 +86,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "ipa-prop.h"
|
||||
#include "ipa-fnsummary.h"
|
||||
#include "symtab-thunks.h"
|
||||
#include "symtab-clones.h"
|
||||
|
||||
/* Create clone of edge in the node N represented by CALL_EXPR
|
||||
the callgraph. */
|
||||
@ -201,16 +202,17 @@ duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node)
|
||||
}
|
||||
|
||||
tree new_decl;
|
||||
if (node->clone.param_adjustments)
|
||||
clone_info *info = clone_info::get (node);
|
||||
if (info && info->param_adjustments)
|
||||
{
|
||||
/* We do not need to duplicate this_adjusting thunks if we have removed
|
||||
this. */
|
||||
if (i->this_adjusting
|
||||
&& !node->clone.param_adjustments->first_param_intact_p ())
|
||||
&& !info->param_adjustments->first_param_intact_p ())
|
||||
return node;
|
||||
|
||||
new_decl = copy_node (thunk->decl);
|
||||
ipa_param_body_adjustments body_adj (node->clone.param_adjustments,
|
||||
ipa_param_body_adjustments body_adj (info->param_adjustments,
|
||||
new_decl);
|
||||
body_adj.modify_formal_parameters ();
|
||||
}
|
||||
@ -237,7 +239,9 @@ duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node)
|
||||
new_thunk->thunk = thunk->thunk;
|
||||
new_thunk->unique_name = in_lto_p;
|
||||
new_thunk->former_clone_of = thunk->decl;
|
||||
new_thunk->clone.param_adjustments = node->clone.param_adjustments;
|
||||
if (info->param_adjustments)
|
||||
clone_info::get_create (new_thunk)->param_adjustments
|
||||
= info->param_adjustments;
|
||||
new_thunk->unit_id = thunk->unit_id;
|
||||
new_thunk->merged_comdat = thunk->merged_comdat;
|
||||
new_thunk->merged_extern_inline = thunk->merged_extern_inline;
|
||||
@ -403,13 +407,16 @@ cgraph_node::create_clone (tree new_decl, profile_count prof_count,
|
||||
new_node->unit_id = unit_id;
|
||||
new_node->merged_comdat = merged_comdat;
|
||||
new_node->merged_extern_inline = merged_extern_inline;
|
||||
clone_info *info = clone_info::get (this);
|
||||
|
||||
if (param_adjustments)
|
||||
new_node->clone.param_adjustments = param_adjustments;
|
||||
else
|
||||
new_node->clone.param_adjustments = clone.param_adjustments;
|
||||
new_node->clone.tree_map = NULL;
|
||||
new_node->clone.performed_splits = vec_safe_copy (clone.performed_splits);
|
||||
clone_info::get_create (new_node)->param_adjustments = param_adjustments;
|
||||
else if (info && info->param_adjustments)
|
||||
clone_info::get_create (new_node)->param_adjustments
|
||||
= info->param_adjustments;
|
||||
if (info && info->performed_splits)
|
||||
clone_info::get_create (new_node)->performed_splits
|
||||
= vec_safe_copy (info->performed_splits);
|
||||
new_node->split_part = split_part;
|
||||
|
||||
FOR_EACH_VEC_ELT (redirect_callers, i, e)
|
||||
@ -616,7 +623,8 @@ cgraph_node::create_virtual_clone (vec<cgraph_edge *> redirect_callers,
|
||||
ABI support for this. */
|
||||
set_new_clone_decl_and_node_flags (new_node);
|
||||
new_node->ipcp_clone = ipcp_clone;
|
||||
new_node->clone.tree_map = tree_map;
|
||||
if (tree_map)
|
||||
clone_info::get_create (new_node)->tree_map = tree_map;
|
||||
if (!implicit_section)
|
||||
new_node->set_section (get_section ());
|
||||
|
||||
@ -682,7 +690,9 @@ cgraph_node::find_replacement (void)
|
||||
clones = NULL;
|
||||
|
||||
/* Copy clone info. */
|
||||
next_inline_clone->clone = clone;
|
||||
clone_info *info = clone_info::get (this);
|
||||
if (info)
|
||||
*clone_info::get_create (next_inline_clone) = *info;
|
||||
|
||||
/* Now place it into clone tree at same level at NODE. */
|
||||
next_inline_clone->clone_of = clone_of;
|
||||
@ -1087,6 +1097,7 @@ void cgraph_node::remove_from_clone_tree ()
|
||||
void
|
||||
cgraph_node::materialize_clone ()
|
||||
{
|
||||
clone_info *info = clone_info::get (this);
|
||||
clone_of->get_untransformed_body ();
|
||||
former_clone_of = clone_of->decl;
|
||||
if (clone_of->former_clone_of)
|
||||
@ -1096,15 +1107,15 @@ cgraph_node::materialize_clone ()
|
||||
fprintf (symtab->dump_file, "cloning %s to %s\n",
|
||||
clone_of->dump_name (),
|
||||
dump_name ());
|
||||
if (clone.tree_map)
|
||||
if (info->tree_map)
|
||||
{
|
||||
fprintf (symtab->dump_file, " replace map:");
|
||||
for (unsigned int i = 0;
|
||||
i < vec_safe_length (clone.tree_map);
|
||||
i < vec_safe_length (info->tree_map);
|
||||
i++)
|
||||
{
|
||||
ipa_replace_map *replace_info;
|
||||
replace_info = (*clone.tree_map)[i];
|
||||
replace_info = (*info->tree_map)[i];
|
||||
fprintf (symtab->dump_file, "%s %i -> ",
|
||||
i ? "," : "", replace_info->parm_num);
|
||||
print_generic_expr (symtab->dump_file,
|
||||
@ -1112,13 +1123,14 @@ cgraph_node::materialize_clone ()
|
||||
}
|
||||
fprintf (symtab->dump_file, "\n");
|
||||
}
|
||||
if (clone.param_adjustments)
|
||||
clone.param_adjustments->dump (symtab->dump_file);
|
||||
if (info->param_adjustments)
|
||||
info->param_adjustments->dump (symtab->dump_file);
|
||||
}
|
||||
clear_stmts_in_references ();
|
||||
/* Copy the OLD_VERSION_NODE function tree to the new version. */
|
||||
tree_function_versioning (clone_of->decl, decl,
|
||||
clone.tree_map, clone.param_adjustments,
|
||||
info ? info->tree_map : NULL,
|
||||
info ? info->param_adjustments : NULL,
|
||||
true, NULL, NULL);
|
||||
if (symtab->dump_file)
|
||||
{
|
||||
|
||||
@ -1727,6 +1727,7 @@ open_base_files (void)
|
||||
"target-globals.h", "ipa-ref.h", "cgraph.h", "symbol-summary.h",
|
||||
"ipa-prop.h", "ipa-fnsummary.h", "dwarf2out.h", "omp-general.h",
|
||||
"omp-offload.h", "ipa-modref-tree.h", "ipa-modref.h", "symtab-thunks.h",
|
||||
"symtab-clones.h",
|
||||
NULL
|
||||
};
|
||||
const char *const *ifp;
|
||||
|
||||
23
gcc/ipa-cp.c
23
gcc/ipa-cp.c
@ -124,6 +124,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "stringpool.h"
|
||||
#include "attribs.h"
|
||||
#include "dbgcnt.h"
|
||||
#include "symtab-clones.h"
|
||||
|
||||
template <typename valtype> class ipcp_value;
|
||||
|
||||
@ -1226,18 +1227,21 @@ initialize_node_lattices (struct cgraph_node *node)
|
||||
|
||||
auto_vec<bool, 16> surviving_params;
|
||||
bool pre_modified = false;
|
||||
if (!disable && node->clone.param_adjustments)
|
||||
|
||||
clone_info *cinfo = clone_info::get (node);
|
||||
|
||||
if (!disable && cinfo && cinfo->param_adjustments)
|
||||
{
|
||||
/* At the moment all IPA optimizations should use the number of
|
||||
parameters of the prevailing decl as the m_always_copy_start.
|
||||
Handling any other value would complicate the code below, so for the
|
||||
time bing let's only assert it is so. */
|
||||
gcc_assert ((node->clone.param_adjustments->m_always_copy_start
|
||||
gcc_assert ((cinfo->param_adjustments->m_always_copy_start
|
||||
== ipa_get_param_count (info))
|
||||
|| node->clone.param_adjustments->m_always_copy_start < 0);
|
||||
|| cinfo->param_adjustments->m_always_copy_start < 0);
|
||||
|
||||
pre_modified = true;
|
||||
node->clone.param_adjustments->get_surviving_params (&surviving_params);
|
||||
cinfo->param_adjustments->get_surviving_params (&surviving_params);
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS)
|
||||
&& !node->alias && !node->thunk)
|
||||
@ -4456,9 +4460,10 @@ want_remove_some_param_p (cgraph_node *node, vec<tree> known_csts)
|
||||
|
||||
if (!filled_vec)
|
||||
{
|
||||
if (!node->clone.param_adjustments)
|
||||
clone_info *info = clone_info::get (node);
|
||||
if (!info || !info->param_adjustments)
|
||||
return true;
|
||||
node->clone.param_adjustments->get_surviving_params (&surviving);
|
||||
info->param_adjustments->get_surviving_params (&surviving);
|
||||
filled_vec = true;
|
||||
}
|
||||
if (surviving.length() < (unsigned) i && surviving[i])
|
||||
@ -4484,7 +4489,9 @@ create_specialized_node (struct cgraph_node *node,
|
||||
struct ipa_agg_replacement_value *av;
|
||||
struct cgraph_node *new_node;
|
||||
int i, count = ipa_get_param_count (info);
|
||||
ipa_param_adjustments *old_adjustments = node->clone.param_adjustments;
|
||||
clone_info *cinfo = clone_info::get (node);
|
||||
ipa_param_adjustments *old_adjustments = cinfo
|
||||
? cinfo->param_adjustments : NULL;
|
||||
ipa_param_adjustments *new_adjustments;
|
||||
gcc_assert (!info->ipcp_orig_node);
|
||||
gcc_assert (node->can_change_signature
|
||||
@ -4538,7 +4545,7 @@ create_specialized_node (struct cgraph_node *node,
|
||||
else
|
||||
new_adjustments = NULL;
|
||||
|
||||
replace_trees = vec_safe_copy (node->clone.tree_map);
|
||||
replace_trees = cinfo ? vec_safe_copy (cinfo->tree_map) : NULL;
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
tree t = known_csts[i];
|
||||
|
||||
@ -84,6 +84,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "stringpool.h"
|
||||
#include "attribs.h"
|
||||
#include "tree-into-ssa.h"
|
||||
#include "symtab-clones.h"
|
||||
|
||||
/* Summaries. */
|
||||
fast_function_summary <ipa_fn_summary *, va_gc> *ipa_fn_summaries;
|
||||
@ -811,9 +812,10 @@ ipa_fn_summary_t::duplicate (cgraph_node *src,
|
||||
that are known to be false or true. */
|
||||
info->conds = vec_safe_copy (info->conds);
|
||||
|
||||
clone_info *cinfo = clone_info::get (dst);
|
||||
/* When there are any replacements in the function body, see if we can figure
|
||||
out that something was optimized out. */
|
||||
if (ipa_node_params_sum && dst->clone.tree_map)
|
||||
if (ipa_node_params_sum && cinfo && cinfo->tree_map)
|
||||
{
|
||||
vec<size_time_entry, va_gc> *entry = info->size_time_table;
|
||||
/* Use SRC parm info since it may not be copied yet. */
|
||||
@ -834,7 +836,7 @@ ipa_fn_summary_t::duplicate (cgraph_node *src,
|
||||
{
|
||||
struct ipa_replace_map *r;
|
||||
|
||||
for (j = 0; vec_safe_iterate (dst->clone.tree_map, j, &r); j++)
|
||||
for (j = 0; vec_safe_iterate (cinfo->tree_map, j, &r); j++)
|
||||
{
|
||||
if (r->parm_num == i)
|
||||
{
|
||||
|
||||
@ -60,6 +60,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "ipa-prop.h"
|
||||
#include "ipa-fnsummary.h"
|
||||
#include "attr-fnspec.h"
|
||||
#include "symtab-clones.h"
|
||||
|
||||
/* Class (from which there is one global instance) that holds modref summaries
|
||||
for all analyzed functions. */
|
||||
@ -1606,7 +1607,8 @@ modref_read (void)
|
||||
static void
|
||||
update_signature (struct cgraph_node *node)
|
||||
{
|
||||
if (!node->clone.param_adjustments)
|
||||
clone_info *info = clone_info::get (node);
|
||||
if (!info || !info->param_adjustments)
|
||||
return;
|
||||
|
||||
modref_summary *r = optimization_summaries
|
||||
@ -1625,9 +1627,9 @@ update_signature (struct cgraph_node *node)
|
||||
size_t i, max = 0;
|
||||
ipa_adjusted_param *p;
|
||||
|
||||
FOR_EACH_VEC_SAFE_ELT (node->clone.param_adjustments->m_adj_params, i, p)
|
||||
FOR_EACH_VEC_SAFE_ELT (info->param_adjustments->m_adj_params, i, p)
|
||||
{
|
||||
int idx = node->clone.param_adjustments->get_original_index (i);
|
||||
int idx = info->param_adjustments->get_original_index (i);
|
||||
if (idx > (int)max)
|
||||
max = idx;
|
||||
}
|
||||
@ -1637,9 +1639,9 @@ update_signature (struct cgraph_node *node)
|
||||
map.reserve (max + 1);
|
||||
for (i = 0; i <= max; i++)
|
||||
map.quick_push (-1);
|
||||
FOR_EACH_VEC_SAFE_ELT (node->clone.param_adjustments->m_adj_params, i, p)
|
||||
FOR_EACH_VEC_SAFE_ELT (info->param_adjustments->m_adj_params, i, p)
|
||||
{
|
||||
int idx = node->clone.param_adjustments->get_original_index (i);
|
||||
int idx = info->param_adjustments->get_original_index (i);
|
||||
if (idx >= 0)
|
||||
map[idx] = i;
|
||||
}
|
||||
|
||||
@ -40,6 +40,9 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "builtins.h"
|
||||
#include "tree-ssa.h"
|
||||
#include "tree-inline.h"
|
||||
#include "alloc-pool.h"
|
||||
#include "symbol-summary.h"
|
||||
#include "symtab-clones.h"
|
||||
|
||||
|
||||
/* Actual prefixes of different newly synthetized parameters. Keep in sync
|
||||
@ -1072,7 +1075,8 @@ ipa_param_body_adjustments::common_initialization (tree old_fndecl,
|
||||
ipa_param_performed_split ps;
|
||||
ps.dummy_decl = dummy_decl;
|
||||
ps.unit_offset = apm->unit_offset;
|
||||
vec_safe_push (m_id->dst_node->clone.performed_splits, ps);
|
||||
vec_safe_push (clone_info::get_create
|
||||
(m_id->dst_node)->performed_splits, ps);
|
||||
}
|
||||
else
|
||||
register_replacement (apm, new_parm);
|
||||
@ -1131,11 +1135,11 @@ ipa_param_body_adjustments::common_initialization (tree old_fndecl,
|
||||
when they were in fact replaced by a constant. */
|
||||
auto_vec <int, 16> index_mapping;
|
||||
bool need_remap = false;
|
||||
clone_info *info = clone_info::get (m_id->src_node);
|
||||
|
||||
if (m_id && m_id->src_node->clone.param_adjustments)
|
||||
if (m_id && info && info->param_adjustments)
|
||||
{
|
||||
ipa_param_adjustments *prev_adjustments
|
||||
= m_id->src_node->clone.param_adjustments;
|
||||
ipa_param_adjustments *prev_adjustments = info->param_adjustments;
|
||||
prev_adjustments->get_updated_indices (&index_mapping);
|
||||
need_remap = true;
|
||||
}
|
||||
|
||||
@ -53,6 +53,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "builtins.h"
|
||||
#include "tree-cfgcleanup.h"
|
||||
#include "options.h"
|
||||
#include "symtab-clones.h"
|
||||
|
||||
/* Function summary where the parameter infos are actually stored. */
|
||||
ipa_node_params_t *ipa_node_params_sum = NULL;
|
||||
@ -5419,12 +5420,13 @@ adjust_agg_replacement_values (struct cgraph_node *node,
|
||||
struct ipa_agg_replacement_value *aggval)
|
||||
{
|
||||
struct ipa_agg_replacement_value *v;
|
||||
clone_info *cinfo = clone_info::get (node);
|
||||
|
||||
if (!node->clone.param_adjustments)
|
||||
if (!cinfo || !cinfo->param_adjustments)
|
||||
return;
|
||||
|
||||
auto_vec<int, 16> new_indices;
|
||||
node->clone.param_adjustments->get_updated_indices (&new_indices);
|
||||
cinfo->param_adjustments->get_updated_indices (&new_indices);
|
||||
for (v = aggval; v; v = v->next)
|
||||
{
|
||||
gcc_checking_assert (v->index >= 0);
|
||||
@ -5577,9 +5579,10 @@ ipcp_get_parm_bits (tree parm, tree *value, widest_int *mask)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cnode->clone.param_adjustments)
|
||||
clone_info *cinfo = clone_info::get (cnode);
|
||||
if (cinfo && cinfo->param_adjustments)
|
||||
{
|
||||
i = cnode->clone.param_adjustments->get_original_index (i);
|
||||
i = cinfo->param_adjustments->get_original_index (i);
|
||||
if (i < 0)
|
||||
return false;
|
||||
}
|
||||
@ -5610,9 +5613,10 @@ ipcp_update_bits (struct cgraph_node *node)
|
||||
|
||||
auto_vec<int, 16> new_indices;
|
||||
bool need_remapping = false;
|
||||
if (node->clone.param_adjustments)
|
||||
clone_info *cinfo = clone_info::get (node);
|
||||
if (cinfo && cinfo->param_adjustments)
|
||||
{
|
||||
node->clone.param_adjustments->get_updated_indices (&new_indices);
|
||||
cinfo->param_adjustments->get_updated_indices (&new_indices);
|
||||
need_remapping = true;
|
||||
}
|
||||
auto_vec <tree, 16> parm_decls;
|
||||
@ -5731,9 +5735,10 @@ ipcp_update_vr (struct cgraph_node *node)
|
||||
|
||||
auto_vec<int, 16> new_indices;
|
||||
bool need_remapping = false;
|
||||
if (node->clone.param_adjustments)
|
||||
clone_info *cinfo = clone_info::get (node);
|
||||
if (cinfo && cinfo->param_adjustments)
|
||||
{
|
||||
node->clone.param_adjustments->get_updated_indices (&new_indices);
|
||||
cinfo->param_adjustments->get_updated_indices (&new_indices);
|
||||
need_remapping = true;
|
||||
}
|
||||
auto_vec <tree, 16> parm_decls;
|
||||
|
||||
@ -84,6 +84,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "cfganal.h"
|
||||
#include "tree-streamer.h"
|
||||
#include "internal-fn.h"
|
||||
#include "symtab-clones.h"
|
||||
|
||||
static void ipa_sra_summarize_function (cgraph_node *);
|
||||
|
||||
@ -3686,10 +3687,11 @@ process_isra_node_results (cgraph_node *node,
|
||||
|
||||
auto_vec<bool, 16> surviving_params;
|
||||
bool check_surviving = false;
|
||||
if (node->clone.param_adjustments)
|
||||
clone_info *cinfo = clone_info::get (node);
|
||||
if (cinfo && cinfo->param_adjustments)
|
||||
{
|
||||
check_surviving = true;
|
||||
node->clone.param_adjustments->get_surviving_params (&surviving_params);
|
||||
cinfo->param_adjustments->get_surviving_params (&surviving_params);
|
||||
}
|
||||
|
||||
unsigned param_count = vec_safe_length (ifs->m_parameters);
|
||||
@ -3723,7 +3725,8 @@ process_isra_node_results (cgraph_node *node,
|
||||
}
|
||||
|
||||
vec<ipa_adjusted_param, va_gc> *new_params = NULL;
|
||||
if (ipa_param_adjustments *old_adjustments = node->clone.param_adjustments)
|
||||
if (ipa_param_adjustments *old_adjustments
|
||||
= cinfo ? cinfo->param_adjustments : NULL)
|
||||
{
|
||||
unsigned old_adj_len = vec_safe_length (old_adjustments->m_adj_params);
|
||||
for (unsigned i = 0; i < old_adj_len; i++)
|
||||
@ -3784,10 +3787,11 @@ disable_unavailable_parameters (cgraph_node *node, isra_func_summary *ifs)
|
||||
|
||||
auto_vec<bool, 16> surviving_params;
|
||||
bool check_surviving = false;
|
||||
if (node->clone.param_adjustments)
|
||||
clone_info *cinfo = clone_info::get (node);
|
||||
if (cinfo && cinfo->param_adjustments)
|
||||
{
|
||||
check_surviving = true;
|
||||
node->clone.param_adjustments->get_surviving_params (&surviving_params);
|
||||
cinfo->param_adjustments->get_surviving_params (&surviving_params);
|
||||
}
|
||||
bool dumped_first = false;
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
|
||||
@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "alloc-pool.h"
|
||||
#include "symbol-summary.h"
|
||||
#include "symtab-thunks.h"
|
||||
#include "symtab-clones.h"
|
||||
|
||||
/* True when asm nodes has been output. */
|
||||
bool asm_nodes_output = false;
|
||||
@ -1823,9 +1824,10 @@ input_offload_tables (bool do_force_output)
|
||||
static int
|
||||
output_cgraph_opt_summary_p (struct cgraph_node *node)
|
||||
{
|
||||
return ((node->clone_of || node->former_clone_of)
|
||||
&& (node->clone.tree_map
|
||||
|| node->clone.param_adjustments));
|
||||
if (node->clone_of || node->former_clone_of)
|
||||
return true;
|
||||
clone_info *info = clone_info::get (node);
|
||||
return info && (info->tree_map || info->param_adjustments);
|
||||
}
|
||||
|
||||
/* Output optimization summary for EDGE to OB. */
|
||||
@ -1849,9 +1851,12 @@ output_node_opt_summary (struct output_block *ob,
|
||||
/* TODO: Should this code be moved to ipa-param-manipulation? */
|
||||
struct bitpack_d bp;
|
||||
bp = bitpack_create (ob->main_stream);
|
||||
bp_pack_value (&bp, (node->clone.param_adjustments != NULL), 1);
|
||||
clone_info *info = clone_info::get (node);
|
||||
|
||||
bp_pack_value (&bp, (info && info->param_adjustments != NULL), 1);
|
||||
streamer_write_bitpack (&bp);
|
||||
if (ipa_param_adjustments *adjustments = node->clone.param_adjustments)
|
||||
if (ipa_param_adjustments *adjustments
|
||||
= info ? info->param_adjustments : NULL)
|
||||
{
|
||||
streamer_write_uhwi (ob, vec_safe_length (adjustments->m_adj_params));
|
||||
ipa_adjusted_param *adj;
|
||||
@ -1879,17 +1884,18 @@ output_node_opt_summary (struct output_block *ob,
|
||||
}
|
||||
streamer_write_hwi (ob, adjustments->m_always_copy_start);
|
||||
bp = bitpack_create (ob->main_stream);
|
||||
bp_pack_value (&bp, node->clone.param_adjustments->m_skip_return, 1);
|
||||
bp_pack_value (&bp, info->param_adjustments->m_skip_return, 1);
|
||||
streamer_write_bitpack (&bp);
|
||||
}
|
||||
|
||||
streamer_write_uhwi (ob, vec_safe_length (node->clone.tree_map));
|
||||
FOR_EACH_VEC_SAFE_ELT (node->clone.tree_map, i, map)
|
||||
{
|
||||
streamer_write_uhwi (ob, map->parm_num);
|
||||
gcc_assert (EXPR_LOCATION (map->new_tree) == UNKNOWN_LOCATION);
|
||||
stream_write_tree (ob, map->new_tree, true);
|
||||
}
|
||||
streamer_write_uhwi (ob, info ? vec_safe_length (info->tree_map) : 0);
|
||||
if (info)
|
||||
FOR_EACH_VEC_SAFE_ELT (info->tree_map, i, map)
|
||||
{
|
||||
streamer_write_uhwi (ob, map->parm_num);
|
||||
gcc_assert (EXPR_LOCATION (map->new_tree) == UNKNOWN_LOCATION);
|
||||
stream_write_tree (ob, map->new_tree, true);
|
||||
}
|
||||
|
||||
if (lto_symtab_encoder_in_partition_p (encoder, node))
|
||||
{
|
||||
@ -1959,6 +1965,8 @@ input_node_opt_summary (struct cgraph_node *node,
|
||||
struct bitpack_d bp;
|
||||
bp = streamer_read_bitpack (ib_main);
|
||||
bool have_adjustments = bp_unpack_value (&bp, 1);
|
||||
clone_info *info = clone_info::get_create (node);
|
||||
|
||||
if (have_adjustments)
|
||||
{
|
||||
count = streamer_read_uhwi (ib_main);
|
||||
@ -1991,7 +1999,7 @@ input_node_opt_summary (struct cgraph_node *node,
|
||||
int always_copy_start = streamer_read_hwi (ib_main);
|
||||
bp = streamer_read_bitpack (ib_main);
|
||||
bool skip_return = bp_unpack_value (&bp, 1);
|
||||
node->clone.param_adjustments
|
||||
info->param_adjustments
|
||||
= (new (ggc_alloc <ipa_param_adjustments> ())
|
||||
ipa_param_adjustments (new_params, always_copy_start, skip_return));
|
||||
}
|
||||
@ -2001,7 +2009,7 @@ input_node_opt_summary (struct cgraph_node *node,
|
||||
{
|
||||
struct ipa_replace_map *map = ggc_alloc<ipa_replace_map> ();
|
||||
|
||||
vec_safe_push (node->clone.tree_map, map);
|
||||
vec_safe_push (info->tree_map, map);
|
||||
map->parm_num = streamer_read_uhwi (ib_main);
|
||||
map->new_tree = stream_read_tree (ib_main, data_in);
|
||||
}
|
||||
|
||||
76
gcc/symtab-clones.cc
Normal file
76
gcc/symtab-clones.cc
Normal file
@ -0,0 +1,76 @@
|
||||
/* Support for virtual clones in symbol table.
|
||||
Copyright (C) 2003-2020 Free Software Foundation, Inc.
|
||||
Contributed by Jan Hubicka
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "backend.h"
|
||||
#include "tree.h"
|
||||
#include "gimple.h"
|
||||
#include "predict.h"
|
||||
#include "target.h"
|
||||
#include "rtl.h"
|
||||
#include "alloc-pool.h"
|
||||
#include "cgraph.h"
|
||||
#include "symbol-summary.h"
|
||||
#include "symtab-clones.h"
|
||||
#include "lto-streamer.h"
|
||||
#include "data-streamer.h"
|
||||
|
||||
namespace {
|
||||
|
||||
/* Function summary for clone_infos. */
|
||||
class GTY((user)) clone_infos_t: public function_summary <clone_info *>
|
||||
{
|
||||
public:
|
||||
clone_infos_t (symbol_table *table, bool ggc):
|
||||
function_summary<clone_info *> (table, ggc) { }
|
||||
|
||||
/* Hook that is called by summary when a node is duplicated. */
|
||||
virtual void duplicate (cgraph_node *node,
|
||||
cgraph_node *node2,
|
||||
clone_info *data,
|
||||
clone_info *data2);
|
||||
};
|
||||
|
||||
/* Duplication hook. */
|
||||
void
|
||||
clone_infos_t::duplicate (cgraph_node *, cgraph_node *,
|
||||
clone_info *src, clone_info *dst)
|
||||
{
|
||||
*dst = *src;
|
||||
}
|
||||
|
||||
} /* anon namespace */
|
||||
|
||||
/* Return thunk_info possibly creating new one. */
|
||||
clone_info *
|
||||
clone_info::get_create (cgraph_node *node)
|
||||
{
|
||||
if (!symtab->m_clones)
|
||||
{
|
||||
symtab->m_clones
|
||||
= new (ggc_alloc_no_dtor <clone_infos_t> ())
|
||||
clone_infos_t (symtab, true);
|
||||
symtab->m_clones->disable_insertion_hook ();
|
||||
symtab->m_clones->disable_duplication_hook ();
|
||||
}
|
||||
return symtab->m_clones->get_create (node);
|
||||
}
|
||||
90
gcc/symtab-clones.h
Normal file
90
gcc/symtab-clones.h
Normal file
@ -0,0 +1,90 @@
|
||||
/* Representation of adjustment made to virtual clones in the symbol table.
|
||||
Copyright (C) 2003-2020 Free Software Foundation, Inc.
|
||||
Contributed by Jan Hubicka
|
||||
|
||||
This file is part of GCC.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License as published by the Free
|
||||
Software Foundation; either version 3, or (at your option) any later
|
||||
version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef GCC_SYMTAB_CLONES_H
|
||||
#define GCC_SYMTAB_CLONES_H
|
||||
|
||||
struct GTY(()) clone_info
|
||||
{
|
||||
/* Constructor. */
|
||||
clone_info ()
|
||||
: tree_map (NULL),
|
||||
param_adjustments (NULL),
|
||||
performed_splits (NULL)
|
||||
{
|
||||
}
|
||||
/* Constants discovered by IPA-CP, i.e. which parameter should be replaced
|
||||
with what. */
|
||||
vec<ipa_replace_map *, va_gc> *tree_map;
|
||||
/* Parameter modification that IPA-SRA decided to perform. */
|
||||
ipa_param_adjustments *param_adjustments;
|
||||
/* Lists of dummy-decl and offset pairs representing split formal parameters
|
||||
in the caller. Offsets of all new replacements are enumerated, those
|
||||
coming from the same original parameter have the same dummy decl stored
|
||||
along with them.
|
||||
|
||||
Dummy decls sit in call statement arguments followed by new parameter
|
||||
decls (or their SSA names) in between (caller) clone materialization and
|
||||
call redirection. Redirection then recognizes the dummy variable and
|
||||
together with the stored offsets can reconstruct what exactly the new
|
||||
parameter decls represent and can leave in place only those that the
|
||||
callee expects. */
|
||||
vec<ipa_param_performed_split, va_gc> *performed_splits;
|
||||
|
||||
/* Return clone_info, if available. */
|
||||
static clone_info *get (cgraph_node *node);
|
||||
|
||||
/* Return clone_info possibly creating new one. */
|
||||
static clone_info *get_create (cgraph_node *node);
|
||||
|
||||
/* Remove clone_info. */
|
||||
static void remove (cgraph_node *node);
|
||||
|
||||
/* Release all clone_infos. */
|
||||
static void release (void);
|
||||
};
|
||||
|
||||
/* Return clone_info, if available. */
|
||||
inline clone_info *
|
||||
clone_info::get (cgraph_node *node)
|
||||
{
|
||||
if (!symtab->m_clones)
|
||||
return NULL;
|
||||
return symtab->m_clones->get (node);
|
||||
}
|
||||
|
||||
|
||||
/* Remove clone_info association for NODE. */
|
||||
inline void
|
||||
clone_info::remove (cgraph_node *node)
|
||||
{
|
||||
symtab->m_clones->remove (node);
|
||||
}
|
||||
|
||||
/* Free clone info summaries. */
|
||||
inline void
|
||||
clone_info::release ()
|
||||
{
|
||||
if (symtab->m_clones)
|
||||
delete (symtab->m_clones);
|
||||
symtab->m_clones = NULL;
|
||||
}
|
||||
|
||||
#endif /* GCC_SYMTAB_CLONES_H */
|
||||
@ -64,6 +64,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "alloc-pool.h"
|
||||
#include "symbol-summary.h"
|
||||
#include "symtab-thunks.h"
|
||||
#include "symtab-clones.h"
|
||||
|
||||
/* I'm not real happy about this, but we need to handle gimple and
|
||||
non-gimple trees. */
|
||||
@ -4702,6 +4703,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id,
|
||||
use_operand_p use;
|
||||
gimple *simtenter_stmt = NULL;
|
||||
vec<tree> *simtvars_save;
|
||||
clone_info *info;
|
||||
|
||||
/* The gimplifier uses input_location in too many places, such as
|
||||
internal_get_tmp_var (). */
|
||||
@ -5024,31 +5026,33 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id,
|
||||
/* Add local vars in this inlined callee to caller. */
|
||||
add_local_variables (id->src_cfun, cfun, id);
|
||||
|
||||
if (id->src_node->clone.performed_splits)
|
||||
info = clone_info::get (id->src_node);
|
||||
if (info && info->performed_splits)
|
||||
{
|
||||
clone_info *dst_info = clone_info::get_create (id->dst_node);
|
||||
/* Any calls from the inlined function will be turned into calls from the
|
||||
function we inline into. We must preserve notes about how to split
|
||||
parameters such calls should be redirected/updated. */
|
||||
unsigned len = vec_safe_length (id->src_node->clone.performed_splits);
|
||||
unsigned len = vec_safe_length (info->performed_splits);
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
ipa_param_performed_split ps
|
||||
= (*id->src_node->clone.performed_splits)[i];
|
||||
= (*info->performed_splits)[i];
|
||||
ps.dummy_decl = remap_decl (ps.dummy_decl, id);
|
||||
vec_safe_push (id->dst_node->clone.performed_splits, ps);
|
||||
vec_safe_push (dst_info->performed_splits, ps);
|
||||
}
|
||||
|
||||
if (flag_checking)
|
||||
{
|
||||
len = vec_safe_length (id->dst_node->clone.performed_splits);
|
||||
len = vec_safe_length (dst_info->performed_splits);
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
ipa_param_performed_split *ps1
|
||||
= &(*id->dst_node->clone.performed_splits)[i];
|
||||
= &(*dst_info->performed_splits)[i];
|
||||
for (unsigned j = i + 1; j < len; j++)
|
||||
{
|
||||
ipa_param_performed_split *ps2
|
||||
= &(*id->dst_node->clone.performed_splits)[j];
|
||||
= &(*dst_info->performed_splits)[j];
|
||||
gcc_assert (ps1->dummy_decl != ps2->dummy_decl
|
||||
|| ps1->unit_offset != ps2->unit_offset);
|
||||
}
|
||||
@ -6074,8 +6078,9 @@ tree_versionable_function_p (tree fndecl)
|
||||
static void
|
||||
update_clone_info (copy_body_data * id)
|
||||
{
|
||||
clone_info *dst_info = clone_info::get (id->dst_node);
|
||||
vec<ipa_param_performed_split, va_gc> *cur_performed_splits
|
||||
= id->dst_node->clone.performed_splits;
|
||||
= dst_info ? dst_info->performed_splits : NULL;
|
||||
if (cur_performed_splits)
|
||||
{
|
||||
unsigned len = cur_performed_splits->length ();
|
||||
@ -6092,23 +6097,24 @@ update_clone_info (copy_body_data * id)
|
||||
for (node = id->dst_node->clones; node != id->dst_node;)
|
||||
{
|
||||
/* First update replace maps to match the new body. */
|
||||
if (node->clone.tree_map)
|
||||
{
|
||||
clone_info *info = clone_info::get (node);
|
||||
if (info && info->tree_map)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < vec_safe_length (node->clone.tree_map); i++)
|
||||
for (i = 0; i < vec_safe_length (info->tree_map); i++)
|
||||
{
|
||||
struct ipa_replace_map *replace_info;
|
||||
replace_info = (*node->clone.tree_map)[i];
|
||||
replace_info = (*info->tree_map)[i];
|
||||
walk_tree (&replace_info->new_tree, copy_tree_body_r, id, NULL);
|
||||
}
|
||||
}
|
||||
if (node->clone.performed_splits)
|
||||
if (info && info->performed_splits)
|
||||
{
|
||||
unsigned len = vec_safe_length (node->clone.performed_splits);
|
||||
unsigned len = vec_safe_length (info->performed_splits);
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
{
|
||||
ipa_param_performed_split *ps
|
||||
= &(*node->clone.performed_splits)[i];
|
||||
= &(*info->performed_splits)[i];
|
||||
ps->dummy_decl = remap_decl (ps->dummy_decl, id);
|
||||
}
|
||||
}
|
||||
@ -6118,10 +6124,12 @@ update_clone_info (copy_body_data * id)
|
||||
a copy of function body for later during inlining, that would just
|
||||
duplicate all entries. So let's have a look whether anything
|
||||
referring to the first dummy_decl is present. */
|
||||
unsigned dst_len = vec_safe_length (node->clone.performed_splits);
|
||||
if (!info)
|
||||
info = clone_info::get_create (node);
|
||||
unsigned dst_len = vec_safe_length (info->performed_splits);
|
||||
ipa_param_performed_split *first = &(*cur_performed_splits)[0];
|
||||
for (unsigned i = 0; i < dst_len; i++)
|
||||
if ((*node->clone.performed_splits)[i].dummy_decl
|
||||
if ((*info->performed_splits)[i].dummy_decl
|
||||
== first->dummy_decl)
|
||||
{
|
||||
len = 0;
|
||||
@ -6129,18 +6137,18 @@ update_clone_info (copy_body_data * id)
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < len; i++)
|
||||
vec_safe_push (node->clone.performed_splits,
|
||||
vec_safe_push (info->performed_splits,
|
||||
(*cur_performed_splits)[i]);
|
||||
if (flag_checking)
|
||||
{
|
||||
for (unsigned i = 0; i < dst_len; i++)
|
||||
{
|
||||
ipa_param_performed_split *ps1
|
||||
= &(*node->clone.performed_splits)[i];
|
||||
= &(*info->performed_splits)[i];
|
||||
for (unsigned j = i + 1; j < dst_len; j++)
|
||||
{
|
||||
ipa_param_performed_split *ps2
|
||||
= &(*node->clone.performed_splits)[j];
|
||||
= &(*info->performed_splits)[j];
|
||||
gcc_assert (ps1->dummy_decl != ps2->dummy_decl
|
||||
|| ps1->unit_offset != ps2->unit_offset);
|
||||
}
|
||||
@ -6270,8 +6278,9 @@ tree_function_versioning (tree old_decl, tree new_decl,
|
||||
= copy_static_chain (p, &id);
|
||||
|
||||
auto_vec<int, 16> new_param_indices;
|
||||
clone_info *info = clone_info::get (old_version_node);
|
||||
ipa_param_adjustments *old_param_adjustments
|
||||
= old_version_node->clone.param_adjustments;
|
||||
= info ? info->param_adjustments : NULL;
|
||||
if (old_param_adjustments)
|
||||
old_param_adjustments->get_updated_indices (&new_param_indices);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user