|
|
01e27f8 |
2000-08-12 Richard Henderson <rth@cygnus.com>
|
|
|
01e27f8 |
|
|
|
01e27f8 |
* sibcall.c (uses_addressof): Accept both addressof and
|
|
|
01e27f8 |
current_function_internal_arg_pointer inside a mem.
|
|
|
01e27f8 |
(optimize_sibling_and_tail_recursive_call): Fail tail recursion
|
|
|
01e27f8 |
if current_function_uses_addressof.
|
|
|
01e27f8 |
* stmt.c (expand_return): Kill tail recursion and HAVE_return
|
|
|
01e27f8 |
optimizations.
|
|
|
01e27f8 |
|
|
|
01e27f8 |
*** gcc/sibcall.c 2000/08/04 20:28:06 1.7
|
|
|
01e27f8 |
--- gcc/sibcall.c 2000/08/12 16:24:33
|
|
|
01e27f8 |
*************** static rtx skip_copy_to_return_value PAR
|
|
|
01e27f8 |
*** 37,43 ****
|
|
|
01e27f8 |
static rtx skip_use_of_return_value PARAMS ((rtx, enum rtx_code));
|
|
|
01e27f8 |
static rtx skip_stack_adjustment PARAMS ((rtx));
|
|
|
01e27f8 |
static rtx skip_jump_insn PARAMS ((rtx));
|
|
|
01e27f8 |
! static int uses_addressof PARAMS ((rtx, int));
|
|
|
01e27f8 |
static int sequence_uses_addressof PARAMS ((rtx));
|
|
|
01e27f8 |
static void purge_reg_equiv_notes PARAMS ((void));
|
|
|
01e27f8 |
|
|
|
01e27f8 |
--- 37,43 ----
|
|
|
01e27f8 |
static rtx skip_use_of_return_value PARAMS ((rtx, enum rtx_code));
|
|
|
01e27f8 |
static rtx skip_stack_adjustment PARAMS ((rtx));
|
|
|
01e27f8 |
static rtx skip_jump_insn PARAMS ((rtx));
|
|
|
01e27f8 |
! static int uses_addressof PARAMS ((rtx));
|
|
|
01e27f8 |
static int sequence_uses_addressof PARAMS ((rtx));
|
|
|
01e27f8 |
static void purge_reg_equiv_notes PARAMS ((void));
|
|
|
01e27f8 |
|
|
|
01e27f8 |
*************** skip_jump_insn (orig_insn)
|
|
|
01e27f8 |
*** 237,252 ****
|
|
|
01e27f8 |
|
|
|
01e27f8 |
/* Scan the rtx X for ADDRESSOF expressions or
|
|
|
01e27f8 |
current_function_internal_arg_pointer registers.
|
|
|
01e27f8 |
! INMEM argument should be 1 if we're looking at inner part of some
|
|
|
01e27f8 |
! MEM expression, otherwise 0.
|
|
|
01e27f8 |
! Return nonzero if an ADDRESSOF expresion is found or if
|
|
|
01e27f8 |
! current_function_internal_arg_pointer is found outside of some MEM
|
|
|
01e27f8 |
! expression, else return zero. */
|
|
|
01e27f8 |
|
|
|
01e27f8 |
static int
|
|
|
01e27f8 |
! uses_addressof (x, inmem)
|
|
|
01e27f8 |
rtx x;
|
|
|
01e27f8 |
- int inmem;
|
|
|
01e27f8 |
{
|
|
|
01e27f8 |
RTX_CODE code;
|
|
|
01e27f8 |
int i, j;
|
|
|
01e27f8 |
--- 237,248 ----
|
|
|
01e27f8 |
|
|
|
01e27f8 |
/* Scan the rtx X for ADDRESSOF expressions or
|
|
|
01e27f8 |
current_function_internal_arg_pointer registers.
|
|
|
01e27f8 |
! Return nonzero if an ADDRESSOF or current_function_internal_arg_pointer
|
|
|
01e27f8 |
! is found outside of some MEM expression, else return zero. */
|
|
|
01e27f8 |
|
|
|
01e27f8 |
static int
|
|
|
01e27f8 |
! uses_addressof (x)
|
|
|
01e27f8 |
rtx x;
|
|
|
01e27f8 |
{
|
|
|
01e27f8 |
RTX_CODE code;
|
|
|
01e27f8 |
int i, j;
|
|
|
01e27f8 |
*************** uses_addressof (x, inmem)
|
|
|
01e27f8 |
*** 256,270 ****
|
|
|
01e27f8 |
return 0;
|
|
|
01e27f8 |
|
|
|
01e27f8 |
code = GET_CODE (x);
|
|
|
01e27f8 |
-
|
|
|
01e27f8 |
- if (code == ADDRESSOF)
|
|
|
01e27f8 |
- return 1;
|
|
|
01e27f8 |
|
|
|
01e27f8 |
! if (x == current_function_internal_arg_pointer && ! inmem)
|
|
|
01e27f8 |
return 1;
|
|
|
01e27f8 |
|
|
|
01e27f8 |
if (code == MEM)
|
|
|
01e27f8 |
! return uses_addressof (XEXP (x, 0), 1);
|
|
|
01e27f8 |
|
|
|
01e27f8 |
/* Scan all subexpressions. */
|
|
|
01e27f8 |
fmt = GET_RTX_FORMAT (code);
|
|
|
01e27f8 |
--- 252,263 ----
|
|
|
01e27f8 |
return 0;
|
|
|
01e27f8 |
|
|
|
01e27f8 |
code = GET_CODE (x);
|
|
|
01e27f8 |
|
|
|
01e27f8 |
! if (code == ADDRESSOF || x == current_function_internal_arg_pointer)
|
|
|
01e27f8 |
return 1;
|
|
|
01e27f8 |
|
|
|
01e27f8 |
if (code == MEM)
|
|
|
01e27f8 |
! return 0;
|
|
|
01e27f8 |
|
|
|
01e27f8 |
/* Scan all subexpressions. */
|
|
|
01e27f8 |
fmt = GET_RTX_FORMAT (code);
|
|
|
01e27f8 |
*************** uses_addressof (x, inmem)
|
|
|
01e27f8 |
*** 272,284 ****
|
|
|
01e27f8 |
{
|
|
|
01e27f8 |
if (*fmt == 'e')
|
|
|
01e27f8 |
{
|
|
|
01e27f8 |
! if (uses_addressof (XEXP (x, i), inmem))
|
|
|
01e27f8 |
return 1;
|
|
|
01e27f8 |
}
|
|
|
01e27f8 |
else if (*fmt == 'E')
|
|
|
01e27f8 |
{
|
|
|
01e27f8 |
for (j = 0; j < XVECLEN (x, i); j++)
|
|
|
01e27f8 |
! if (uses_addressof (XVECEXP (x, i, j), inmem))
|
|
|
01e27f8 |
return 1;
|
|
|
01e27f8 |
}
|
|
|
01e27f8 |
}
|
|
|
01e27f8 |
--- 265,277 ----
|
|
|
01e27f8 |
{
|
|
|
01e27f8 |
if (*fmt == 'e')
|
|
|
01e27f8 |
{
|
|
|
01e27f8 |
! if (uses_addressof (XEXP (x, i)))
|
|
|
01e27f8 |
return 1;
|
|
|
01e27f8 |
}
|
|
|
01e27f8 |
else if (*fmt == 'E')
|
|
|
01e27f8 |
{
|
|
|
01e27f8 |
for (j = 0; j < XVECLEN (x, i); j++)
|
|
|
01e27f8 |
! if (uses_addressof (XVECEXP (x, i, j)))
|
|
|
01e27f8 |
return 1;
|
|
|
01e27f8 |
}
|
|
|
01e27f8 |
}
|
|
|
01e27f8 |
*************** sequence_uses_addressof (seq)
|
|
|
01e27f8 |
*** 318,325 ****
|
|
|
01e27f8 |
&& sequence_uses_addressof (XEXP (PATTERN (insn), 2)))
|
|
|
01e27f8 |
return 1;
|
|
|
01e27f8 |
}
|
|
|
01e27f8 |
! else if (uses_addressof (PATTERN (insn), 0)
|
|
|
01e27f8 |
! || (REG_NOTES (insn) && uses_addressof (REG_NOTES (insn), 0)))
|
|
|
01e27f8 |
return 1;
|
|
|
01e27f8 |
}
|
|
|
01e27f8 |
return 0;
|
|
|
01e27f8 |
--- 311,318 ----
|
|
|
01e27f8 |
&& sequence_uses_addressof (XEXP (PATTERN (insn), 2)))
|
|
|
01e27f8 |
return 1;
|
|
|
01e27f8 |
}
|
|
|
01e27f8 |
! else if (uses_addressof (PATTERN (insn))
|
|
|
01e27f8 |
! || (REG_NOTES (insn) && uses_addressof (REG_NOTES (insn))))
|
|
|
01e27f8 |
return 1;
|
|
|
01e27f8 |
}
|
|
|
01e27f8 |
return 0;
|
|
|
01e27f8 |
*************** optimize_sibling_and_tail_recursive_call
|
|
|
01e27f8 |
*** 490,503 ****
|
|
|
01e27f8 |
if (frame_offset)
|
|
|
01e27f8 |
goto failure;
|
|
|
01e27f8 |
|
|
|
01e27f8 |
/* alloca (until we have stack slot life analysis) inhibits
|
|
|
01e27f8 |
sibling call optimizations, but not tail recursion.
|
|
|
01e27f8 |
-
|
|
|
01e27f8 |
- Similarly if we have ADDRESSOF expressions.
|
|
|
01e27f8 |
-
|
|
|
01e27f8 |
Similarly if we use varargs or stdarg since they implicitly
|
|
|
01e27f8 |
may take the address of an argument. */
|
|
|
01e27f8 |
! if (current_function_calls_alloca || current_function_uses_addressof
|
|
|
01e27f8 |
|| current_function_varargs || current_function_stdarg)
|
|
|
01e27f8 |
sibcall = 0;
|
|
|
01e27f8 |
|
|
|
01e27f8 |
--- 483,498 ----
|
|
|
01e27f8 |
if (frame_offset)
|
|
|
01e27f8 |
goto failure;
|
|
|
01e27f8 |
|
|
|
01e27f8 |
+ /* Taking the address of a local variable is fatal to tail
|
|
|
01e27f8 |
+ recursion if the address is used by the recursive call. */
|
|
|
01e27f8 |
+ if (current_function_uses_addressof)
|
|
|
01e27f8 |
+ goto failure;
|
|
|
01e27f8 |
+
|
|
|
01e27f8 |
/* alloca (until we have stack slot life analysis) inhibits
|
|
|
01e27f8 |
sibling call optimizations, but not tail recursion.
|
|
|
01e27f8 |
Similarly if we use varargs or stdarg since they implicitly
|
|
|
01e27f8 |
may take the address of an argument. */
|
|
|
01e27f8 |
! if (current_function_calls_alloca
|
|
|
01e27f8 |
|| current_function_varargs || current_function_stdarg)
|
|
|
01e27f8 |
sibcall = 0;
|
|
|
01e27f8 |
|
|
|
01e27f8 |
*** gcc/stmt.c 2000/08/06 10:07:30 1.156
|
|
|
01e27f8 |
--- gcc/stmt.c 2000/08/12 16:24:33
|
|
|
01e27f8 |
*************** expand_return (retval)
|
|
|
01e27f8 |
*** 2809,2817 ****
|
|
|
01e27f8 |
rtx last_insn = 0;
|
|
|
01e27f8 |
rtx result_rtl = DECL_RTL (DECL_RESULT (current_function_decl));
|
|
|
01e27f8 |
register rtx val = 0;
|
|
|
01e27f8 |
- #ifdef HAVE_return
|
|
|
01e27f8 |
- register rtx op0;
|
|
|
01e27f8 |
- #endif
|
|
|
01e27f8 |
tree retval_rhs;
|
|
|
01e27f8 |
int cleanups;
|
|
|
01e27f8 |
|
|
|
01e27f8 |
--- 2809,2814 ----
|
|
|
01e27f8 |
*************** expand_return (retval)
|
|
|
01e27f8 |
*** 2884,2965 ****
|
|
|
01e27f8 |
end_cleanup_deferral ();
|
|
|
01e27f8 |
return;
|
|
|
01e27f8 |
}
|
|
|
01e27f8 |
-
|
|
|
01e27f8 |
- /* Attempt to optimize the call if it is tail recursive. */
|
|
|
01e27f8 |
- if (flag_optimize_sibling_calls
|
|
|
01e27f8 |
- && retval_rhs != NULL_TREE
|
|
|
01e27f8 |
- && frame_offset == 0
|
|
|
01e27f8 |
- && TREE_CODE (retval_rhs) == CALL_EXPR
|
|
|
01e27f8 |
- && TREE_CODE (TREE_OPERAND (retval_rhs, 0)) == ADDR_EXPR
|
|
|
01e27f8 |
- && (TREE_OPERAND (TREE_OPERAND (retval_rhs, 0), 0)
|
|
|
01e27f8 |
- == current_function_decl)
|
|
|
01e27f8 |
- && optimize_tail_recursion (TREE_OPERAND (retval_rhs, 1), last_insn))
|
|
|
01e27f8 |
- return;
|
|
|
01e27f8 |
-
|
|
|
01e27f8 |
- #ifdef HAVE_return
|
|
|
01e27f8 |
- /* This optimization is safe if there are local cleanups
|
|
|
01e27f8 |
- because expand_null_return takes care of them.
|
|
|
01e27f8 |
- ??? I think it should also be safe when there is a cleanup label,
|
|
|
01e27f8 |
- because expand_null_return takes care of them, too.
|
|
|
01e27f8 |
- Any reason why not? */
|
|
|
01e27f8 |
- if (HAVE_return && cleanup_label == 0
|
|
|
01e27f8 |
- && ! current_function_returns_pcc_struct
|
|
|
01e27f8 |
- && BRANCH_COST <= 1)
|
|
|
01e27f8 |
- {
|
|
|
01e27f8 |
- /* If this is return x == y; then generate
|
|
|
01e27f8 |
- if (x == y) return 1; else return 0;
|
|
|
01e27f8 |
- if we can do it with explicit return insns and branches are cheap,
|
|
|
01e27f8 |
- but not if we have the corresponding scc insn. */
|
|
|
01e27f8 |
- int has_scc = 0;
|
|
|
01e27f8 |
- if (retval_rhs)
|
|
|
01e27f8 |
- switch (TREE_CODE (retval_rhs))
|
|
|
01e27f8 |
- {
|
|
|
01e27f8 |
- case EQ_EXPR:
|
|
|
01e27f8 |
- #ifdef HAVE_seq
|
|
|
01e27f8 |
- has_scc = HAVE_seq;
|
|
|
01e27f8 |
- #endif
|
|
|
01e27f8 |
- case NE_EXPR:
|
|
|
01e27f8 |
- #ifdef HAVE_sne
|
|
|
01e27f8 |
- has_scc = HAVE_sne;
|
|
|
01e27f8 |
- #endif
|
|
|
01e27f8 |
- case GT_EXPR:
|
|
|
01e27f8 |
- #ifdef HAVE_sgt
|
|
|
01e27f8 |
- has_scc = HAVE_sgt;
|
|
|
01e27f8 |
- #endif
|
|
|
01e27f8 |
- case GE_EXPR:
|
|
|
01e27f8 |
- #ifdef HAVE_sge
|
|
|
01e27f8 |
- has_scc = HAVE_sge;
|
|
|
01e27f8 |
- #endif
|
|
|
01e27f8 |
- case LT_EXPR:
|
|
|
01e27f8 |
- #ifdef HAVE_slt
|
|
|
01e27f8 |
- has_scc = HAVE_slt;
|
|
|
01e27f8 |
- #endif
|
|
|
01e27f8 |
- case LE_EXPR:
|
|
|
01e27f8 |
- #ifdef HAVE_sle
|
|
|
01e27f8 |
- has_scc = HAVE_sle;
|
|
|
01e27f8 |
- #endif
|
|
|
01e27f8 |
- case TRUTH_ANDIF_EXPR:
|
|
|
01e27f8 |
- case TRUTH_ORIF_EXPR:
|
|
|
01e27f8 |
- case TRUTH_AND_EXPR:
|
|
|
01e27f8 |
- case TRUTH_OR_EXPR:
|
|
|
01e27f8 |
- case TRUTH_NOT_EXPR:
|
|
|
01e27f8 |
- case TRUTH_XOR_EXPR:
|
|
|
01e27f8 |
- if (! has_scc)
|
|
|
01e27f8 |
- {
|
|
|
01e27f8 |
- op0 = gen_label_rtx ();
|
|
|
01e27f8 |
- jumpifnot (retval_rhs, op0);
|
|
|
01e27f8 |
- expand_value_return (const1_rtx);
|
|
|
01e27f8 |
- emit_label (op0);
|
|
|
01e27f8 |
- expand_value_return (const0_rtx);
|
|
|
01e27f8 |
- return;
|
|
|
01e27f8 |
- }
|
|
|
01e27f8 |
- break;
|
|
|
01e27f8 |
-
|
|
|
01e27f8 |
- default:
|
|
|
01e27f8 |
- break;
|
|
|
01e27f8 |
- }
|
|
|
01e27f8 |
- }
|
|
|
01e27f8 |
- #endif /* HAVE_return */
|
|
|
01e27f8 |
|
|
|
01e27f8 |
/* If the result is an aggregate that is being returned in one (or more)
|
|
|
01e27f8 |
registers, load the registers here. The compiler currently can't handle
|
|
|
01e27f8 |
--- 2881,2886 ----
|
|
|
01e27f8 |
|