]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR middle-end/58555 (Floating point exception in want_inline_self_recursive_call_p)
authorJan Hubicka <hubicka@ucw.cz>
Thu, 20 Feb 2014 06:40:07 +0000 (07:40 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Thu, 20 Feb 2014 06:40:07 +0000 (06:40 +0000)
PR ipa/58555
* ipa-inline-transform.c (clone_inlined_nodes): Add freq_scale parameter
specifying the scaling.
(inline_call): Update.
(want_inline_recursively): Guard division by zero.
(recursive_inlining): Update.
* ipa-inline.h (clone_inlined_nodes): Update.
* testsuite/g++.dg/torture/pr58555.C: New testcase.

From-SVN: r207934

gcc/ChangeLog
gcc/ipa-inline-transform.c
gcc/ipa-inline.c
gcc/ipa-inline.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr58555.C [new file with mode: 0644]

index a401d853ed82df6888fb3e6cd4cd736f3a07d1f2..24d8e18084bd5c4fa478434f45dfd6c0922710a2 100644 (file)
@@ -1,3 +1,13 @@
+2014-02-20  Jan Hubicka  <hubicka@ucw.cz>
+
+       PR ipa/58555
+       * ipa-inline-transform.c (clone_inlined_nodes): Add freq_scale parameter
+       specifying the scaling.
+       (inline_call): Update.
+       (want_inline_recursively): Guard division by zero.
+       (recursive_inlining): Update.
+       * ipa-inline.h (clone_inlined_nodes): Update.
+
 2014-02-20  Ilya Tocar  <ilya.tocar@intel.com>
 
        PR target/60204
index a24f68db38ed0a521c438ca9dbcbab189362ef8a..b2e0285462c17a58eea7694a4d82f621ad57c216 100644 (file)
@@ -127,11 +127,15 @@ can_remove_node_now_p (struct cgraph_node *node, struct cgraph_edge *e)
    the edge and redirect it to the new clone.
    DUPLICATE is used for bookkeeping on whether we are actually creating new
    clones or re-using node originally representing out-of-line function call.
-   */
+   By default the offline copy is removed, when it appears dead after inlining.
+   UPDATE_ORIGINAL prevents this transformation.
+   If OVERALL_SIZE is non-NULL, the size is updated to reflect the
+   transformation.
+   FREQ_SCALE specify the scaling of frequencies of call sites.  */
 
 void
 clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
-                    bool update_original, int *overall_size)
+                    bool update_original, int *overall_size, int freq_scale)
 {
   struct cgraph_node *inlining_into;
   struct cgraph_edge *next;
@@ -175,8 +179,11 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
       else
        {
          struct cgraph_node *n;
+
+         if (freq_scale == -1)
+           freq_scale = e->frequency;
          n = cgraph_clone_node (e->callee, e->callee->decl,
-                                e->count, e->frequency, update_original,
+                                e->count, freq_scale, update_original,
                                 vNULL, true, inlining_into);
          cgraph_redirect_edge_callee (e, n);
        }
@@ -191,7 +198,7 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
     {
       next = e->next_callee;
       if (!e->inline_failed)
-        clone_inlined_nodes (e, duplicate, update_original, overall_size);
+        clone_inlined_nodes (e, duplicate, update_original, overall_size, freq_scale);
       if (e->speculative && !speculation_useful_p (e, true))
        {
          cgraph_resolve_speculation (e, NULL);
@@ -260,7 +267,7 @@ inline_call (struct cgraph_edge *e, bool update_original,
        }
     }
 
-  clone_inlined_nodes (e, true, update_original, overall_size);
+  clone_inlined_nodes (e, true, update_original, overall_size, e->frequency);
 
   gcc_assert (curr->callee->global.inlined_to == to);
 
index d304133bfe4745084238b1bc4cd9ab449a3d3a96..f6f97f87ebe417af459a45778bc65688926280d5 100644 (file)
@@ -708,6 +708,12 @@ want_inline_self_recursive_call_p (struct cgraph_edge *edge,
   if (outer_node->global.inlined_to)
     caller_freq = outer_node->callers->frequency;
 
+  if (!caller_freq)
+    {
+      reason = "function is inlined and unlikely";
+      want_inline = false;
+    }
+
   if (!want_inline)
     ;
   /* Inlining of self recursive function into copy of itself within other function
@@ -1385,7 +1391,7 @@ recursive_inlining (struct cgraph_edge *edge,
                                            false, vNULL, true, NULL);
          for (e = master_clone->callees; e; e = e->next_callee)
            if (!e->inline_failed)
-             clone_inlined_nodes (e, true, false, NULL);
+             clone_inlined_nodes (e, true, false, NULL, CGRAPH_FREQ_BASE);
           cgraph_redirect_edge_callee (curr, master_clone);
           reset_edge_growth_cache (curr);
        }
index 618189b9b5fc38f83ce6c43625e56f1bfe77848e..0a5960899a3fb5a147dae8702dfddb9854ef305f 100644 (file)
@@ -233,7 +233,8 @@ bool speculation_useful_p (struct cgraph_edge *e, bool anticipate_inlining);
 /* In ipa-inline-transform.c  */
 bool inline_call (struct cgraph_edge *, bool, vec<cgraph_edge_p> *, int *, bool);
 unsigned int inline_transform (struct cgraph_node *);
-void clone_inlined_nodes (struct cgraph_edge *e, bool, bool, int *);
+void clone_inlined_nodes (struct cgraph_edge *e, bool, bool, int *,
+                         int freq_scale);
 
 extern int ncalls_inlined;
 extern int nfunctions_inlined;
index 46ef4dc32cbad9a055496d64df42ae99e73fc0f2..0b8de7804b7b680ffebee90fdae52de0098d8143 100644 (file)
@@ -1,3 +1,8 @@
+2014-02-20  Jan Hubicka  <hubicka@ucw.cz>
+
+       PR ipa/58555
+       * testsuite/g++.dg/torture/pr58555.C: New testcase.
+
 2014-02-20  Ilya Tocar  <ilya.tocar@intel.com>
 
        PR target/60204
diff --git a/gcc/testsuite/g++.dg/torture/pr58555.C b/gcc/testsuite/g++.dg/torture/pr58555.C
new file mode 100644 (file)
index 0000000..ac5009a
--- /dev/null
@@ -0,0 +1,114 @@
+/* { dg-do compile } */
+template <typename _Tp> _Tp *__addressof(_Tp &) {}
+template <typename _Tp> class A {
+public:
+  typedef _Tp *pointer;
+};
+template <typename _Tp> class M : public A<_Tp> {
+public:
+  typedef M other;
+  ~M();
+};
+class B {
+public:
+  B(int *);
+};
+class C {
+public:
+  void GetNext();
+  C *GetChildren();
+};
+template <typename _Tp> void _Destroy(_Tp *p1) { p1->~_Tp(); }
+struct D {
+  template <typename _ForwardIterator>
+  static void __destroy(_ForwardIterator p1, _ForwardIterator p2) {
+    for (; p1 != p2; ++p1)
+      _Destroy(__addressof(*p1));
+  }
+};
+template <typename _ForwardIterator>
+void _Destroy(_ForwardIterator p1, _ForwardIterator p2) {
+  D::__destroy(p1, p2);
+}
+template <typename _ForwardIterator, typename _Tp>
+void _Destroy(_ForwardIterator p1, _ForwardIterator p2, M<_Tp> &) {
+  _Destroy(p1, p2);
+}
+template <typename _Alloc> struct F {
+  typedef _Alloc _Tp_alloc_type;
+  typedef typename _Tp_alloc_type::pointer pointer;
+  struct N : _Tp_alloc_type {
+    pointer _M_start;
+    pointer _M_finish;
+  };
+  _Tp_alloc_type &_M_get_Tp_allocator();
+  N _M_impl;
+};
+template <typename _Tp, typename _Alloc = M<_Tp> > class O : F<_Alloc> {
+using  F<_Alloc>::_M_get_Tp_allocator;
+public:
+  ~O() {
+    _Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
+             _M_get_Tp_allocator());
+  }
+};
+template <class T> void checked_delete(T *p1) { delete p1; }
+template <class> class I;
+template <class T> struct J {
+  typedef T *type;
+};
+class K;
+class L {
+public:
+  virtual ~L();
+};
+class P : L {
+  O<I<int> > databasesM;
+  O<I<K> > usersM;
+public:
+  I<int> addDatabase();
+};
+C a;
+C *b;
+int atomic_exchange_and_add();
+class G {
+public:
+  virtual void dispose() = 0;
+  void release() {
+    if (atomic_exchange_and_add() == 1)
+      dispose();
+  }
+};
+class Q : G {
+  P *px_;
+  Q() {}
+  void dispose() { checked_delete(px_); }
+};
+class H {
+  G *pi_;
+public:
+  H();
+  H(P *);
+  ~H() {
+    if (pi_)
+      pi_->release();
+  }
+};
+template <class T, class Y> void sp_pointer_construct(I<T> *, Y, H);
+template <class T> class I {
+public:
+  typedef T element_type;
+  template <class Y> I(Y *p1) { sp_pointer_construct(this, 0, 0); }
+  typename J<T>::type operator->();
+  H pn;
+};
+void getNodeContent(const B &) {
+  for (C *n = a.GetChildren(); n; n->GetNext())
+    ;
+}
+void parseDatabase(I<P> p1) {
+  I<int> c = p1->addDatabase();
+  for (; b;)
+    getNodeContent(0);
+}
+void addServer() { I<int>(new P); }