Fix ICE on overflow of profile-count

Message ID 20171208112914.GG78650@kam.mff.cuni.cz
State New
Headers show
Series
  • Fix ICE on overflow of profile-count
Related show

Commit Message

Jan Hubicka Dec. 8, 2017, 11:29 a.m.
Hi,
the testcase triggers ICE because loop iterates too many times.  We used to
work around by capping all counts to 10000 but that leads to many problems
during IPA profile propagation (because there is no way to determine
frequency of call given frequency of entry when entry frequency is 0).

This patch adds capping.  It seems very rare case and profile is either
already wrong or the program would run just too long to finish.

Bootstrapped/regtested x86_64-linux, comitted.

Honza

	* profile-count.c (profile_count::from_gcov_type): Move from
	profile-count.h; handle overflow.
	* profile-count. (profile_count::from_gcov_type): Move offline.

	PR middle-end/83609
	* gcc.c-torture/compile/pr83069.c: New testcase.

Patch

Index: profile-count.c
===================================================================
--- profile-count.c	(revision 255466)
+++ profile-count.c	(working copy)
@@ -327,3 +327,21 @@  profile_count::combine_with_ipa_count (p
     return this->global0 ();
   return this->global0adjusted ();
 }
+
+/* The profiling runtime uses gcov_type, which is usually 64bit integer.
+   Conversions back and forth are used to read the coverage and get it
+   into internal representation.  */
+profile_count
+profile_count::from_gcov_type (gcov_type v)
+  {
+    profile_count ret;
+    gcc_checking_assert (v >= 0);
+    if (dump_file && v >= (gcov_type)max_count)
+      fprintf (dump_file,
+	       "Capping gcov count %" PRId64 " to max_count %" PRId64 "\n",
+	       (int64_t) v, (int64_t) max_count);
+    ret.m_val = MIN (v, (gcov_type)max_count);
+    ret.m_quality = profile_precise;
+    return ret;
+  }
+
Index: profile-count.h
===================================================================
--- profile-count.h	(revision 255466)
+++ profile-count.h	(working copy)
@@ -667,18 +667,6 @@  public:
       return c;
     }
 
-  /* The profiling runtime uses gcov_type, which is usually 64bit integer.
-     Conversions back and forth are used to read the coverage and get it
-     into internal representation.  */
-  static profile_count from_gcov_type (gcov_type v)
-    {
-      profile_count ret;
-      gcc_checking_assert (v >= 0 && (uint64_t) v <= max_count);
-      ret.m_val = v;
-      ret.m_quality = profile_precise;
-      return ret;
-    }
-
   /* Conversion to gcov_type is lossy.  */
   gcov_type to_gcov_type () const
     {
@@ -1083,6 +1071,11 @@  public:
      global0.  */
   profile_count combine_with_ipa_count (profile_count ipa);
 
+  /* The profiling runtime uses gcov_type, which is usually 64bit integer.
+     Conversions back and forth are used to read the coverage and get it
+     into internal representation.  */
+  static profile_count from_gcov_type (gcov_type v);
+
   /* LTO streaming support.  */
   static profile_count stream_in (struct lto_input_block *);
   void stream_out (struct output_block *);
Index: testsuite/gcc.c-torture/compile/pr83069.c
===================================================================
--- testsuite/gcc.c-torture/compile/pr83069.c	(revision 0)
+++ testsuite/gcc.c-torture/compile/pr83069.c	(working copy)
@@ -0,0 +1,14 @@ 
+#define MAX 98
+
+void foo (unsigned long *res, unsigned long in)
+{
+  for (unsigned long a = 0; a < MAX; a++)
+    for (unsigned long b = 0; b < MAX; b++)
+      for (unsigned long c = 0; c < MAX; c++)
+        for (unsigned long d = 0; d < MAX; d++)
+          for (unsigned long e = 0; e < MAX; e++)
+            for (unsigned long f = 0; f < MAX; f++)
+              for (unsigned long g = 0; g < MAX; g++)
+                *res += a * in;
+}
+