Commit cd921bcb authored by rth's avatar rth
Browse files

* 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.


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@35657 138bc75d-0d04-0410-961f-82ee72b054a4
parent 00608ffd
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.
......
......@@ -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;
......
......@@ -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
......
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