Commit bd936951 by Jan Hubicka Committed by Jan Hubicka

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
parent 3c898e1a
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> 2014-02-20 Ilya Tocar <ilya.tocar@intel.com>
PR target/60204 PR target/60204
......
...@@ -127,11 +127,15 @@ can_remove_node_now_p (struct cgraph_node *node, struct cgraph_edge *e) ...@@ -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. the edge and redirect it to the new clone.
DUPLICATE is used for bookkeeping on whether we are actually creating new DUPLICATE is used for bookkeeping on whether we are actually creating new
clones or re-using node originally representing out-of-line function call. 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 void
clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, 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_node *inlining_into;
struct cgraph_edge *next; struct cgraph_edge *next;
...@@ -175,8 +179,11 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, ...@@ -175,8 +179,11 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
else else
{ {
struct cgraph_node *n; struct cgraph_node *n;
if (freq_scale == -1)
freq_scale = e->frequency;
n = cgraph_clone_node (e->callee, e->callee->decl, 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); vNULL, true, inlining_into);
cgraph_redirect_edge_callee (e, n); cgraph_redirect_edge_callee (e, n);
} }
...@@ -191,7 +198,7 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, ...@@ -191,7 +198,7 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
{ {
next = e->next_callee; next = e->next_callee;
if (!e->inline_failed) 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)) if (e->speculative && !speculation_useful_p (e, true))
{ {
cgraph_resolve_speculation (e, NULL); cgraph_resolve_speculation (e, NULL);
...@@ -260,7 +267,7 @@ inline_call (struct cgraph_edge *e, bool update_original, ...@@ -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); gcc_assert (curr->callee->global.inlined_to == to);
......
...@@ -708,6 +708,12 @@ want_inline_self_recursive_call_p (struct cgraph_edge *edge, ...@@ -708,6 +708,12 @@ want_inline_self_recursive_call_p (struct cgraph_edge *edge,
if (outer_node->global.inlined_to) if (outer_node->global.inlined_to)
caller_freq = outer_node->callers->frequency; caller_freq = outer_node->callers->frequency;
if (!caller_freq)
{
reason = "function is inlined and unlikely";
want_inline = false;
}
if (!want_inline) if (!want_inline)
; ;
/* Inlining of self recursive function into copy of itself within other function /* Inlining of self recursive function into copy of itself within other function
...@@ -1385,7 +1391,7 @@ recursive_inlining (struct cgraph_edge *edge, ...@@ -1385,7 +1391,7 @@ recursive_inlining (struct cgraph_edge *edge,
false, vNULL, true, NULL); false, vNULL, true, NULL);
for (e = master_clone->callees; e; e = e->next_callee) for (e = master_clone->callees; e; e = e->next_callee)
if (!e->inline_failed) 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); cgraph_redirect_edge_callee (curr, master_clone);
reset_edge_growth_cache (curr); reset_edge_growth_cache (curr);
} }
......
...@@ -233,7 +233,8 @@ bool speculation_useful_p (struct cgraph_edge *e, bool anticipate_inlining); ...@@ -233,7 +233,8 @@ bool speculation_useful_p (struct cgraph_edge *e, bool anticipate_inlining);
/* In ipa-inline-transform.c */ /* In ipa-inline-transform.c */
bool inline_call (struct cgraph_edge *, bool, vec<cgraph_edge_p> *, int *, bool); bool inline_call (struct cgraph_edge *, bool, vec<cgraph_edge_p> *, int *, bool);
unsigned int inline_transform (struct cgraph_node *); 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 ncalls_inlined;
extern int nfunctions_inlined; extern int nfunctions_inlined;
......
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> 2014-02-20 Ilya Tocar <ilya.tocar@intel.com>
PR target/60204 PR target/60204
......
/* { 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); }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment