This is the mail archive of the
mailing list for the GCC project.
Re: can_throw_internal affected by inlining?
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: Richard Henderson <rth at redhat dot com>
- Cc: jh at suse dot cz, gcc at gcc dot gnu dot org
- Date: Sat, 11 Jul 2009 14:59:30 +0200
- Subject: Re: can_throw_internal affected by inlining?
- References: <4A57C772.email@example.com>
> Re: http://gcc.gnu.org/ml/gcc-patches/2009-03/msg01404.html
> Do you have test cases for this?
> Changing can_throw_internal/external to depend on whether or not future
> inlining is possible looks *very* wrong to me. Surely the only thing
> that matters for new code that might appear "below" this position in the
> tree is whether or not it might throw, and the only thing that changes
> with inlining is increased knowledge of whether and how it throws.
The problem here is fact that MUST_NOT_THROW region reachable only via
runtime is handled completely via runtime, however MUST_NOT_THROW region
reachable via RESX is eventually going to be handled by direct
std::terminate call, since RESX will eventually get translated as direct
goto to the MIST_NOT_THROW reciever.
When compiling, C++ frontend first produce MUST_NOT_THROW receivers
doing direct call and those are left in code till they are renered
unreachable and removed by cleanup_cfg.
This decision do depend on inlining - when you call function with
externally throwing RESX in MUST_NOT_THROW region, you don't need
std::terminate() call since runtime will handle it. After you inline it,
you must have the std::terminate() call. We got this wrong on old tree
removing the receivers and sometimes incorrectly optimizing out
MUST_NOT_THROW wrappers. One can construct testcase with inlined
destructor in cleanup that have externally throwing resx that won't
result in terminate call afterwards, but will silently continue
unwinding form the cleanup.
So I am delaying removal of those receiver after inlining decisions are
fixed, but because these regions tends to be very numberous and tends to
consume a lot of memory, I also added the logic to remove them early
when it is known that they are not needed.
> The only thing I can imagine is that somehow an inline function was
> incorrectly marked as nothrow, and then it was inlined exposing the
> throw (i.e. resx) which then led the problem you report.
> On the trans-mem branch this is causing me problems. I'm replacing a
> direct function call with an indirect function call. Neither can be
> inlined, but inlinable_call_p thinks that it's a possibility for the
> indirect function call. With your logic, this magically changes a
> statement from !can_throw_internal to can_throw_internal. Which then of
> course results in a verify_cfg abort.
Well, we can either teach inlinable_call_p to handle your new indirect
calls as "for sure uninlinable", make it conservative and consider all
calls inlinable or we can stop doing the early removal of MUST_NOT_THROW
receivers. I also added logic to inliner heuristics to prevent those
from increasing estimated function bodies, so it should affect mostly
memory usage and compile time, I can re-test that.