diff options
author | Jan Hubicka <hubicka@ucw.cz> | 2014-02-20 07:40:07 +0100 |
---|---|---|
committer | Jan Hubicka <hubicka@gcc.gnu.org> | 2014-02-20 06:40:07 +0000 |
commit | bd936951453c1105710649955568375e67c69d30 (patch) | |
tree | aa5cb062d365b7b66d1c27c29cac928aaa4f40a4 /gcc | |
parent | 3c898e1acb4f9c8d43c84d2138fa298de0205c46 (diff) | |
download | gcc-bd936951453c1105710649955568375e67c69d30.zip gcc-bd936951453c1105710649955568375e67c69d30.tar.gz gcc-bd936951453c1105710649955568375e67c69d30.tar.bz2 |
re PR middle-end/58555 (Floating point exception in want_inline_self_recursive_call_p)
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/ipa-inline-transform.c | 17 | ||||
-rw-r--r-- | gcc/ipa-inline.c | 8 | ||||
-rw-r--r-- | gcc/ipa-inline.h | 3 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/torture/pr58555.C | 114 |
6 files changed, 150 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a401d85..24d8e18 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c index a24f68d..b2e0285 100644 --- a/gcc/ipa-inline-transform.c +++ b/gcc/ipa-inline-transform.c @@ -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); diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c index d304133..f6f97f8 100644 --- a/gcc/ipa-inline.c +++ b/gcc/ipa-inline.c @@ -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); } diff --git a/gcc/ipa-inline.h b/gcc/ipa-inline.h index 618189b..0a59608 100644 --- a/gcc/ipa-inline.h +++ b/gcc/ipa-inline.h @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 46ef4dc..0b8de78 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..ac5009a --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr58555.C @@ -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); } |