Hi, the testcase triggers yet another case where we do not update profile type correctly when inter-proceduraly inlining because of 0 in the entry_block_ptr count.
Bootstrapped/regtested x86_64-linux, will commit it shortly. Honza * ipa-inline-transform.c (update_noncloned_frequencies): Use profile_count::adjust_for_ipa_scaling. * tree-inline.c (copy_bb, copy_cfg_body): Likewise. * profile-count.c (profile_count::adjust_for_ipa_scaling): New member function. * profile-count.h (profile_count::adjust_for_ipa_scaling): Declare. * gcc.c-torture/compile/pr82879.c: New testcase. Index: ipa-inline-transform.c =================================================================== --- ipa-inline-transform.c (revision 254567) +++ ipa-inline-transform.c (working copy) @@ -60,17 +60,7 @@ update_noncloned_frequencies (struct cgr { struct cgraph_edge *e; - /* We always must scale to be sure counters end up compatible. - If den is zero, just force it nonzero and hope for reasonable - approximation. - When num is forced nonzero, also update den, so we do not scale profile - to 0. */ - if (!(num == den) - && !(den.force_nonzero () == den)) - { - den = den.force_nonzero (); - num = num.force_nonzero (); - } + profile_count::adjust_for_ipa_scaling (&num, &den); /* We do not want to ignore high loop nest after freq drops to 0. */ if (!freq_scale) Index: profile-count.c =================================================================== --- profile-count.c (revision 254567) +++ profile-count.c (working copy) @@ -255,3 +255,29 @@ profile_count::to_cgraph_frequency (prof return CGRAPH_FREQ_MAX; return MIN (scale, CGRAPH_FREQ_MAX); } + +/* We want to scale profile across function boundary from NUM to DEN. + Take care of the side case when DEN is zeros. We still want to behave + sanely here which means + - scale to profile_count::zero () if NUM is profile_count::zero + - do not affect anything if NUM == DEN + - preserve counter value but adjust quality in other cases. */ + +void +profile_count::adjust_for_ipa_scaling (profile_count *num, + profile_count *den) +{ + /* Scaling is no-op if NUM and DEN are the same. */ + if (*num == *den) + return; + /* Scaling to zero is always zeor. */ + if (*num == profile_count::zero ()) + return; + /* If den is non-zero we are safe. */ + if (den->force_nonzero () == *den) + return; + /* Force both to non-zero so we do not push profiles to 0 when + both num == 0 and den == 0. */ + *den = den->force_nonzero (); + *num = num->force_nonzero (); +} Index: profile-count.h =================================================================== --- profile-count.h (revision 254567) +++ profile-count.h (working copy) @@ -1044,6 +1044,11 @@ public: /* Return true if THIS is known to differ significantly from OTHER. */ bool differs_from_p (profile_count other) const; + /* We want to scale profile across function boundary from NUM to DEN. + Take care of the side case when NUM and DEN are zeros of incompatible + kinds. */ + static void adjust_for_ipa_scaling (profile_count *num, profile_count *den); + /* LTO streaming support. */ static profile_count stream_in (struct lto_input_block *); void stream_out (struct output_block *); Index: testsuite/gcc.c-torture/compile/pr82879.c =================================================================== --- testsuite/gcc.c-torture/compile/pr82879.c (revision 0) +++ testsuite/gcc.c-torture/compile/pr82879.c (working copy) @@ -0,0 +1,11 @@ +int a, b; +static __attribute__((cold)) void fn1() { + for (;;) + for (; a;) + ; +} +void fn2() { + if (b) + fn1(); +} + Index: tree-inline.c =================================================================== --- tree-inline.c (revision 254567) +++ tree-inline.c (working copy) @@ -1771,17 +1771,7 @@ copy_bb (copy_body_data *id, basic_block tree decl; basic_block prev; - /* We always must scale to be sure counters end up compatible. - If den is zero, just force it nonzero and hope for reasonable - approximation. - When num is forced nonzero, also update den, so we do not scale profile - to 0. */ - if (!(num == den) - && !(den.force_nonzero () == den)) - { - den = den.force_nonzero (); - num = num.force_nonzero (); - } + profile_count::adjust_for_ipa_scaling (&num, &den); /* Search for previous copied basic block. */ prev = bb->prev_bb; @@ -2698,17 +2688,7 @@ copy_cfg_body (copy_body_data * id, prof profile_count den = ENTRY_BLOCK_PTR_FOR_FN (src_cfun)->count; profile_count num = entry_block_map->count; - /* We always must scale to be sure counters end up compatible. - If den is zero, just force it nonzero and hope for reasonable - approximation. - When num is forced nonzero, also update den, so we do not scale profile - to 0. */ - if (!(num == den) - && !(den.force_nonzero () == den)) - { - den = den.force_nonzero (); - num = num.force_nonzero (); - } + profile_count::adjust_for_ipa_scaling (&num, &den); cfun_to_copy = id->src_cfun = DECL_STRUCT_FUNCTION (callee_fndecl);