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
This commit is contained in:
Jan Hubicka 2014-02-20 07:40:07 +01:00 committed by Jan Hubicka
parent 3c898e1acb
commit bd93695145
6 changed files with 150 additions and 7 deletions

View 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

View 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);

View 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);
}

View 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;

View 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

View File

@ -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); }