Commit 610c8ef0 by Martin Jambor Committed by Martin Jambor

re PR ipa/60640 (ICE edge points to wrong declaration / verify_cgraph_node failed)

2014-04-04  Martin Jambor  <mjambor@suse.cz>

	PR ipa/60640
        * cgraph.h (cgraph_clone_node): New parameter added to declaration.
        Adjust all callers.
	* cgraph.c (clone_of_p): Also return true if thunks match.
	(verify_edge_corresponds_to_fndecl): Removed extraneous call to
	cgraph_function_or_thunk_node and an obsolete comment.
        * cgraphclones.c (build_function_type_skip_args): Moved upwards in the
        file.
        (build_function_decl_skip_args): Likewise.
	(set_new_clone_decl_and_node_flags): New function.
        (duplicate_thunk_for_node): Likewise.
        (redirect_edge_duplicating_thunks): Likewise.
        (cgraph_clone_node): New parameter args_to_skip, pass it to
        redirect_edge_duplicating_thunks which is called instead of
        cgraph_redirect_edge_callee.
        (cgraph_create_virtual_clone): Pass args_to_skip to cgraph_clone_node,
	moved setting of a lot of flags to set_new_clone_decl_and_node_flags.

testsuite/
        * g++.dg/ipa/pr60640-1.C: New test.
        * g++.dg/ipa/pr60640-2.C: Likewise.
        * g++.dg/ipa/pr60640-3.C: Likewise.
        * g++.dg/ipa/pr60640-4.C: Likewise.

From-SVN: r209097
parent 57ef133b
2014-04-04 Martin Jambor <mjambor@suse.cz>
PR ipa/60640
* cgraph.h (cgraph_clone_node): New parameter added to declaration.
Adjust all callers.
* cgraph.c (clone_of_p): Also return true if thunks match.
(verify_edge_corresponds_to_fndecl): Removed extraneous call to
cgraph_function_or_thunk_node and an obsolete comment.
* cgraphclones.c (build_function_type_skip_args): Moved upwards in the
file.
(build_function_decl_skip_args): Likewise.
(set_new_clone_decl_and_node_flags): New function.
(duplicate_thunk_for_node): Likewise.
(redirect_edge_duplicating_thunks): Likewise.
(cgraph_clone_node): New parameter args_to_skip, pass it to
redirect_edge_duplicating_thunks which is called instead of
cgraph_redirect_edge_callee.
(cgraph_create_virtual_clone): Pass args_to_skip to cgraph_clone_node,
moved setting of a lot of flags to set_new_clone_decl_and_node_flags.
2014-04-04 Bernd Edlinger <bernd.edlinger@hotmail.de>
PR fortran/60191
......
......@@ -2544,12 +2544,34 @@ collect_callers_of_node (struct cgraph_node *node)
return redirect_callers;
}
/* Return TRUE if NODE2 is equivalent to NODE or its clone. */
/* Return TRUE if NODE2 a clone of NODE or is equivalent to it. */
static bool
clone_of_p (struct cgraph_node *node, struct cgraph_node *node2)
{
bool skipped_thunk = false;
node = cgraph_function_or_thunk_node (node, NULL);
node2 = cgraph_function_or_thunk_node (node2, NULL);
/* There are no virtual clones of thunks so check former_clone_of or if we
might have skipped thunks because this adjustments are no longer
necessary. */
while (node->thunk.thunk_p)
{
if (node2->former_clone_of == node->decl)
return true;
if (!node->thunk.this_adjusting)
return false;
node = cgraph_function_or_thunk_node (node->callees->callee, NULL);
skipped_thunk = true;
}
if (skipped_thunk
&& (!node2->clone_of
|| !node2->clone.args_to_skip
|| !bitmap_bit_p (node2->clone.args_to_skip, 0)))
return false;
while (node != node2 && node2)
node2 = node2->clone_of;
return node2 != NULL;
......@@ -2649,10 +2671,8 @@ verify_edge_corresponds_to_fndecl (struct cgraph_edge *e, tree decl)
node = cgraph_function_or_thunk_node (node, NULL);
if (e->callee->former_clone_of != node->decl
/* IPA-CP sometimes redirect edge to clone and then back to the former
function. This ping-pong has to go, eventually. */
&& (node != cgraph_function_or_thunk_node (e->callee, NULL))
&& !clone_of_p (cgraph_function_or_thunk_node (node, NULL), e->callee))
&& !clone_of_p (node, e->callee))
return true;
else
return false;
......
......@@ -890,7 +890,7 @@ struct cgraph_edge * cgraph_clone_edge (struct cgraph_edge *,
unsigned, gcov_type, int, bool);
struct cgraph_node * cgraph_clone_node (struct cgraph_node *, tree, gcov_type,
int, bool, vec<cgraph_edge_p>,
bool, struct cgraph_node *);
bool, struct cgraph_node *, bitmap);
tree clone_function_name (tree decl, const char *);
struct cgraph_node * cgraph_create_virtual_clone (struct cgraph_node *old_node,
vec<cgraph_edge_p>,
......
......@@ -184,7 +184,7 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
freq_scale = e->frequency;
n = cgraph_clone_node (e->callee, e->callee->decl,
e->count, freq_scale, update_original,
vNULL, true, inlining_into);
vNULL, true, inlining_into, NULL);
cgraph_redirect_edge_callee (e, n);
}
}
......
......@@ -1383,7 +1383,7 @@ recursive_inlining (struct cgraph_edge *edge,
/* We need original clone to copy around. */
master_clone = cgraph_clone_node (node, node->decl,
node->count, CGRAPH_FREQ_BASE,
false, vNULL, true, NULL);
false, vNULL, true, NULL, NULL);
for (e = master_clone->callees; e; e = e->next_callee)
if (!e->inline_failed)
clone_inlined_nodes (e, true, false, NULL, CGRAPH_FREQ_BASE);
......
......@@ -1042,7 +1042,7 @@ input_node (struct lto_file_decl_data *file_data,
{
node = cgraph_clone_node (cgraph (nodes[clone_ref]), fn_decl,
0, CGRAPH_FREQ_BASE, false,
vNULL, false, NULL);
vNULL, false, NULL, NULL);
}
else
{
......
2014-04-04 Martin Jambor <mjambor@suse.cz>
PR ipa/60640
* g++.dg/ipa/pr60640-1.C: New test.
* g++.dg/ipa/pr60640-2.C: Likewise.
* g++.dg/ipa/pr60640-3.C: Likewise.
* g++.dg/ipa/pr60640-4.C: Likewise.
2014-04-04 Jeff Law <law@redhat.com>
PR target/60657
......
// { dg-do compile }
// { dg-options "-O3" }
class ASN1Object
{
public:
virtual ~ASN1Object ();
};
class A
{
virtual unsigned m_fn1 () const;
};
class B
{
public:
ASN1Object Element;
virtual unsigned m_fn1 (bool) const;
};
template <class BASE> class C : public BASE
{
};
class D : ASN1Object, public B
{
};
class G : public D
{
unsigned m_fn1 (bool) const {}
};
class F : A
{
public:
F (A);
unsigned m_fn1 () const
{
int a;
a = m_fn2 ().m_fn1 (0);
return a;
}
const B &m_fn2 () const { return m_groupParameters; }
C<G> m_groupParameters;
};
template <class D> void BenchMarkKeyAgreement (int *, int *, int)
{
A f;
D d (f);
}
void BenchmarkAll2 () { BenchMarkKeyAgreement<F>(0, 0, 0); }
// { dg-do compile }
// { dg-options "-O3" }
struct B { virtual unsigned f () const; };
struct C { virtual void f (); };
struct F { virtual unsigned f (bool) const; ~F (); };
struct J : C, F {};
struct G : J { unsigned f (bool) const { return 0; } };
struct H : B
{
H (int);
unsigned f () const { return ((const F &) h).f (0); }
G h;
};
H h (0);
// { dg-do run }
// { dg-options "-O3" }
struct Distraction
{
char fc[8];
virtual Distraction * return_self ()
{ return this; }
};
namespace {
struct A;
static A * __attribute__ ((noinline, noclone)) get_an_A ();
static int go;
struct A
{
int fi;
A () : fi(777) {}
A (int pi) : fi (pi) {}
virtual A * foo (int p) = 0;
};
struct B;
static B * __attribute__ ((noinline, noclone)) get_a_B ();
struct B : public Distraction, A
{
B () : Distraction(), A() { }
B (int pi) : Distraction (), A (pi) {}
virtual B * foo (int p)
{
int o = fi;
for (int i = 0; i < p; i++)
o += i + i * i;
go = o;
return get_a_B ();
}
};
struct B gb1 (1111), gb2 (2);
static B * __attribute__ ((noinline, noclone))
get_a_B ()
{
return &gb1;
}
static A * __attribute__ ((noinline, noclone))
get_an_A ()
{
return &gb2;
}
}
static int __attribute__ ((noinline, noclone))
get_a_number ()
{
return 5;
}
extern "C" void abort (void);
int main (int argc, char *argv[])
{
for (int i = 0; i < get_a_number (); i++)
{
struct A *p = get_an_A ();
struct A *r = p->foo (4);
if (r->fi != 1111)
abort ();
if (go != 22)
abort ();
}
return 0;
}
// { dg-do run }
// { dg-options "-O3 -fdump-ipa-cp" }
struct Distraction
{
char fc[8];
virtual Distraction * return_self ()
{ return this; }
};
namespace {
struct A;
static A * __attribute__ ((noinline, noclone)) get_an_A ();
static int go;
struct A
{
int fi;
A () : fi(777) {}
A (int pi) : fi (pi) {}
virtual void foo (int p) = 0;
};
struct B : public Distraction, A
{
B () : Distraction(), A() { }
B (int pi) : Distraction (), A (pi) {}
virtual void foo (int p)
{
int o = fi;
for (int i = 0; i < p; i++)
o += i + i * i;
go = o;
}
};
struct B gb (2);
static A * __attribute__ ((noinline, noclone))
get_an_A ()
{
return &gb;
}
}
static int __attribute__ ((noinline, noclone))
get_a_number ()
{
return 5;
}
extern "C" void abort (void);
static void __attribute__ ((noinline, noclone))
bar ()
{
for (int i = 0; i < get_a_number (); i++)
{
struct A *p = get_an_A ();
p->foo (4);
if (go != 22)
abort ();
}
}
int main (int argc, char *argv[])
{
for (int i = 0; i < get_a_number (); i++)
{
struct A *p = get_an_A ();
p->foo (4);
if (go != 22)
abort ();
}
bar ();
return 0;
}
/* { dg-final { scan-ipa-dump-times "Thunk fixed offset" 2 "cp"} } */
/* { dg-final { cleanup-ipa-dump "cp" } } */
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