This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: x86 sibling call stuff
On Sun, Mar 19, 2000 at 05:05:43PM -0800, Mark Mitchell wrote:
> I've attached a reduced
> test-case, together with a minor modification to the C++ front-end
> that makes for more consistent handling of TARGET_EXPRs through
> UNSAVEs -- but I'm not sure whether that change is necessary or
> correct, yet.
Thanks. The smaller test case is easier to work with. And the patch
appears to fix what I'd been stumbling over.
> o Both attempts to call `f' (the sibling call version, and
> non-sibling call version) register a cleanup (namely the
> destruction of `A'. (This cleanup is to be run either when
> an exception occurs, or when the call completes normally.)
Yes.
>
> o We only expand the cleanups after the call to `g', i.e., well
> out of the range of the sibling call machinery.
Yes.
> Note that there are two calls to the destructor there (_._1A). That's
> all straight-line code, so it's going to be running the destructor
> twice.
Yes, I'd noticed that was going to happen during the previous
debugging session, but was getting hung up on the reexpansion problem.
> If I'm right, the sibling call stuff is going to take some extra work
> in order to work right with exceptions: you're going to have to
> unregister the cleanups registered during the proto-call, or
> something.
Yes, and that appears quite trivial. Please scrutinize the following.
I've started x86 and alpha bootstraps; I'll check back after dinner.
r~
* calls.c (expand_call): Don't bother generating tail call
sequences if there are pending cleanups. Use
expand_start_target_temps/expand_end_target_temps to elide
cleanups created during sibcall expansion.
Index: calls.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/calls.c,v
retrieving revision 1.97
diff -c -p -d -r1.97 calls.c
*** calls.c 2000/03/17 22:40:43 1.97
--- calls.c 2000/03/20 02:10:55
*************** expand_call (exp, target, ignore)
*** 2020,2026 ****
safe_for_reeval = 0;
if (optimize >= 2
&& currently_expanding_call == 1
! && stmt_loop_nest_empty ())
{
/* Verify that each argument is safe for re-evaluation. */
for (p = actparms; p; p = TREE_CHAIN (p))
--- 2020,2027 ----
safe_for_reeval = 0;
if (optimize >= 2
&& currently_expanding_call == 1
! && stmt_loop_nest_empty ()
! && ! any_pending_cleanups (1))
{
/* Verify that each argument is safe for re-evaluation. */
for (p = actparms; p; p = TREE_CHAIN (p))
*************** expand_call (exp, target, ignore)
*** 2152,2157 ****
--- 2153,2164 ----
|| ! FUNCTION_OK_FOR_SIBCALL (fndecl))
continue;
+ /* We know at this point that there are not currently any
+ pending cleanups. If, however, in the process of evaluating
+ the arguments we were to create some, we'll need to be
+ able to get rid of them. */
+ expand_start_target_temps ();
+
/* State variables we need to save and restore between
iterations. */
save_pending_stack_adjust = pending_stack_adjust;
*************** expand_call (exp, target, ignore)
*** 2924,2929 ****
--- 2931,2944 ----
for (i = 0; i < num_actuals; ++i)
if (args[i].aligned_regs)
free (args[i].aligned_regs);
+
+ if (pass == 0)
+ {
+ /* Undo the fake expand_start_target_temps we did earlier. If
+ there had been any cleanups created, we've already set
+ sibcall_failure. */
+ expand_end_target_temps ();
+ }
insns = get_insns ();
end_sequence ();