aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ipa-prop.cc188
1 files changed, 111 insertions, 77 deletions
diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc
index cbc8256..9070a45 100644
--- a/gcc/ipa-prop.cc
+++ b/gcc/ipa-prop.cc
@@ -4503,99 +4503,96 @@ ipa_edge_args_sum_t::remove (cgraph_edge *cs, ipa_edge_args *args)
}
}
-/* Method invoked when an edge is duplicated. Copy ipa_edge_args and adjust
- reference count data strucutres accordingly. */
+/* Copy information from SRC_JF to DST_JF which correstpond to call graph edges
+ SRC and DST. */
-void
-ipa_edge_args_sum_t::duplicate (cgraph_edge *src, cgraph_edge *dst,
- ipa_edge_args *old_args, ipa_edge_args *new_args)
+static void
+ipa_duplicate_jump_function (cgraph_edge *src, cgraph_edge *dst,
+ ipa_jump_func *src_jf, ipa_jump_func *dst_jf)
{
- unsigned int i;
+ dst_jf->agg.items = vec_safe_copy (src_jf->agg.items);
+ dst_jf->agg.by_ref = src_jf->agg.by_ref;
- new_args->jump_functions = vec_safe_copy (old_args->jump_functions);
- if (old_args->polymorphic_call_contexts)
- new_args->polymorphic_call_contexts
- = vec_safe_copy (old_args->polymorphic_call_contexts);
+ /* We can avoid calling ipa_set_jfunc_vr since it would only look up the
+ place in the hash_table where the source m_vr resides. */
+ dst_jf->m_vr = src_jf->m_vr;
- for (i = 0; i < vec_safe_length (old_args->jump_functions); i++)
+ if (src_jf->type == IPA_JF_CONST)
{
- struct ipa_jump_func *src_jf = ipa_get_ith_jump_func (old_args, i);
- struct ipa_jump_func *dst_jf = ipa_get_ith_jump_func (new_args, i);
-
- dst_jf->agg.items = vec_safe_copy (dst_jf->agg.items);
+ ipa_set_jf_cst_copy (dst_jf, src_jf);
+ struct ipa_cst_ref_desc *src_rdesc = jfunc_rdesc_usable (src_jf);
- if (src_jf->type == IPA_JF_CONST)
+ if (!src_rdesc)
+ dst_jf->value.constant.rdesc = NULL;
+ else if (src->caller == dst->caller)
{
- struct ipa_cst_ref_desc *src_rdesc = jfunc_rdesc_usable (src_jf);
-
- if (!src_rdesc)
- dst_jf->value.constant.rdesc = NULL;
- else if (src->caller == dst->caller)
- {
- /* Creation of a speculative edge. If the source edge is the one
- grabbing a reference, we must create a new (duplicate)
- reference description. Otherwise they refer to the same
- description corresponding to a reference taken in a function
- src->caller is inlined to. In that case we just must
- increment the refcount. */
- if (src_rdesc->cs == src)
- {
- symtab_node *n = symtab_node_for_jfunc (src_jf);
- gcc_checking_assert (n);
- ipa_ref *ref
- = src->caller->find_reference (n, src->call_stmt,
- src->lto_stmt_uid,
- IPA_REF_ADDR);
- gcc_checking_assert (ref);
- dst->caller->clone_reference (ref, ref->stmt);
-
- ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate ();
- dst_rdesc->cs = dst;
- dst_rdesc->refcount = src_rdesc->refcount;
- dst_rdesc->next_duplicate = NULL;
- dst_jf->value.constant.rdesc = dst_rdesc;
- }
- else
- {
- src_rdesc->refcount++;
- dst_jf->value.constant.rdesc = src_rdesc;
- }
- }
- else if (src_rdesc->cs == src)
+ /* Creation of a speculative edge. If the source edge is the one
+ grabbing a reference, we must create a new (duplicate)
+ reference description. Otherwise they refer to the same
+ description corresponding to a reference taken in a function
+ src->caller is inlined to. In that case we just must
+ increment the refcount. */
+ if (src_rdesc->cs == src)
{
- struct ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate ();
+ symtab_node *n = symtab_node_for_jfunc (src_jf);
+ gcc_checking_assert (n);
+ ipa_ref *ref
+ = src->caller->find_reference (n, src->call_stmt,
+ src->lto_stmt_uid,
+ IPA_REF_ADDR);
+ gcc_checking_assert (ref);
+ dst->caller->clone_reference (ref, ref->stmt);
+
+ ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate ();
dst_rdesc->cs = dst;
dst_rdesc->refcount = src_rdesc->refcount;
- dst_rdesc->next_duplicate = src_rdesc->next_duplicate;
- src_rdesc->next_duplicate = dst_rdesc;
+ dst_rdesc->next_duplicate = NULL;
dst_jf->value.constant.rdesc = dst_rdesc;
}
else
{
- struct ipa_cst_ref_desc *dst_rdesc;
- /* This can happen during inlining, when a JFUNC can refer to a
- reference taken in a function up in the tree of inline clones.
- We need to find the duplicate that refers to our tree of
- inline clones. */
-
- gcc_assert (dst->caller->inlined_to);
- for (dst_rdesc = src_rdesc->next_duplicate;
- dst_rdesc;
- dst_rdesc = dst_rdesc->next_duplicate)
- {
- struct cgraph_node *top;
- top = dst_rdesc->cs->caller->inlined_to
- ? dst_rdesc->cs->caller->inlined_to
- : dst_rdesc->cs->caller;
- if (dst->caller->inlined_to == top)
- break;
- }
- gcc_assert (dst_rdesc);
- dst_jf->value.constant.rdesc = dst_rdesc;
+ src_rdesc->refcount++;
+ dst_jf->value.constant.rdesc = src_rdesc;
+ }
+ }
+ else if (src_rdesc->cs == src)
+ {
+ struct ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate ();
+ dst_rdesc->cs = dst;
+ dst_rdesc->refcount = src_rdesc->refcount;
+ dst_rdesc->next_duplicate = src_rdesc->next_duplicate;
+ src_rdesc->next_duplicate = dst_rdesc;
+ dst_jf->value.constant.rdesc = dst_rdesc;
+ }
+ else
+ {
+ struct ipa_cst_ref_desc *dst_rdesc;
+ /* This can happen during inlining, when a JFUNC can refer to a
+ reference taken in a function up in the tree of inline clones.
+ We need to find the duplicate that refers to our tree of
+ inline clones. */
+
+ gcc_assert (dst->caller->inlined_to);
+ for (dst_rdesc = src_rdesc->next_duplicate;
+ dst_rdesc;
+ dst_rdesc = dst_rdesc->next_duplicate)
+ {
+ struct cgraph_node *top;
+ top = dst_rdesc->cs->caller->inlined_to
+ ? dst_rdesc->cs->caller->inlined_to
+ : dst_rdesc->cs->caller;
+ if (dst->caller->inlined_to == top)
+ break;
}
+ gcc_assert (dst_rdesc);
+ dst_jf->value.constant.rdesc = dst_rdesc;
}
- else if (dst_jf->type == IPA_JF_PASS_THROUGH
- && src->caller == dst->caller)
+ }
+ else if (src_jf->type == IPA_JF_PASS_THROUGH)
+ {
+ dst_jf->type = IPA_JF_PASS_THROUGH;
+ dst_jf->value.pass_through = src_jf->value.pass_through;
+ if (src->caller == dst->caller)
{
struct cgraph_node *inline_root = dst->caller->inlined_to
? dst->caller->inlined_to : dst->caller;
@@ -4610,6 +4607,43 @@ ipa_edge_args_sum_t::duplicate (cgraph_edge *src, cgraph_edge *dst,
}
}
}
+ else if (src_jf->type == IPA_JF_ANCESTOR)
+ {
+ dst_jf->type = IPA_JF_ANCESTOR;
+ dst_jf->value.ancestor = src_jf->value.ancestor;
+ }
+ else
+ gcc_assert (src_jf->type == IPA_JF_UNKNOWN);
+}
+
+/* Method invoked when an edge is duplicated. Copy ipa_edge_args and adjust
+ reference count data strucutres accordingly. */
+
+void
+ipa_edge_args_sum_t::duplicate (cgraph_edge *src, cgraph_edge *dst,
+ ipa_edge_args *old_args, ipa_edge_args *new_args)
+{
+ unsigned int i;
+
+ if (old_args->polymorphic_call_contexts)
+ new_args->polymorphic_call_contexts
+ = vec_safe_copy (old_args->polymorphic_call_contexts);
+
+ if (!vec_safe_length (old_args->jump_functions))
+ {
+ new_args->jump_functions = NULL;
+ return;
+ }
+ vec_safe_grow_cleared (new_args->jump_functions,
+ old_args->jump_functions->length (), true);
+
+ for (i = 0; i < vec_safe_length (old_args->jump_functions); i++)
+ {
+ struct ipa_jump_func *src_jf = ipa_get_ith_jump_func (old_args, i);
+ struct ipa_jump_func *dst_jf = ipa_get_ith_jump_func (new_args, i);
+
+ ipa_duplicate_jump_function (src, dst, src_jf, dst_jf);
+ }
}
/* Analyze newly added function into callgraph. */