This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] C++ space optimization: omit EH info for thunks


On Monday, Aug 19, 2002, at 15:53 US/Pacific, Richard Henderson wrote:

On Fri, Aug 16, 2002 at 03:53:42PM -0700, Stuart Hastings wrote:
/* Don't emit EH unwind info for leaf functions that don't need it. */
- if (!flag_asynchronous_unwind_tables && for_eh && fde->nothrow
- && ! fde->uses_eh_lsda)
+ if (!flag_asynchronous_unwind_tables && for_eh &&
+ (fde->all_throwers_are_sibcalls || (fde->nothrow && ! fde->uses_eh_lsda)))
continue;
This is incorrect.  You want:

	if (!flag_asynchronous_unwind_tables && for_eh
	    && (fde->nothrow || fde->all_throwers_are_sibcalls)
	    && !fde->uses_eh_lsda)

Just because a function doesn't throw doesn't mean it doesn't
handle exceptions.  For instance, given

	void foo()
	{
	  try
	    bar();
	  catch (...)
	    ;
	}

both nothrow and all_throwers_are_sibcalls are true, since
can_throw_external is false for the call to bar.
Actually, the catch try/catch block is implemented with some CALL_INSNS that aren't sibcalled, so the existing code would emit EH info for your example.

However, your version seems more robust, so I've changed my sources to match.

However, uses_eh_lsda will be true since we need to catch the exception.

for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (can_throw_external (insn))
! {
! current_function_nothrow = 0;
! cfun->all_throwers_are_sibcalls &= (GET_CODE (insn) == CALL_INSN && SIBLING_CALL_P (insn));
! /* If the current function has a possible thrower that isn't a sibcall, we're done. */
! if (!cfun->all_throwers_are_sibcalls)
! return;
This is incorrect.

You're clearing leaving all_throwers_are_sibcalls set when CALL_INSN is false.
I'm sorry, I don't understand this statement.

Something that cannot happen with C++
by default, but does happen with Java or with -fnon-call-exceptions.

In any case, I'd rather see this written:

	if (GET_CODE (insn) == CALL_INSN && !SIBLING_CALL_P (insn))
	  {
	    cfun->all_throwers_are_sibcalls = 0;
	    return;
	  }
You seem to be suggesting a more aggressive approach. My previous version would abandon the optimization when it encountered any insn that could throw. The whole idea was to recognize that a CALL_INSN marked SIBLING_CALL_P can't.

Yours appears to ignore any instruction that isn't a CALL_INSN. For example, given a thunk with one sibcall-optimized CALL_INSN, if a load instruction was marked as "can_throw_exception()", my version would abandon the optimization and emit EH info as usual, and yours appears to sustain the optimization and omit the EH info. If this is intentional, I'd be happy to include it in my next submission; I just wanted to be sure I understood it first.

Perhaps you meant

for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (can_throw_external (insn))
{
current_function_nothrow = 0;

if (GET_CODE (insn) != CALL_INSN || !SIBLING_CALL_P (insn))
{
cfun->all_throwers_are_sibcalls = 0;
return;
}
}

Or perhaps this is more comprehensible (?):

for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
if (can_throw_external (insn))
{
current_function_nothrow = 0;

if (GET_CODE (insn) == CALL_INSN && SIBLING_CALL_P (insn))
;
else
{
cfun->all_throwers_are_sibcalls = 0;
return;
}
}


stuart hastings
Apple Computer


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]