Add sanity checking for profile counter compatibility

Message ID 20191128173210.pyatmml4ysbilcf5@kam.mff.cuni.cz
State New
Headers show
Series
  • Add sanity checking for profile counter compatibility
Related show

Commit Message

Jan Hubicka Nov. 28, 2019, 5:32 p.m.
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.

Patch

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