> Hello Josef, > > On Tue, Nov 05 2024, Josef Melcr wrote: > > Hi! > > > > On 11/5/24 12:06, Martin Jambor wrote: > >> +/* Copy information from SRC_JF to DST_JF which correstpond to call graph > >> edges > >> + SRC and DST. */ > >> + > >> +static void > >> +ipa_duplicate_jump_function (cgraph_edge *src, cgraph_edge *dst, > >> + ipa_jump_func *src_jf, ipa_jump_func *dst_jf) > > > > I am not sure this function copies over all necessary information, e.g. > > jump function type. It will work fine when used in the duplication hook, > > as the dst jump functions are created through > > > > new_args->jump_functions = vec_safe_copy (old_args->jump_functions); > > > > so all other information is copied over, but I don't think that's the > > case when using this function on its own. When a jump function is > > constructed through different means, will the contents of the jump > > functions still match ? > > Thanks for reading through the patch. I am happy that I was wrong when > reviewing the current situation rather then when writing the original > code. Though of course mainly I need to pay more attention to details. > > We still want to have the split for the purposes of propagating stuff to > OpenMP outlined regions, and for that I have prepared the patch below. > I am just not sure whether it makes sense to push this now or wait for > stage1 of GCC 16. The patch does pass bootstrap and testing on > x86_64-linux. > > Honza, any preferences? (Independently of whether it is OK to be > pushed.)
I think it is fine to commit it now. It makes it easier to maintain the branch. Patch is OK. Honza > > Thanks, > > Martin > > ---------- 8< -------------------- 8< -------------------- 8< ---------- > > When reviewing various IPA bits and pieces I have falsely assumed > that jump function duplication misses copying important bits because > it relies on vec_safe_copy-ing all data in the vector of jump > functions and then just fixes up the few fields it needs to. > > Perhaps more importantly, we do want a function to copy one individual > jump function to form jump functions for planned call-graph edges that > model transfer of control to OpenMP outlined regions through calls to > gomp functions. > > Therefore, this patch introduces such function and makes > ipa_edge_args_sum_t::duplicate just allocate the new vectors and then > uses the new function to copy the data. > > gcc/ChangeLog: > > 2024-11-12 Martin Jambor <mjam...@suse.cz> > > * ipa-prop.cc (ipa_duplicate_jump_function): New function. > (ipa_edge_args_sum_t::duplicate): Move individual jump function > copying to ipa_duplicate_jump_function. > --- > gcc/ipa-prop.cc | 186 ++++++++++++++++++++++++++++-------------------- > 1 file changed, 110 insertions(+), 76 deletions(-) > > diff --git a/gcc/ipa-prop.cc b/gcc/ipa-prop.cc > index 599181d0a94..e1c4c798f3f 100644 > --- a/gcc/ipa-prop.cc > +++ b/gcc/ipa-prop.cc > @@ -4497,99 +4497,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); > + ipa_set_jf_cst_copy (dst_jf, src_jf); > + struct ipa_cst_ref_desc *src_rdesc = jfunc_rdesc_usable (src_jf); > > - dst_jf->agg.items = vec_safe_copy (dst_jf->agg.items); > - > - 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) > { > - /* 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); > + 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) > - { > - struct ipa_cst_ref_desc *dst_rdesc = ipa_refdesc_pool.allocate (); > + 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 (dst_jf->type == IPA_JF_PASS_THROUGH > - && src->caller == dst->caller) > + 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 (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; > @@ -4604,6 +4601,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. */ > -- > 2.47.0 > >