Bug 40570 - [4.5 Regression] ICE with recursion at -O3
Summary: [4.5 Regression] ICE with recursion at -O3
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.5.0
: P1 normal
Target Milestone: 4.5.0
Assignee: Not yet assigned to anyone
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2009-06-27 18:07 UTC by David Binderman
Modified: 2009-07-30 16:43 UTC (History)
5 users (show)

See Also:
Host: x86_64-suse-linux
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2009-06-30 01:59:22


Attachments
C source code (44.93 KB, text/plain)
2009-06-27 18:08 UTC, David Binderman
Details
reduced testcase (742 bytes, text/plain)
2009-06-27 19:06 UTC, Richard Biener
Details

Note You need to log in before you can comment on or make changes to this bug.
Description David Binderman 2009-06-27 18:07:41 UTC
I just tried to compile the Suse Linux package qemacs-0.3.1-381.2
with the G++ compiler version 4.5 snapshot 20090625.
The compiler said

css.c:819:24: warning: cast from pointer to integer of different size
gcc: Internal error: Segmentation fault (program cc1)
Please submit a full bug report.
See <http://gcc.gnu.org/bugs.html> for instructions.

Preprocessed source attached. Flag -O3 required.

Here is valgrind helping out with a stack backtrace.

==19864== Invalid read of size 4
==19864==    at 0x8897FE: get_constraint_for_ptr_offset (tree-ssa-structalias.c:2877)
==19864==    by 0x10000006F: ???
==19864==    by 0x7FFFFFFFFFFFFFFF: ???
==19864==    by 0x87: ???
==19864==    by 0x645537F: ???
==19864==    by 0x7FEFFF92F: ???
==19864==    by 0x5F2C57F: ???
==19864==  Address 0x623b23c is 12 bytes inside a block of size 72 free'd
==19864==    at 0x4C257E1: realloc (in /usr/lib64/valgrind/amd64-linux/vgpreload_memcheck.so)
==19864==    by 0xC231CC: xrealloc (xmalloc.c:179)
==19864==    by 0x9076D6: vec_heap_o_reserve_1 (vec.c:320)
==19864==    by 0x889823: get_constraint_for_ptr_offset (tree-ssa-structalias.c:379)
==19864==    by 0x10000006F: ???
==19864==    by 0x7FFFFFFFFFFFFFFF: ???
==19864==    by 0x87: ???
==19864==    by 0x645537F: ???
==19864==    by 0x7FEFFF92F: ???
==19864==    by 0x5F2C57F: ???
Comment 1 David Binderman 2009-06-27 18:08:56 UTC
Created attachment 18079 [details]
C source code
Comment 2 Richard Biener 2009-06-27 18:38:20 UTC
Hm, for me it endlessly recurses

#49 0x087e631e in cgraph_clone_inlined_nodes (e=0xb78db340, duplicate=0 '\0', 
    update_original=1 '\001') at /home/richard/src/trunk/gcc/ipa-inline.c:261
261	      cgraph_clone_inlined_nodes (e, duplicate, update_original);
(gdb) 
#50 0x087e631e in cgraph_clone_inlined_nodes (e=0xb78e2980, duplicate=0 '\0', 
    update_original=1 '\001') at /home/richard/src/trunk/gcc/ipa-inline.c:261
261	      cgraph_clone_inlined_nodes (e, duplicate, update_original);
(gdb) 
#51 0x087e631e in cgraph_clone_inlined_nodes (e=0xb78db340, duplicate=0 '\0', 
    update_original=1 '\001') at /home/richard/src/trunk/gcc/ipa-inline.c:261
261	      cgraph_clone_inlined_nodes (e, duplicate, update_original);
(gdb) 
#52 0x087e631e in cgraph_clone_inlined_nodes (e=0xb78e2980, duplicate=0 '\0', 
    update_original=1 '\001') at /home/richard/src/trunk/gcc/ipa-inline.c:261
261	      cgraph_clone_inlined_nodes (e, duplicate, update_original);

-O2 -fipa-cp-clone is enough to cause that.

If you can reproduce the ICE in tree-ssa-structalias.c can you try to
reduce it and/or debug it?
Comment 3 Richard Biener 2009-06-27 19:06:56 UTC
Created attachment 18080 [details]
reduced testcase

slightly reduced testcase.
Comment 4 Martin Jambor 2009-06-29 11:22:00 UTC
I'm quite confident this is a cgraph bug => CCing honza.  (I'll try to keep this on my radar but there are other issues for which I am certainly responsible now). 
Comment 5 Volker Reichelt 2009-06-30 01:59:22 UTC
Confirmed. Reduced testcase that goes into infinite loop:

=========================================
static int foo(int i);

static int bar(int i) { foo(i); }

static int foo(int i)
{
  int j;
  if (j)
    FOO(j);
  return bar(i);
}

int baz()
{
  foo(0);
  if (baz())
    return 1;
  return 0;
}
=========================================

This might be related to PR40556.
Comment 6 Martin Jambor 2009-07-28 20:14:39 UTC
When I move "e->inline_failed = CIF_OK" in cgraph_mark_inline_edge()
until after call to cgraph_clone_inlined_nodes(), the endless
recursion goes away.  However, I now get an assert in
cgraph_estimate_size_after_inlining because the calculated size
overflows... thus I'm looking at where the sizes grow so grossly.
Comment 7 Martin Jambor 2009-07-28 20:59:26 UTC
Ha, please disregard the previous message, obviously I had to make a
fool out of myself before realizing that loops in the inlining plan
are the bug, not how we handle them.

The reason there are such loops is that ipa-cp has made a portion of
the graph effectively dead but strongly connected via single uses
which ipa-inline handles specially and wants to inline them whenever
it seems possible.  But it sis not check for loops.

So, I belive the patch below fixes this issue and I am going to
bootstrap it overnight.  Honza, can you please confirm this is indeed
a correct fix?  Thanks.


2009-07-28  Martin Jambor  <mjambor@suse.cz>

	* ipa-inline.c (cgraph_decide_inlining): Watch out for dead single
	use inlining loops.

	* testsuite/gcc.c-torture/compile/pr40570.c: New test.


Index: icln/gcc/ipa-inline.c
===================================================================
--- icln.orig/gcc/ipa-inline.c
+++ icln/gcc/ipa-inline.c
@@ -1227,6 +1227,7 @@ cgraph_decide_inlining (void)
 	      && !node->needed
 	      && node->local.inlinable
 	      && node->callers->inline_failed
+	      && node->callers->caller->global.inlined_to != node
 	      && !gimple_call_cannot_inline_p (node->callers->call_stmt)
 	      && !DECL_EXTERNAL (node->decl)
 	      && !DECL_COMDAT (node->decl))
Index: icln/gcc/testsuite/gcc.c-torture/compile/pr40570.c
===================================================================
--- /dev/null
+++ icln/gcc/testsuite/gcc.c-torture/compile/pr40570.c
@@ -0,0 +1,19 @@
+static int foo(int i);
+
+static int bar(int i) { foo(i); }
+
+static int foo(int i)
+{
+  int j;
+  if (j)
+    FOO(j);
+  return bar(i);
+}
+
+int baz()
+{
+  foo(0);
+  if (baz())
+    return 1;
+  return 0;
+}
Comment 8 rguenther@suse.de 2009-07-29 08:09:36 UTC
Subject: Re:  [4.5 Regression] ICE with recursion
 at -O3

On Tue, 28 Jul 2009, jamborm at gcc dot gnu dot org wrote:

> ------- Comment #7 from jamborm at gcc dot gnu dot org  2009-07-28 20:59 -------
> Ha, please disregard the previous message, obviously I had to make a
> fool out of myself before realizing that loops in the inlining plan
> are the bug, not how we handle them.
> 
> The reason there are such loops is that ipa-cp has made a portion of
> the graph effectively dead but strongly connected via single uses
> which ipa-inline handles specially and wants to inline them whenever
> it seems possible.  But it sis not check for loops.
> 
> So, I belive the patch below fixes this issue and I am going to
> bootstrap it overnight.  Honza, can you please confirm this is indeed
> a correct fix?  Thanks.

> +             && node->callers->caller->global.inlined_to != node

That only detects direct loops, does it?  IMHO ipa-inline should have
computed callgraph SCCs anyway for a long time now ... we just seem
to keep accumulating interesting workarounds for cycles ;)

Richard.
Comment 9 Martin Jambor 2009-07-29 09:51:41 UTC
(In reply to comment #8)

> > ------- Comment #7 from jamborm at gcc dot gnu dot org  2009-07-28 20:59 -------
> > So, I belive the patch below fixes this issue and I am going to
> > bootstrap it overnight.  Honza, can you please confirm this is indeed
> > a correct fix?  Thanks.
> 
> > +             && node->callers->caller->global.inlined_to != node
> 
> That only detects direct loops, does it?  

I don't understand.  This loop consisted of nodes that are going to be
inlined, they have only one caller and the incoming edge is marked for
inlining.  There cannot be any indirect calls or complex cycles or
anything.  In fact, looking at the inlined edges, the inlined nodes
should only form a tree.

> IMHO ipa-inline should have computed callgraph SCCs anyway for a
> long time now ... we just seem to keep accumulating interesting
> workarounds for cycles ;)

Well, I don't see how this would help, at least in this particular
case.  There are cycles in the call graph, we just must not create
cycles consisting of edges with inline_failed == NULL.  I do not think
that explicit tests like this are somehow bad, we would have to test
the property one way or another.
Comment 10 Martin Jambor 2009-07-29 10:33:29 UTC
Bootstrap and testing finished fine, I submitted the patch:
http://gcc.gnu.org/ml/gcc-patches/2009-07/msg01642.html
Comment 11 Martin Jambor 2009-07-29 13:40:50 UTC
(In reply to comment #8)
> That only detects direct loops, does it? 

Actually, now  I may understand  but no, it  is exactly the  other way
round.  The patch above only detects indirect loops, when there are at
least two nodes involved.  But that is not necessarily true, as I have
just  discovered the  hard way  when testing  my ipa-cp  stuff...  The
updated patch which I am going to test now therefore is:


2009-07-30  Martin Jambor  <mjambor@suse.cz>

	* ipa-inline.c (cgraph_decide_inlining): Watch out for dead single
	use inlining loops.

	* testsuite/gcc.c-torture/compile/pr40570.c: New test.


Index: icln/gcc/ipa-inline.c
===================================================================
--- icln.orig/gcc/ipa-inline.c
+++ icln/gcc/ipa-inline.c
@@ -1227,6 +1227,8 @@ cgraph_decide_inlining (void)
 	      && !node->needed
 	      && node->local.inlinable
 	      && node->callers->inline_failed
+	      && node->callers->caller != node
+	      && node->callers->caller->global.inlined_to != node
 	      && !gimple_call_cannot_inline_p (node->callers->call_stmt)
 	      && !DECL_EXTERNAL (node->decl)
 	      && !DECL_COMDAT (node->decl))
Index: icln/gcc/testsuite/gcc.c-torture/compile/pr40570.c
===================================================================
--- /dev/null
+++ icln/gcc/testsuite/gcc.c-torture/compile/pr40570.c
@@ -0,0 +1,19 @@
+static int foo(int i);
+
+static int bar(int i) { foo(i); }
+
+static int foo(int i)
+{
+  int j;
+  if (j)
+    FOO(j);
+  return bar(i);
+}
+
+int baz()
+{
+  foo(0);
+  if (baz())
+    return 1;
+  return 0;
+}

Comment 12 Martin Jambor 2009-07-30 16:26:36 UTC
Subject: Bug 40570

Author: jamborm
Date: Thu Jul 30 16:26:09 2009
New Revision: 150263

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=150263
Log:
2009-07-30  Martin Jambor  <mjambor@suse.cz>

	PR tree-optimization/40570
	* ipa-inline.c (cgraph_decide_inlining): Watch out for dead single
	use inlining loops.

	* testsuite/gcc.c-torture/compile/pr40570.c: New test.


Added:
    trunk/gcc/testsuite/gcc.c-torture/compile/pr40570.c
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/ipa-inline.c
    trunk/gcc/testsuite/ChangeLog

Comment 13 Martin Jambor 2009-07-30 16:43:27 UTC
Fixed.
Comment 14 hjl@gcc.gnu.org 2009-08-05 14:45:38 UTC
Subject: Bug 40570

Author: hjl
Date: Wed Aug  5 14:45:15 2009
New Revision: 150487

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=150487
Log:
2009-07-28  H.J. Lu  <hongjiu.lu@intel.com>

	Backport from mainline:
	2009-07-30  Martin Jambor  <mjambor@suse.cz>

	PR tree-optimization/40570
	* gcc.c-torture/compile/pr40570.c: New test.

	2009-07-29  Richard Guenther  <rguenther@suse.de>

	PR c++/40834
	* g++.dg/torture/pr40834.C: New testcase.

Added:
    branches/gcc-4_4-branch/gcc/testsuite/g++.dg/torture/pr40834.C
      - copied unchanged from r150485, trunk/gcc/testsuite/g++.dg/torture/pr40834.C
    branches/gcc-4_4-branch/gcc/testsuite/gcc.c-torture/compile/pr40570.c
      - copied unchanged from r150484, trunk/gcc/testsuite/gcc.c-torture/compile/pr40570.c
Modified:
    branches/gcc-4_4-branch/gcc/testsuite/ChangeLog