This is the mail archive of the gcc-bugs@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]

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 ();

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