Hi,
this ICE is caused by double updating in ipa-prop that reduces call stmt size
once when it becomes speculative and again when it is turned to direct.  Fixed
by the following patch that makes updating to happen while duplication so
ipa-prop needs to care only about case it turned real indirect call into
direct.

Bootstrapped/regtested x86_64-linux, will commit it shortly.

Honza

        PR ipa/63470
        * ipa-inline-analysis.c (inline_edge_duplication_hook): Adjust
        cost when edge becomes direct.
        * ipa-prop.c (make_edge_direct): Do not adjust when speculation
        is resolved or when introducing new speculation.

        * testsuite/g++.dg/ipa/pr63470.C: New testcase.

Index: ipa-inline-analysis.c
===================================================================
--- ipa-inline-analysis.c       (revision 219430)
+++ ipa-inline-analysis.c       (working copy)
@@ -1312,6 +1312,13 @@
   info->predicate = NULL;
   edge_set_predicate (dst, srcinfo->predicate);
   info->param = srcinfo->param.copy ();
+  if (!dst->indirect_unknown_callee && src->indirect_unknown_callee)
+    {
+      info->call_stmt_size -= (eni_size_weights.indirect_call_cost
+                              - eni_size_weights.call_cost);
+      info->call_stmt_time -= (eni_time_weights.indirect_call_cost
+                              - eni_time_weights.call_cost);
+    }
 }
 
 
Index: ipa-prop.c
===================================================================
--- ipa-prop.c  (revision 219430)
+++ ipa-prop.c  (working copy)
@@ -2737,7 +2737,20 @@
                       ie->caller->name (), callee->name ());
     }
   if (!speculative)
-    ie = ie->make_direct (callee);
+    {
+      struct cgraph_edge *orig = ie;
+      ie = ie->make_direct (callee);
+      /* If we resolved speculative edge the cost is already up to date
+        for direct call (adjusted by inline_edge_duplication_hook).  */
+      if (ie == orig)
+       {
+         es = inline_edge_summary (ie);
+         es->call_stmt_size -= (eni_size_weights.indirect_call_cost
+                                - eni_size_weights.call_cost);
+         es->call_stmt_time -= (eni_time_weights.indirect_call_cost
+                                - eni_time_weights.call_cost);
+       }
+    }
   else
     {
       if (!callee->can_be_discarded_p ())
@@ -2747,14 +2760,10 @@
          if (alias)
            callee = alias;
        }
+      /* make_speculative will update ie's cost to direct call cost. */
       ie = ie->make_speculative
             (callee, ie->count * 8 / 10, ie->frequency * 8 / 10);
     }
-  es = inline_edge_summary (ie);
-  es->call_stmt_size -= (eni_size_weights.indirect_call_cost
-                        - eni_size_weights.call_cost);
-  es->call_stmt_time -= (eni_time_weights.indirect_call_cost
-                        - eni_time_weights.call_cost);
 
   return ie;
 }
Index: testsuite/g++.dg/ipa/pr63470.C
===================================================================
--- testsuite/g++.dg/ipa/pr63470.C      (revision 0)
+++ testsuite/g++.dg/ipa/pr63470.C      (revision 0)
@@ -0,0 +1,54 @@
+/* PR ipa/63470.C */
+/* { dg-do compile } */
+/* { dg-options "-O2 -finline-functions" } */
+
+class A
+{
+public:
+  virtual bool m_fn1 ();
+  virtual const char **m_fn2 (int);
+  virtual int m_fn3 ();
+};
+class FTjackSupport : A
+{
+  ~FTjackSupport ();
+  bool m_fn1 ();
+  bool m_fn4 ();
+  const char **
+  m_fn2 (int)
+  {
+  }
+  int _inited;
+  int *_jackClient;
+  int _activePathCount;
+}
+
+* a;
+void fn1 (...);
+void fn2 (void *);
+int fn3 (int *);
+FTjackSupport::~FTjackSupport () { m_fn4 (); }
+
+bool
+FTjackSupport::m_fn1 ()
+{
+  if (!_jackClient)
+    return 0;
+  for (int i=0; _activePathCount; ++i)
+    if (m_fn2 (i))
+      fn2 (a);
+  if (m_fn3 ())
+    fn2 (a);
+  if (fn3 (_jackClient))
+    fn1 (0);
+}
+
+bool
+FTjackSupport::m_fn4 ()
+{
+  if (_inited && _jackClient)
+    {
+      m_fn1 ();
+      return 0;
+    }
+}

Reply via email to