diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 92498dc0ba3..ef257fe82bf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,8 +1,3 @@ -Thu Jan 7 19:52:53 1999 Gerald Pfeifer - - * system.h (abort): Supply more detailed information on how to - report an Internal Compiler Error. - Fri Jan 8 10:51:13 1999 Andreas Schwab * config/m68k/m68k.h: Declare output_function_epilogue. @@ -10,9 +5,18 @@ Fri Jan 8 10:51:13 1999 Andreas Schwab Fri Jan 8 01:43:53 1999 Jeffrey A Law (law@cygnus.com) + * stmt.c (optimize_tail_recursion): New function, extracted from ... + (expand_return): Use optimize_tail_recursion. + * tree.h (optimize_tail_recursion): Declare. + * toplev.c (compile_file): Move call to output_func_start_profiler to after the loop to emit deferred functions. +Thu Jan 7 19:52:53 1999 Gerald Pfeifer + + * system.h (abort): Supply more detailed information on how to + report an Internal Compiler Error. + Thu Jan 7 11:26:17 1999 Mark Mitchell * calls.c (store_unaligned_arguments_into_pseudos): Use xmalloc to diff --git a/gcc/stmt.c b/gcc/stmt.c index 7a8a6571305..4f2e911dfbc 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -1,5 +1,5 @@ /* Expands front end tree to back end RTL for GNU C-Compiler - Copyright (C) 1987, 88, 89, 92-97, 1998 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc. This file is part of GNU CC. @@ -2564,32 +2564,9 @@ expand_return (retval) return; } - /* For tail-recursive call to current function, - just jump back to the beginning. - It's unsafe if any auto variable in this function - has its address taken; for simplicity, - require stack frame to be empty. */ - if (optimize && retval_rhs != 0 - && frame_offset == 0 - && TREE_CODE (retval_rhs) == CALL_EXPR - && TREE_CODE (TREE_OPERAND (retval_rhs, 0)) == ADDR_EXPR - && TREE_OPERAND (TREE_OPERAND (retval_rhs, 0), 0) == current_function_decl - /* Finish checking validity, and if valid emit code - to set the argument variables for the new call. */ - && tail_recursion_args (TREE_OPERAND (retval_rhs, 1), - DECL_ARGUMENTS (current_function_decl))) - { - if (tail_recursion_label == 0) - { - tail_recursion_label = gen_label_rtx (); - emit_label_after (tail_recursion_label, - tail_recursion_reentry); - } - emit_queue (); - expand_goto_internal (NULL_TREE, tail_recursion_label, last_insn); - emit_barrier (); - return; - } + /* Attempt to optimize the call if it is tail recursive. */ + optimize_tail_recursion (retval_rhs, last_insn); + #ifdef HAVE_return /* This optimization is safe if there are local cleanups because expand_null_return takes care of them. @@ -2794,6 +2771,45 @@ drop_through_at_end_p () return insn && GET_CODE (insn) != BARRIER; } +/* Test CALL_EXPR to determine if it is a potential tail recursion call + and emit code to optimize the tail recursion. LAST_INSN indicates where + to place the jump to the tail recursion label. + + This is only used by expand_return, but expand_call is expected to + use it soon. */ + +void +optimize_tail_recursion (call_expr, last_insn) + tree call_expr; + rtx last_insn; +{ + /* For tail-recursive call to current function, + just jump back to the beginning. + It's unsafe if any auto variable in this function + has its address taken; for simplicity, + require stack frame to be empty. */ + if (optimize && call_expr != 0 + && frame_offset == 0 + && TREE_CODE (call_expr) == CALL_EXPR + && TREE_CODE (TREE_OPERAND (call_expr, 0)) == ADDR_EXPR + && TREE_OPERAND (TREE_OPERAND (call_expr, 0), 0) == current_function_decl + /* Finish checking validity, and if valid emit code + to set the argument variables for the new call. */ + && tail_recursion_args (TREE_OPERAND (call_expr, 1), + DECL_ARGUMENTS (current_function_decl))) + { + if (tail_recursion_label == 0) + { + tail_recursion_label = gen_label_rtx (); + emit_label_after (tail_recursion_label, + tail_recursion_reentry); + } + emit_queue (); + expand_goto_internal (NULL_TREE, tail_recursion_label, last_insn); + emit_barrier (); + } +} + /* Emit code to alter this function's formal parms for a tail-recursive call. ACTUALS is a list of actual parameter expressions (chain of TREE_LISTs). FORMALS is the chain of decls of formals. diff --git a/gcc/tree.h b/gcc/tree.h index 895cf2a1b4a..cf3ec9dc368 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -1,5 +1,5 @@ /* Front-end tree definitions for GNU compiler. - Copyright (C) 1989, 93, 94, 95, 96, 97, 1998 Free Software Foundation, Inc. + Copyright (C) 1989, 93-98, 1999 Free Software Foundation, Inc. This file is part of GNU CC. @@ -1930,6 +1930,7 @@ extern int expand_exit_something PROTO((void)); extern void expand_null_return PROTO((void)); extern void expand_return PROTO((tree)); +extern void optimize_tail_recursion PROTO((tree, struct rtx_def *)); extern void expand_start_bindings PROTO((int)); extern void expand_end_bindings PROTO((tree, int, int)); extern void start_cleanup_deferral PROTO((void));