aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>2000-08-12 09:28:10 -0700
committerRichard Henderson <rth@gcc.gnu.org>2000-08-12 09:28:10 -0700
commit055bcfeedad2c54d2abbf2dc85f50565defc92f0 (patch)
tree0b58003a89bb66321aeaebb663ee8fe8ba653669
parent3ac597cb9a7b77b48e54670f6d9f3a028bd75b8f (diff)
downloadgcc-055bcfeedad2c54d2abbf2dc85f50565defc92f0.zip
gcc-055bcfeedad2c54d2abbf2dc85f50565defc92f0.tar.gz
gcc-055bcfeedad2c54d2abbf2dc85f50565defc92f0.tar.bz2
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
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/sibcall.c37
-rw-r--r--gcc/stmt.c79
3 files changed, 25 insertions, 100 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ac510fa..402fe22 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 78e855e..42a9d70 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 47431f6..38572ca 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