diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ipa-prop.cc | 188 |
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. */ |