diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 28a3177fd1fd..d767472eedb6 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2004-10-18  Eric Botcazou  <ebotcazou@libertysurf.fr>
+            Roger Sayle  <roger@eyesopen.com>
+
+	PR middle-end/17813
+	* dojump.c (discard_pending_stack_adjust): New function.
+	(clear_pending_stack_adjust): Call it.
+	* expr.h (discard_pending_stack_adjust): Declare it.
+	* explow.c (emit_stack_save): Emit pending stack adjustments
+	before saving the stack pointer.
+	(emit_stack_restore): Discard pending stack adjustments before
+	restoring the stack pointer.
+
 2004-10-18  Richard Henderson  <rth@redhat.com>
 
 	* c-common.c (handle_mode_attribute): Allow scalar->vector 
diff --git a/gcc/dojump.c b/gcc/dojump.c
index 50fc093f72f6..e506684f41d7 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -50,6 +50,15 @@ init_pending_stack_adjust (void)
   pending_stack_adjust = 0;
 }
 
+/* Discard any pending stack adjustment.  This avoid relying on the
+   RTL optimizers to remove useless adjustments when we know the
+   stack pointer value is dead.  */
+void discard_pending_stack_adjust (void)
+{
+  stack_pointer_delta -= pending_stack_adjust;
+  pending_stack_adjust = 0;
+}
+
 /* When exiting from function, if safe, clear out any pending stack adjust
    so the adjustment won't get done.
 
@@ -64,10 +73,7 @@ clear_pending_stack_adjust (void)
       && EXIT_IGNORE_STACK
       && ! (DECL_INLINE (current_function_decl) && ! flag_no_inline)
       && ! flag_inline_functions)
-    {
-      stack_pointer_delta -= pending_stack_adjust,
-      pending_stack_adjust = 0;
-    }
+    discard_pending_stack_adjust ();
 }
 
 /* Pop any previously-pushed arguments that have not been popped yet.  */
diff --git a/gcc/explow.c b/gcc/explow.c
index 62ca87c3ca0b..45126f6c420c 100644
--- a/gcc/explow.c
+++ b/gcc/explow.c
@@ -965,6 +965,7 @@ emit_stack_save (enum save_level save_level, rtx *psave, rtx after)
       rtx seq;
 
       start_sequence ();
+      do_pending_stack_adjust ();
       /* We must validize inside the sequence, to ensure that any instructions
 	 created by the validize call also get moved to the right place.  */
       if (sa != 0)
@@ -976,6 +977,7 @@ emit_stack_save (enum save_level save_level, rtx *psave, rtx after)
     }
   else
     {
+      do_pending_stack_adjust ();
       if (sa != 0)
 	sa = validize_mem (sa);
       emit_insn (fcn (sa, stack_pointer_rtx));
@@ -1032,6 +1034,8 @@ emit_stack_restore (enum save_level save_level, rtx sa, rtx after)
 		    gen_rtx_MEM (BLKmode, stack_pointer_rtx)));
     }
 
+  discard_pending_stack_adjust ();
+
   if (after)
     {
       rtx seq;
diff --git a/gcc/expr.h b/gcc/expr.h
index 2f693bb3daf7..dc66239f2403 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -499,6 +499,9 @@ extern void expand_var (tree);
    arguments waiting to be popped.  */
 extern void init_pending_stack_adjust (void);
 
+/* Discard any pending stack adjustment.  */
+extern void discard_pending_stack_adjust (void);
+
 /* When exiting from function, if safe, clear out any pending stack adjust
    so the adjustment won't get done.  */
 extern void clear_pending_stack_adjust (void);