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));
/* 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;
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);
{
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;
}
}
&& 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;
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;
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;
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