sibcall.c (uses_addressof): Accept both addressof and current_function_internal_arg_pointer inside a mem.
* 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. From-SVN: r35657
This commit is contained in:
parent
3ac597cb9a
commit
055bcfeeda
3 changed files with 25 additions and 100 deletions
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
79
gcc/stmt.c
79
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
|
||||
|
|
Loading…
Add table
Reference in a new issue