[Bug ipa/68470] [4.9/5/6 Regression] Internal Compiler Error observed by g++-4.9.2 and a few other versions (reported to Debian)
miyuki at gcc dot gnu.org
gcc-bugzilla@gcc.gnu.org
Sat Nov 21 23:35:00 GMT 2015
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68470
Mikhail Maltsev <miyuki at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |miyuki at gcc dot gnu.org
Component|middle-end |ipa
--- Comment #3 from Mikhail Maltsev <miyuki at gcc dot gnu.org> ---
A bit simplified testcase:
void deallocate(void *);
void *a;
struct C {
virtual void m_fn1();
};
struct D {
C *m_fn2() {
if (a)
__builtin_abort();
}
};
D getd();
struct vec_int {
int _M_start;
~vec_int() {
if (_M_start)
deallocate(&_M_start);
}
};
vec_int *b;
struct I {
virtual void m_fn3();
};
void I::m_fn3() {
if (a)
getd().m_fn2()->m_fn1();
b->~vec_int();
}
$ cc1plus -O2 test.cc - ICE after fnsplit
$ cc1plus -O2 test.cc -fno-checking - ICE in IPA-ICF (like in the original bug
report)
$ cc1plus -O2 test.cc -fno-devirtualize - OK
$ cc1plus -O2 test.cc --param partial-inlining-entry-probability=0 - OK
ISTM, this is some IPA-related issue:
D::m_fn2 and vec_int::~vec_int are inlined into I::m_fn3.
D::m_fn2 (D::operator-> in previous comments) does not return any value
(undefined behavior), so gimple_fold_call devirtualizes getd().m_fn2()->m_fn1()
into __builtin_unreachable during fwprop1.
fnsplit then tries to split I::m_fn3. This is how the function looks before
fnsplit:
;; Function virtual void I::m_fn3() (_ZN1I5m_fn3Ev, funcdef_no=4,
decl_uid=2299, cgraph_uid=4, symbol_order=6)
virtual void I::m_fn3() (struct I * const this)
{
struct C * D.2356;
void * a.0_3;
void * a.2_5;
struct vec_int * b.1_12;
int _14;
int * _15;
<bb 2>:
a.0_3 = a;
if (a.0_3 != 0B)
goto <bb 3>;
else
goto <bb 6>;
<bb 3>:
getd ();
a.2_5 = a;
if (a.2_5 != 0B)
goto <bb 4>;
else
goto <bb 5>;
<bb 4>:
__builtin_abort ();
<bb 5>:
__builtin_unreachable ();
<bb 6>:
b.1_12 = b;
_14 = b.1_12->_M_start;
if (_14 != 0)
goto <bb 7>;
else
goto <bb 8>;
<bb 7>:
_15 = &b.1_12->_M_start;
deallocate (_15);
<bb 8>:
MEM[(struct &)b.1_12] ={v} {CLOBBER};
return;
}
The splitting pass tries to do this:
Splitting function at:
Split point at BB 6
header time: 19646 header size: 10
split time: 2491 split size: 6
bbs: 6, 7
SSA names to pass:
Introduced new external node (void __builtin_unreachable()/18).
ICE probably happens in this part:
virtual void I::m_fn3() (struct I * const this)
{
struct C * D.2356;
void * a.0_3;
void * a.2_5;
<bb 2>:
a.0_3 = a;
if (a.0_3 != 0B)
goto <bb 3>;
else
goto <bb 6>;
<bb 3>:
getd ();
a.2_5 = a;
if (a.2_5 != 0B)
goto <bb 4>;
else
goto <bb 5>;
<bb 4>:
__builtin_abort ();
<bb 5>:
__builtin_unreachable ();
<bb 6>:
I::_ZN1I5m_fn3Ev.part.1 ();
MEM[(struct &)_12] ={v} {CLOBBER};
return;
}
More information about the Gcc-bugs
mailing list