Bug 58165

Summary: [4.8/4.9 regression] internal compiler error: verify_flow_info
Product: gcc Reporter: Alexander Ivchenko <aivchenk>
Component: regressionAssignee: Jakub Jelinek <jakub>
Status: RESOLVED FIXED    
Severity: normal CC: jakub
Priority: P3    
Version: 4.8.0   
Target Milestone: 4.8.2   
Host: Target:
Build: Known to work:
Known to fail: Last reconfirmed: 2013-08-15 00:00:00
Attachments: gcc49-pr58165.patch
gcc49-pr58165.patch

Description Alexander Ivchenko 2013-08-15 07:00:40 UTC
extern "C" {
  float sqrtf(float);
}

class V
{
public:
  double length2 () const {}
  double length () const
  {
    return sqrtf(length2());
  }

  V& normalize()
  {
    length();
    return *this;
  }
};

class B1
{
public:
  virtual ~B1 ();
};

class B2: public B1
{
public:
  B2(const V& p0,const V& p1,const V& p2) : B1() {}
};

class A1
{
public:
  virtual ~A1 ();
};

struct A2: public A1
{
  V m_v;

  virtual void foo (V v)
  {
    V v1 (v);
    B2 tA (m_v, m_v, m_v);
    V v2 = v1.normalize();
  }
};

void bar ()
{
  A2 a;
}

Compile: g++ -c -O3 test.C
test.C: In member function ‘virtual void A2::foo(V)’:
test.C:43:16: error: BB 6 is missing an EH edge
   virtual void foo (V v)
                ^
test.C:43:16: internal compiler error: verify_flow_info failed
0x8b31ce verify_flow_info()
        src/gcc/gcc/cfghooks.c:260
0xbceee7 execute_function_todo
        src/gcc/gcc/passes.c:1633
0xbce1b3 do_per_function
        src/gcc/gcc/passes.c:1358
0xbcefd7 execute_todo
        src/gcc/gcc/passes.c:1660

_________________________________________
The case came from android ndk r9: it's 4.8 is unable to compile bullet lib. After some investigation I found that it's the same as in usual 4.8-release with just android sysroot (The reason is that 'sqrtf' is defined in Bionic without throw, if you add throw() to it, as it is in glibc, the ICE will disappear again).


The guilty revision is:


Author: eraman <eraman@138bc75d-0d04-0410-961f-82ee72b054a4>
Date:   Fri Jun 15 17:35:11 2012 +0000

    2012-06-15   Easwaran Raman  <eraman@google.com>

        * passes.c (init_optimization_passes): Remove pass_call_cdce
        from its current position and insert after pass_dce.



    git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@188675 138bc75d-0d04-0410-961f-82ee72b054a4
Comment 1 Andrew Pinski 2013-08-15 07:06:39 UTC
>The guilty revision is:

No that just exposed the bug.
Comment 2 Jakub Jelinek 2013-08-15 12:04:53 UTC
Sounds like call-cdce bug to me.
Reduced testcase:
extern "C" float sqrtf (float);

struct A
{
  A ();
  ~A ();
};

void
foo (double d)
{
  A a;
  sqrtf (d);
}
Comment 3 Jakub Jelinek 2013-08-15 12:43:34 UTC
Created attachment 30661 [details]
gcc49-pr58165.patch

Untested fix.
Comment 4 Alexander Ivchenko 2013-08-15 12:49:23 UTC
I firstly did something like that:

diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c
index 9b6186e..5862ebf 100644
--- a/gcc/tree-call-cdce.c
+++ b/gcc/tree-call-cdce.c
@@ -771,6 +771,9 @@ shrink_wrap_one_built_in_call (gimple bi_call)
   join_tgt_in_edge_fall_thru = make_edge (guard_bb0, join_tgt_bb,
                                           EDGE_FALSE_VALUE);

+  if (!gimple_call_nothrow_p (bi_call))
+    make_eh_edges (bi_call);
+
   bi_call_in_edge0->probability = REG_BR_PROB_BASE * ERR_PROB;
   bi_call_in_edge0->count =
       apply_probability (guard_bb0->count,

which also helped.. but now I see that we shouldn't split the block
Comment 5 Jakub Jelinek 2013-08-15 12:56:32 UTC
(In reply to Alexander Ivchenko from comment #4)
> I firstly did something like that:
> 
> diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c
> index 9b6186e..5862ebf 100644
> --- a/gcc/tree-call-cdce.c
> +++ b/gcc/tree-call-cdce.c
> @@ -771,6 +771,9 @@ shrink_wrap_one_built_in_call (gimple bi_call)
>    join_tgt_in_edge_fall_thru = make_edge (guard_bb0, join_tgt_bb,
>                                            EDGE_FALSE_VALUE);
> 
> +  if (!gimple_call_nothrow_p (bi_call))
> +    make_eh_edges (bi_call);
> +
>    bi_call_in_edge0->probability = REG_BR_PROB_BASE * ERR_PROB;
>    bi_call_in_edge0->count =
>        apply_probability (guard_bb0->count,
> 
> which also helped.. but now I see that we shouldn't split the block

Well, that wouldn't be sufficient, you'd need to also remove the EH edges from the other bb.  But not splitting the block means you don't have to bother with that.  Though, thinking about it again, my patch might be problematic for -fcompare-debug, because we could be not splitting without -g and for -g if a call is followed by some debug stmts, we could be splitting.

So, I need to use stmt_ends_bb_p instead.
Comment 6 Jakub Jelinek 2013-08-15 12:57:52 UTC
Created attachment 30662 [details]
gcc49-pr58165.patch

Updated patch.
Comment 7 Alexander Ivchenko 2013-08-15 13:30:33 UTC
> Well, that wouldn't be sufficient, you'd need to also remove the EH edges
> from the other bb.  But not splitting the block means you don't have to
> bother with that. 

Well, that's true. We could do that and not give up on cdce, but I guess there is no much profit in that..


Your fix works for me and the initial issue with bullet lib is also cured (and reduced testcase shows the problem as well). Thanks =)
Comment 8 Jakub Jelinek 2013-08-16 13:19:21 UTC
Author: jakub
Date: Fri Aug 16 08:57:29 2013
New Revision: 201780

URL: http://gcc.gnu.org/viewcvs?rev=201780&root=gcc&view=rev
Log:
	PR tree-optimization/58165
	* tree-call-cdce.c (shrink_wrap_one_built_in_call): If
	bi_call must be the last stmt in a bb, don't split_block, instead
	use fallthru edge from it and give up if there is none.
	Release conds vector when returning early.

	* g++.dg/opt/pr58165.C: New test.

Added:
    trunk/gcc/testsuite/g++.dg/opt/pr58165.C
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/tree-call-cdce.c

Author: jakub
Date: Fri Aug 16 09:04:52 2013
New Revision: 201781

URL: http://gcc.gnu.org/viewcvs?rev=201781&root=gcc&view=rev
Log:
	PR tree-optimization/58165
	* tree-call-cdce.c (shrink_wrap_one_built_in_call): If
	bi_call must be the last stmt in a bb, don't split_block, instead
	use fallthru edge from it and give up if there is none.
	Release conds vector when returning early.

	* g++.dg/opt/pr58165.C: New test.

Added:
    branches/gcc-4_8-branch/gcc/testsuite/g++.dg/opt/pr58165.C
Modified:
    branches/gcc-4_8-branch/gcc/ChangeLog
    branches/gcc-4_8-branch/gcc/testsuite/ChangeLog
    branches/gcc-4_8-branch/gcc/tree-call-cdce.c