------- Additional Comments From ebotcazou at gcc dot gnu dot org 2005-01-24 11:27 ------- Um... first of all, this works on 3.4 branch only by accident, i.e. I think the underlying problem is still present there. What happens is that a call has an argument containing a TARGET_EXPR with cleanups and is eligible for the sibling call optimization. The cleanups are expanded during the first pass but, since the optimization eventually fails, the RTL is thrown away. Then, during the second pass, the TARGET_EXPR is expanded again but not the cleanups because they are not registered (the variable 'cleanups' is NULL at expr.c:9050).
I'm not sure how this is supposed to work. Richard, do you have any recollection of this? In 2000(!), you commited this patch: Index: calls.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/calls.c,v retrieving revision 1.97 retrieving revision 1.98 diff -u -r1.97 -r1.98 --- calls.c 17 Mar 2000 22:40:43 -0000 1.97 +++ calls.c 20 Mar 2000 22:40:50 -0000 1.98 @@ -2020,7 +2020,8 @@ safe_for_reeval = 0; if (optimize >= 2 && currently_expanding_call == 1 - && stmt_loop_nest_empty ()) + && 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)) @@ -2152,6 +2153,12 @@ || ! 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; @@ -2925,6 +2932,14 @@ 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 (); which is responsible for expanding the cleanups right after the first pass. -- What |Removed |Added ---------------------------------------------------------------------------- CC| |rth at gcc dot gnu dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=15853