diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ac510fa620e4414a15e1aeccaaec8ed1c918bab2..402fe228aecf57395f23d2a8c4ac4b125f5fe362 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2000-08-12 Richard Henderson <rth@cygnus.com> + + * sibcall.c (uses_addressof): Accept both addressof and + current_function_internal_arg_pointer inside a mem. + (optimize_sibling_and_tail_recursive_call): Fail tail recursion + if current_function_uses_addressof. + * stmt.c (expand_return): Kill tail recursion and HAVE_return + optimizations. + 2000-08-11 Richard Henderson <rth@cygnus.com> * config/ia64/ia64.md (addsi3): Remove expander. diff --git a/gcc/sibcall.c b/gcc/sibcall.c index 78e855eef78d6e859869f0037e68ccbea5be01dd..42a9d70fb815a3ef35a8e1e40b3a76f643022672 100644 --- a/gcc/sibcall.c +++ b/gcc/sibcall.c @@ -37,7 +37,7 @@ static rtx skip_copy_to_return_value PARAMS ((rtx, rtx, rtx)); static rtx skip_use_of_return_value PARAMS ((rtx, enum rtx_code)); static rtx skip_stack_adjustment PARAMS ((rtx)); static rtx skip_jump_insn PARAMS ((rtx)); -static int uses_addressof PARAMS ((rtx, int)); +static int uses_addressof PARAMS ((rtx)); static int sequence_uses_addressof PARAMS ((rtx)); static void purge_reg_equiv_notes PARAMS ((void)); @@ -237,16 +237,12 @@ skip_jump_insn (orig_insn) /* Scan the rtx X for ADDRESSOF expressions or current_function_internal_arg_pointer registers. - INMEM argument should be 1 if we're looking at inner part of some - MEM expression, otherwise 0. - Return nonzero if an ADDRESSOF expresion is found or if - current_function_internal_arg_pointer is found outside of some MEM - expression, else return zero. */ + Return nonzero if an ADDRESSOF or current_function_internal_arg_pointer + is found outside of some MEM expression, else return zero. */ static int -uses_addressof (x, inmem) +uses_addressof (x) rtx x; - int inmem; { RTX_CODE code; int i, j; @@ -257,14 +253,11 @@ uses_addressof (x, inmem) code = GET_CODE (x); - if (code == ADDRESSOF) - return 1; - - if (x == current_function_internal_arg_pointer && ! inmem) + if (code == ADDRESSOF || x == current_function_internal_arg_pointer) return 1; if (code == MEM) - return uses_addressof (XEXP (x, 0), 1); + return 0; /* Scan all subexpressions. */ fmt = GET_RTX_FORMAT (code); @@ -272,13 +265,13 @@ uses_addressof (x, inmem) { if (*fmt == 'e') { - if (uses_addressof (XEXP (x, i), inmem)) + if (uses_addressof (XEXP (x, i))) return 1; } else if (*fmt == 'E') { for (j = 0; j < XVECLEN (x, i); j++) - if (uses_addressof (XVECEXP (x, i, j), inmem)) + if (uses_addressof (XVECEXP (x, i, j))) return 1; } } @@ -318,8 +311,8 @@ sequence_uses_addressof (seq) && sequence_uses_addressof (XEXP (PATTERN (insn), 2))) return 1; } - else if (uses_addressof (PATTERN (insn), 0) - || (REG_NOTES (insn) && uses_addressof (REG_NOTES (insn), 0))) + else if (uses_addressof (PATTERN (insn)) + || (REG_NOTES (insn) && uses_addressof (REG_NOTES (insn)))) return 1; } return 0; @@ -490,14 +483,16 @@ optimize_sibling_and_tail_recursive_calls () 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. */ + if (current_function_uses_addressof) + goto failure; + /* alloca (until we have stack slot life analysis) inhibits sibling call optimizations, but not tail recursion. - - Similarly if we have ADDRESSOF expressions. - Similarly if we use varargs or stdarg since they implicitly may take the address of an argument. */ - if (current_function_calls_alloca || current_function_uses_addressof + if (current_function_calls_alloca || current_function_varargs || current_function_stdarg) sibcall = 0; diff --git a/gcc/stmt.c b/gcc/stmt.c index 47431f6471eb3ca6ccff6a1dfe4b81ae4b9d1803..38572ca6fe86eb8ffe25dcccaf0dfd6891741017 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -2809,9 +2809,6 @@ expand_return (retval) rtx last_insn = 0; rtx result_rtl = DECL_RTL (DECL_RESULT (current_function_decl)); register rtx val = 0; -#ifdef HAVE_return - register rtx op0; -#endif tree retval_rhs; int cleanups; @@ -2885,82 +2882,6 @@ expand_return (retval) return; } - /* Attempt to optimize the call if it is tail recursive. */ - if (flag_optimize_sibling_calls - && retval_rhs != NULL_TREE - && 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) - && optimize_tail_recursion (TREE_OPERAND (retval_rhs, 1), last_insn)) - return; - -#ifdef HAVE_return - /* This optimization is safe if there are local cleanups - because expand_null_return takes care of them. - ??? I think it should also be safe when there is a cleanup label, - because expand_null_return takes care of them, too. - Any reason why not? */ - if (HAVE_return && cleanup_label == 0 - && ! current_function_returns_pcc_struct - && BRANCH_COST <= 1) - { - /* If this is return x == y; then generate - if (x == y) return 1; else return 0; - if we can do it with explicit return insns and branches are cheap, - but not if we have the corresponding scc insn. */ - int has_scc = 0; - if (retval_rhs) - switch (TREE_CODE (retval_rhs)) - { - case EQ_EXPR: -#ifdef HAVE_seq - has_scc = HAVE_seq; -#endif - case NE_EXPR: -#ifdef HAVE_sne - has_scc = HAVE_sne; -#endif - case GT_EXPR: -#ifdef HAVE_sgt - has_scc = HAVE_sgt; -#endif - case GE_EXPR: -#ifdef HAVE_sge - has_scc = HAVE_sge; -#endif - case LT_EXPR: -#ifdef HAVE_slt - has_scc = HAVE_slt; -#endif - case LE_EXPR: -#ifdef HAVE_sle - has_scc = HAVE_sle; -#endif - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - case TRUTH_AND_EXPR: - case TRUTH_OR_EXPR: - case TRUTH_NOT_EXPR: - case TRUTH_XOR_EXPR: - if (! has_scc) - { - op0 = gen_label_rtx (); - jumpifnot (retval_rhs, op0); - expand_value_return (const1_rtx); - emit_label (op0); - expand_value_return (const0_rtx); - return; - } - break; - - default: - break; - } - } -#endif /* HAVE_return */ - /* If the result is an aggregate that is being returned in one (or more) registers, load the registers here. The compiler currently can't handle copying a BLKmode value into registers. We could put this code in a