diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index ac510fa620e4414a15e1aeccaaec8ed1c918bab2..402fe228aecf57395f23d2a8c4ac4b125f5fe362 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 78e855eef78d6e859869f0037e68ccbea5be01dd..42a9d70fb815a3ef35a8e1e40b3a76f643022672 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 47431f6471eb3ca6ccff6a1dfe4b81ae4b9d1803..38572ca6fe86eb8ffe25dcccaf0dfd6891741017 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