Bug 45709 - [4.3 Regression] internal compiler error: in add_phi_arg, at tree-phinodes.c:395
Summary: [4.3 Regression] internal compiler error: in add_phi_arg, at tree-phinodes.c:395
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: tree-optimization (show other bugs)
Version: 4.6.0
: P3 normal
Target Milestone: 4.3.6
Assignee: Richard Biener
URL: http://gcc.gnu.org/ml/gcc-patches/201...
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2010-09-17 19:51 UTC by H.J. Lu
Modified: 2010-09-18 18:54 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work: 4.4.5 4.5.2 4.6.0
Known to fail: 4.3.5
Last reconfirmed: 2010-09-18 09:28:41


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description H.J. Lu 2010-09-17 19:51:35 UTC
[hjl@gnu-35 rrs]$ cat foo.cc 
struct foo { 
  virtual void bar();
  struct Rect {
    int bottom;
  };
  struct Region {

    static Region subtract(const Rect& lhs, const Rect& rhs)
      {
	Region reg;
	Rect* storage = reg.storage;
	  {
	    if (lhs.bottom > rhs.bottom)
	      storage++;
	    reg.count = storage - reg.storage;
	  }
	return reg;
      }
    Rect storage[4];
    int count;
  };
  Rect dirtyRegion;
  Rect oldDirtyRegion;
};
void foo::bar()
{
  const Region copyBack(Region::subtract(oldDirtyRegion, dirtyRegion));
}
[hjl@gnu-35 rrs]$ /export/gnu/import/rrs/164143/usr/bin/gcc -S -O foo.cc
foo.cc: In member function ‘virtual void foo::bar()’:
foo.cc:27:70: internal compiler error: in add_phi_arg, at tree-phinodes.c:395
Please submit a full bug report,
with preprocessed source if appropriate.
See <http://gcc.gnu.org/bugs.html> for instructions.
[hjl@gnu-35 rrs]$
Comment 1 Andrew Pinski 2010-09-17 20:25:35 UTC
Reduced testcase:
struct Region {
    int storage[4];
    int count;
};
static inline Region subtract(int lhs)
{
  Region reg;
  int* storage = reg.storage;
  if (lhs > 0)
    storage++;
  reg.count = storage - reg.storage;
  return reg;
}
void bar(int a)
{
  const Region copyBack(subtract(a));
}

---- CUT ---
Comes from inlining.
Comment 2 Andrew Pinski 2010-09-17 20:35:51 UTC
Not what is happening is an interaction between the inlining and the return slot optimization and the named value optimization.
Before inlining we have:

  # storage_1 = PHI <&<retval>.storage[0](2), &<retval>.storage[1](3)>
...
  copyBack.1_1 = (struct Region *) &copyBack;
  *copyBack.1_1 ={v} subtract (a_2(D)) [return slot optimization];

--- Cut ----
Since &(*copyBack.1_1).storage[0] is not a constant we get an ICE.  Why we don't remove the extra cast to begin is questionable.  If we change:
  const Region copyBack(subtract(a));
to
  const Region copyBack = (subtract(a));

We can remove the cast and it works.
Comment 3 H.J. Lu 2010-09-17 22:02:08 UTC
It was introduced between revision 127644 and 127649.
Comment 4 H.J. Lu 2010-09-17 22:17:16 UTC
Revision 127647:

http://gcc.gnu.org/ml/gcc-cvs/2007-08/msg00541.html

introduced:

[hjl@gnu-26 gcc]$ ./xgcc -B./ -S -O ../../../pr45709.cc 
../../../pr45709.cc: In member function ‘virtual void foo::bar()’:
../../../pr45709.cc:27: error: PHI def is not a GIMPLE value
storage_8 = PHI <&copyBack.1_1->storage[0](2), &copyBack.1_1->storage[1](3)>

&copyBack.1_1->storage[0];

../../../pr45709.cc:27: error: PHI def is not a GIMPLE value
storage_8 = PHI <&copyBack.1_1->storage[0](2), &copyBack.1_1->storage[1](3)>

&copyBack.1_1->storage[1];

../../../pr45709.cc:27: error: invalid operand to unary operator
&copyBack.1_1->storage;

../../../pr45709.cc:27: internal compiler error: verify_stmts failed
Please submit a full bug report,
with preprocessed source if appropriate.
See <URL:http://gcc.gnu.org/bugs.html> for instructions.
[hjl@gnu-26 gcc]$ 
Comment 5 H.J. Lu 2010-09-17 22:20:40 UTC
Revision 127647 is the first revision which failed to compile this.
Comment 6 H.J. Lu 2010-09-18 02:59:20 UTC
This patch:

http://gcc.gnu.org/ml/gcc-patches/2010-09/msg01459.html

fixes the bug, but caused:

FAIL: g++.dg/conversion/op5.C  (test for errors, line 18)
FAIL: g++.dg/conversion/op5.C (test for excess errors)

Now, we get

[hjl@gnu-6 gcc]$ ./xgcc -B./ -S -O /export/gnu/import/git/gcc/gcc/testsuite/g++.dg/conversion/op5.C -ansi -pedantic-errors 
/export/gnu/import/git/gcc/gcc/testsuite/g++.dg/conversion/op5.C: In function \u2018void foo(const B&)\u2019:
/export/gnu/import/git/gcc/gcc/testsuite/g++.dg/conversion/op5.C:18:15: error: conversion from \u2018const B\u2019 to non-scalar type \u2018A\u2019 requested
[hjl@gnu-6 gcc]$ 

"const" is missing.
Comment 7 H.J. Lu 2010-09-18 03:36:23 UTC
A patch is posted at

http://gcc.gnu.org/ml/gcc-patches/2010-09/msg01461.html
Comment 8 Richard Biener 2010-09-18 09:53:15 UTC
We run into

              /* With return slot optimization we can end up with
                 non-gimple (foo *)&this->m, fix that here.  */
              if (TREE_CODE (new_arg) != SSA_NAME
                  && TREE_CODE (new_arg) != FUNCTION_DECL
                  && !is_gimple_val (new_arg))
                {
                  gimple_seq stmts = NULL;
                  new_arg = force_gimple_operand (new_arg, &stmts, true, NULL);
                  gsi_insert_seq_on_edge_immediate (new_edge, stmts);

but inserting on an edge that needs splitting, which wrecks new_edge.

Index: tree-inline.c
===================================================================
--- tree-inline.c	(revision 164388)
+++ tree-inline.c	(working copy)
@@ -2021,8 +2021,11 @@ copy_phis_for_bb (basic_block bb, copy_b
 		  && !is_gimple_val (new_arg))
 		{
 		  gimple_seq stmts = NULL;
+		  basic_block tem;
 		  new_arg = force_gimple_operand (new_arg, &stmts, true, NULL);
-		  gsi_insert_seq_on_edge_immediate (new_edge, stmts);
+		  tem = gsi_insert_seq_on_edge_immediate (new_edge, stmts);
+		  if (tem)
+		    new_edge = find_edge (tem, new_bb);
 		}
 	      add_phi_arg (new_phi, new_arg, new_edge,
 			   gimple_phi_arg_location_from_edge (phi, old_edge));

fixes that.
Comment 9 Richard Biener 2010-09-18 11:38:41 UTC
Subject: Bug 45709

Author: rguenth
Date: Sat Sep 18 11:38:25 2010
New Revision: 164390

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=164390
Log:
2010-09-18  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/45709
	* tree-inline.c (copy_phis_for_bb): Fixup new_edge when
	we splitted it.

	* g++.dg/torture/pr45709.C: New testcase.

Added:
    trunk/gcc/testsuite/g++.dg/torture/pr45709.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/tree-inline.c

Comment 10 Richard Biener 2010-09-18 11:39:55 UTC
Subject: Bug 45709

Author: rguenth
Date: Sat Sep 18 11:39:44 2010
New Revision: 164391

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=164391
Log:
2010-09-18  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/45709
	* tree-inline.c (copy_phis_for_bb): Fixup new_edge when
	we splitted it.

	* g++.dg/torture/pr45709.C: New testcase.

Added:
    branches/gcc-4_5-branch/gcc/testsuite/g++.dg/torture/pr45709.C
Modified:
    branches/gcc-4_5-branch/gcc/ChangeLog
    branches/gcc-4_5-branch/gcc/tree-inline.c

Comment 11 Richard Biener 2010-09-18 12:30:55 UTC
Stopping here for now - I guess doing immediate insertion still can break
things as if there is another PHI node we'll iterate over the edges
again (but now including split ones) and find_edge (new_edge->src->aux, bb)
will break as new_edge->src is the newly inserted block.

I suppose delaying edge insert commits until after at least this block
is finished is better.
Comment 12 Richard Biener 2010-09-18 12:42:58 UTC
Yep - testcase that still ICEs (now w/ a segfault):

struct Region {
    int storage[4];
    int count;
};
static inline Region subtract(int lhs)
{
  Region reg;
  int* storage = reg.storage;
  int* storage2 = reg.storage;
  if (lhs > 0)
    storage++, storage2--;
  reg.count = storage - reg.storage + storage2 - reg.storage;
  return reg;
}
void bar(int a)
{
  const Region copyBack(subtract(a));
}
Comment 13 Richard Biener 2010-09-18 12:54:30 UTC
new patch in testing.
Comment 14 Richard Biener 2010-09-18 17:13:16 UTC
Subject: Bug 45709

Author: rguenth
Date: Sat Sep 18 17:13:04 2010
New Revision: 164397

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=164397
Log:
2010-09-18  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/45709
	* tree-inline.c (copy_phis_for_bb): Delay commit of edge
	insertions until after all PHI nodes of the block are processed.

	* g++.dg/torture/pr45709-2.C: New testcase.

Added:
    trunk/gcc/testsuite/g++.dg/torture/pr45709-2.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/tree-inline.c

Comment 15 Richard Biener 2010-09-18 17:16:55 UTC
Subject: Bug 45709

Author: rguenth
Date: Sat Sep 18 17:16:42 2010
New Revision: 164398

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=164398
Log:
2010-09-18  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/45709
	* tree-inline.c (copy_phis_for_bb): Delay commit of edge
	insertions until after all PHI nodes of the block are processed.

	* g++.dg/torture/pr45709-2.C: New testcase.

Added:
    branches/gcc-4_5-branch/gcc/testsuite/g++.dg/torture/pr45709-2.C
Modified:
    branches/gcc-4_5-branch/gcc/ChangeLog
    branches/gcc-4_5-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_5-branch/gcc/tree-inline.c

Comment 16 Richard Biener 2010-09-18 17:23:36 UTC
Subject: Bug 45709

Author: rguenth
Date: Sat Sep 18 17:23:20 2010
New Revision: 164399

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=164399
Log:
2010-09-18  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/45709
	* tree-inline.c (copy_phis_for_bb): Delay commit of edge
	insertions until after all PHI nodes of the block are processed.

	* g++.dg/torture/pr45709.C: New testcase.
	* g++.dg/torture/pr45709-2.C: Likewise.

Added:
    branches/gcc-4_4-branch/gcc/testsuite/g++.dg/torture/pr45709-2.C
    branches/gcc-4_4-branch/gcc/testsuite/g++.dg/torture/pr45709.C
Modified:
    branches/gcc-4_4-branch/gcc/ChangeLog
    branches/gcc-4_4-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_4-branch/gcc/tree-inline.c

Comment 17 Richard Biener 2010-09-18 17:24:14 UTC
Backport for 4.3 pending testing.
Comment 18 Richard Biener 2010-09-18 18:54:09 UTC
Subject: Bug 45709

Author: rguenth
Date: Sat Sep 18 18:53:53 2010
New Revision: 164400

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=164400
Log:
2010-09-18  Richard Guenther  <rguenther@suse.de>

	PR tree-optimization/45709
	* tree-inline.c (copy_phis_for_bb): Delay commit of edge
	insertions until after all PHI nodes of the block are processed.

	* g++.dg/torture/pr45709.C: New testcase.
	* g++.dg/torture/pr45709-2.C: Likewise.

Added:
    branches/gcc-4_3-branch/gcc/testsuite/g++.dg/torture/pr45709-2.C
    branches/gcc-4_3-branch/gcc/testsuite/g++.dg/torture/pr45709.C
Modified:
    branches/gcc-4_3-branch/gcc/ChangeLog
    branches/gcc-4_3-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_3-branch/gcc/tree-inline.c

Comment 19 Richard Biener 2010-09-18 18:54:33 UTC
Fixed.