Commit 021921d0 by Richard Kenner Committed by Richard Kenner

sibcall.c (optimize_sibling_and_tail_recursive_call): Compare against last real…

sibcall.c (optimize_sibling_and_tail_recursive_call): Compare against last real insn in basic block.

	* sibcall.c (optimize_sibling_and_tail_recursive_call): Compare
	against last real insn in basic block.
	Rework to avoid gotos.

From-SVN: r39858
parent fb0c0a12
Sun Feb 18 15:45:17 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu> Sun Feb 18 15:45:17 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* sibcall.c (optimize_sibling_and_tail_recursive_call): Compare
against last real insn in basic block.
Rework to avoid gotos.
* Makefile.in (gcse.o): Now includes ggc.h. * Makefile.in (gcse.o): Now includes ggc.h.
* gcse.c: Include ggc.h. * gcse.c: Include ggc.h.
(want_to_gcse_p): Verify expression can be in SET as valid insn. (want_to_gcse_p): Verify expression can be in SET as valid insn.
......
...@@ -533,20 +533,18 @@ optimize_sibling_and_tail_recursive_calls () ...@@ -533,20 +533,18 @@ optimize_sibling_and_tail_recursive_calls ()
{ {
int sibcall = (XEXP (PATTERN (insn), 1) != NULL_RTX); int sibcall = (XEXP (PATTERN (insn), 1) != NULL_RTX);
int tailrecursion = (XEXP (PATTERN (insn), 2) != NULL_RTX); int tailrecursion = (XEXP (PATTERN (insn), 2) != NULL_RTX);
basic_block succ_block, call_block; basic_block call_block;
rtx temp, hardret, softret; rtx end, temp, hardret, softret;
/* We must be careful with stack slots which are live at /* We must be careful with stack slots which are live at
potential optimization sites. potential optimization sites.
?!? This test is overly conservative and will be replaced. */ ?!? This test is overly conservative and will be replaced. */
if (frame_offset) if (frame_offset
goto failure; /* Taking the address of a local variable is fatal to tail
recursion if the address is used by the recursive call. */
/* Taking the address of a local variable is fatal to tail || current_function_uses_addressof)
recursion if the address is used by the recursive call. */ sibcall = 0, tailrecursion = 0;
if (current_function_uses_addressof)
goto failure;
/* alloca (until we have stack slot life analysis) inhibits /* alloca (until we have stack slot life analysis) inhibits
sibling call optimizations, but not tail recursion. sibling call optimizations, but not tail recursion.
...@@ -556,73 +554,57 @@ optimize_sibling_and_tail_recursive_calls () ...@@ -556,73 +554,57 @@ optimize_sibling_and_tail_recursive_calls ()
|| current_function_varargs || current_function_stdarg) || current_function_varargs || current_function_stdarg)
sibcall = 0; sibcall = 0;
/* Get the block for the call and the last non-note insn in it. We
take advantage of the fact that this cannot be the exit block. */
call_block = BLOCK_FOR_INSN (insn); call_block = BLOCK_FOR_INSN (insn);
end = prev_nonnote_insn (NEXT_INSN (call_block->end));
/* If the block has more than one successor, then we can not /* If the block has more than one successor, then we can not
perform sibcall or tail recursion optimizations. */ perform sibcall or tail recursion optimizations. If the single
successor is not the exit block, then we can not perform sibcall
or tail recursion optimizations. Note that these two tests
combined are sufficient to prevent tail call optimization in the
presense of active exception handlers. */
if (call_block->succ == NULL if (call_block->succ == NULL
|| call_block->succ->succ_next != NULL) || call_block->succ->succ_next != NULL
goto failure; || (call_block->succ->dest != EXIT_BLOCK_PTR
&& call_block->succ->dest != alternate_exit))
/* If the single successor is not the exit block, then we can not sibcall = 0, tailrecursion = 0;
perform sibcall or tail recursion optimizations.
/* If we haven't failed yet, check if this (or safe things) ends our
Note that this test combined with the previous is sufficient block. */
to prevent tail call optimization in the presense of active if ((sibcall || tailrecursion)
exception handlers. */ /* If the call was the end of the block, then we're OK. */
succ_block = call_block->succ->dest; && (end == (temp = insn)
if (succ_block != EXIT_BLOCK_PTR && succ_block != alternate_exit) /* Skip over copying from the call's return value pseudo into
goto failure; this function's hard return register and if that's the end
of the block, we're OK. */
/* If the call was the end of the block, then we're OK. */ || (identify_call_return_value (PATTERN (insn), &hardret,
temp = insn; &softret)
if (temp == call_block->end) && end == (temp = skip_copy_to_return_value (insn,
goto success; hardret,
softret)))
/* Skip over copying from the call's return value pseudo into /* Skip any stack adjustment. */
this function's hard return register. */ || end == (temp = skip_stack_adjustment (temp))
if (identify_call_return_value (PATTERN (insn), &hardret, &softret)) /* Skip over a CLOBBER of the return value as a hard reg. */
{ || end == (temp = skip_use_of_return_value (temp, CLOBBER))
temp = skip_copy_to_return_value (temp, hardret, softret); /* Skip over a USE of the return value (as a hard reg). */
if (temp == call_block->end) || end == (temp = skip_use_of_return_value (temp, USE))
goto success; /* Skip over the JUMP_INSN at the end of the block. */
} || end == (temp = skip_jump_insn (temp))))
;
/* Skip any stack adjustment. */ else
temp = skip_stack_adjustment (temp); /* There are operations at the end of the block which we must
if (temp == call_block->end) execute after returning from the function call. So this call
goto success; can not be optimized. */
sibcall = 0, tailrecursion = 0;
/* Skip over a CLOBBER of the return value (as a hard reg). */
temp = skip_use_of_return_value (temp, CLOBBER);
if (temp == call_block->end)
goto success;
/* Skip over a USE of the return value (as a hard reg). */
temp = skip_use_of_return_value (temp, USE);
if (temp == call_block->end)
goto success;
/* Skip over the JUMP_INSN at the end of the block. */
temp = skip_jump_insn (temp);
if (GET_CODE (temp) == NOTE)
temp = next_nonnote_insn (temp);
if (temp == call_block->end)
goto success;
/* There are operations at the end of the block which we must
execute after returning from the function call. So this call
can not be optimized. */
failure:
sibcall = 0, tailrecursion = 0;
success:
/* Select a set of insns to implement the call and emit them. /* Select a set of insns to implement the call and emit them.
Tail recursion is the most efficient, so select it over Tail recursion is the most efficient, so select it over
a tail/sibling call. */ a tail/sibling call. */
if (sibcall) if (sibcall)
successful_sibling_call = 1; successful_sibling_call = 1;
replaced_call_placeholder = 1; replaced_call_placeholder = 1;
replace_call_placeholder (insn, replace_call_placeholder (insn,
tailrecursion != 0 tailrecursion != 0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment