Hi, this patch adds sanity checks with uncovered all the latent bugs I fixed today. I will add similar checking to cfg profile, too, and also few unit tests.
Bootstrapped/regtested x86_64-linux, plan to commit it shortly. * profile-count.c (profile_count::to_cgraph_frequency, profile_count::to_sreal_scale): Check for compaibility of counts. * profile-count.h (compatible_p): Make public; add checking for global0 versus global types. * cgraph.c (cgraph_node::verify_node): Verify count compatibility. Index: profile-count.c =================================================================== --- profile-count.c (revision 278814) +++ profile-count.c (working copy) @@ -291,6 +292,7 @@ profile_count::to_cgraph_frequency (prof return 0; gcc_checking_assert (entry_bb_count.initialized_p ()); uint64_t scale; + gcc_checking_assert (compatible_p (entry_bb_count)); if (!safe_scale_64bit (!entry_bb_count.m_val ? m_val + 1 : m_val, CGRAPH_FREQ_BASE, MAX (1, entry_bb_count.m_val), &scale)) return CGRAPH_FREQ_MAX; @@ -328,6 +330,7 @@ profile_count::to_sreal_scale (profile_c return 0; if (m_val == in.m_val) return 1; + gcc_checking_assert (compatible_p (in)); if (!in.m_val) { Index: profile-count.h =================================================================== --- profile-count.h (revision 278814) +++ profile-count.h (working copy) @@ -700,6 +700,7 @@ private: uint64_t UINT64_BIT_FIELD_ALIGN m_val : n_bits; #undef UINT64_BIT_FIELD_ALIGN enum profile_quality m_quality : 3; +public: /* Return true if both values can meaningfully appear in single function body. We have either all counters in function local or global, otherwise @@ -711,9 +712,18 @@ private: if (*this == zero () || other == zero ()) return true; + /* Do not allow nonzero global profile together with local guesses + that are globally0. */ + if (ipa ().nonzero_p () + && !(other.ipa () == other)) + return false; + if (other.ipa ().nonzero_p () + && !(ipa () == *this)) + return false; + return ipa_p () == other.ipa_p (); } -public: + /* Used for counters which are expected to be never executed. */ static profile_count zero () { Index: cgraph.c =================================================================== --- cgraph.c (revision 278814) +++ cgraph.c (working copy) @@ -3061,6 +3061,13 @@ cgraph_node::verify_node (void) error ("inline clone in same comdat group list"); error_found = true; } + if (inlined_to && !count.compatible_p (inlined_to->count)) + { + error ("inline clone count is not compatible"); + count.debug (); + inlined_to->count.debug (); + error_found = true; + } if (!definition && !in_other_partition && local) { error ("local symbols must be defined"); @@ -3089,6 +3096,13 @@ cgraph_node::verify_node (void) identifier_to_locale (e->caller->name ())); error_found = true; } + if (!e->count.compatible_p (count)) + { + error ("edge count is not compatible with function count"); + e->count.debug (); + count.debug (); + error_found = true; + } if (!e->indirect_unknown_callee || !e->indirect_info) { @@ -3137,6 +3151,13 @@ cgraph_node::verify_node (void) { if (e->verify_count ()) error_found = true; + if (!e->count.compatible_p (count)) + { + error ("edge count is not compatible with function count"); + e->count.debug (); + count.debug (); + error_found = true; + } if (gimple_has_body_p (e->caller->decl) && !e->caller->inlined_to && !e->speculative