This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PR middle-end/40102
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 8 Jun 2009 16:45:15 +0200
- Subject: PR middle-end/40102
Hi,
this patch fix ICE in PR 40102. The problem here is that indirect
inlining discovers the fact that there is direct call to foo0 after
inlining, but it happens only in some clones but not in another. When
producing IPA-CP clone we fail to add the edge consistently.
Bootstrapping/regtesting x86_64-linux, will commit it if passes.
Honza
* cgraph.c (cgraph_create_edge_including_clones): Also asume that the
original node might've been modified.
* tree-inline.c (copy_bb): Do not assume that all clones are the same.
* g++.dg/torture/pr40102.C: New testcase.
Index: cgraph.c
===================================================================
*** cgraph.c (revision 148275)
--- cgraph.c (working copy)
*************** cgraph_create_edge_including_clones (str
*** 701,708 ****
{
struct cgraph_node *node;
! cgraph_create_edge (orig, callee, stmt, count, freq, loop_depth)->inline_failed =
! reason;
if (orig->clones)
for (node = orig->clones; node != orig;)
--- 701,709 ----
{
struct cgraph_node *node;
! if (!cgraph_edge (orig, stmt))
! cgraph_create_edge (orig, callee, stmt,
! count, freq, loop_depth)->inline_failed = reason;
if (orig->clones)
for (node = orig->clones; node != orig;)
Index: testsuite/g++.dg/torture/pr40102.C
===================================================================
*** testsuite/g++.dg/torture/pr40102.C (revision 0)
--- testsuite/g++.dg/torture/pr40102.C (revision 0)
***************
*** 0 ****
--- 1,41 ----
+ /* { dg-do compile } */
+ bool foo0(int) { return true; }
+
+ bool foo1();
+
+ struct A
+ {
+ A();
+ ~A();
+
+ template<typename T> void bar1(T f)
+ {
+ if (f(0))
+ foo1();
+ }
+
+ template<typename T> void bar2(T);
+ };
+
+ template<typename T> void A::bar2(T f)
+ {
+ A a, b[1], *p;
+
+ while (foo1())
+ {
+ if (p)
+ ++p;
+ if (p && foo1())
+ bar1(f);
+ if (p)
+ ++p;
+ }
+
+ if (foo1())
+ bar1(f);
+ }
+
+ void baz()
+ {
+ A().bar2(foo0);
+ }
Index: tree-inline.c
===================================================================
*** tree-inline.c (revision 148275)
--- tree-inline.c (working copy)
*************** copy_bb (copy_body_data *id, basic_block
*** 1508,1518 ****
gcc_unreachable ();
}
/* Constant propagation on argument done during inlining
may create new direct call. Produce an edge for it. */
! if (!edge && is_gimple_call (stmt)
! && (fn = gimple_call_fndecl (stmt)) != NULL
! && !cgraph_edge (id->dst_node, stmt))
{
struct cgraph_node *dest = cgraph_node (fn);
--- 1508,1521 ----
gcc_unreachable ();
}
+ edge = cgraph_edge (id->src_node, orig_stmt);
/* Constant propagation on argument done during inlining
may create new direct call. Produce an edge for it. */
! if ((!edge
! || (edge->indirect_call
! && id->transform_call_graph_edges == CB_CGE_MOVE_CLONES))
! && is_gimple_call (stmt)
! && (fn = gimple_call_fndecl (stmt)) != NULL)
{
struct cgraph_node *dest = cgraph_node (fn);