--- gcc/dojump.c.jj	2013-12-02 14:33:25.954413998 +0100
+++ gcc/dojump.c	2013-12-02 15:08:39.958423641 +0100
@@ -96,6 +96,29 @@ do_pending_stack_adjust (void)
       pending_stack_adjust = 0;
     }
 }
+
+/* Remember pending_stack_adjust/stack_pointer_delta.
+   To be used around code that may call do_pending_stack_adjust (),
+   but the generated code could be discarded e.g. using delete_insns_since.  */
+
+void
+save_pending_stack_adjust (saved_pending_stack_adjust *save)
+{
+  save->x_pending_stack_adjust = pending_stack_adjust;
+  save->x_stack_pointer_delta = stack_pointer_delta;
+}
+
+/* Restore the saved pending_stack_adjust/stack_pointer_delta.  */
+
+void
+restore_pending_stack_adjust (saved_pending_stack_adjust *save)
+{
+  if (inhibit_defer_pop == 0)
+    {
+      pending_stack_adjust = save->x_pending_stack_adjust;
+      stack_pointer_delta = save->x_stack_pointer_delta;
+    }
+}
 
 /* Expand conditional expressions.  */
 
--- gcc/expr.h.jj	2013-12-02 14:33:26.263412414 +0100
+++ gcc/expr.h	2013-12-02 14:50:15.374175604 +0100
@@ -473,6 +473,28 @@ extern void clear_pending_stack_adjust (
 /* Pop any previously-pushed arguments that have not been popped yet.  */
 extern void do_pending_stack_adjust (void);
 
+/* Struct for saving/restoring of pending_stack_adjust/stack_pointer_delta
+   values.  */
+
+struct saved_pending_stack_adjust
+{
+  /* Saved value of pending_stack_adjust.  */
+  int x_pending_stack_adjust;
+
+  /* Saved value of stack_pointer_delta.  */
+  int x_stack_pointer_delta;
+};
+
+/* Remember pending_stack_adjust/stack_pointer_delta.
+   To be used around code that may call do_pending_stack_adjust (),
+   but the generated code could be discarded e.g. using delete_insns_since.  */
+
+extern void save_pending_stack_adjust (saved_pending_stack_adjust *);
+
+/* Restore the saved pending_stack_adjust/stack_pointer_delta.  */
+
+extern void restore_pending_stack_adjust (saved_pending_stack_adjust *);
+
 /* Return the tree node and offset if a given argument corresponds to
    a string constant.  */
 extern tree string_constant (tree, tree *);
--- gcc/optabs.c.jj	2013-12-02 14:33:25.000000000 +0100
+++ gcc/optabs.c	2013-12-02 15:12:04.000000000 +0100
@@ -4566,8 +4566,10 @@ emit_conditional_move (rtx target, enum
   if (!COMPARISON_P (comparison))
     return NULL_RTX;
 
-  do_pending_stack_adjust ();
+  saved_pending_stack_adjust save;
+  save_pending_stack_adjust (&save);
   last = get_last_insn ();
+  do_pending_stack_adjust ();
   prepare_cmp_insn (XEXP (comparison, 0), XEXP (comparison, 1),
 		    GET_CODE (comparison), NULL_RTX, unsignedp, OPTAB_WIDEN,
 		    &comparison, &cmode);
@@ -4587,6 +4589,7 @@ emit_conditional_move (rtx target, enum
 	}
     }
   delete_insns_since (last);
+  restore_pending_stack_adjust (&save);
   return NULL_RTX;
 }
 
--- gcc/expr.c.jj	2013-12-02 14:33:33.047377131 +0100
+++ gcc/expr.c	2013-12-02 15:10:40.511794869 +0100
@@ -8790,12 +8790,6 @@ expand_expr_real_2 (sepops ops, rtx targ
 	  {
 	    rtx insn;
 
-	    /* ??? Same problem as in expmed.c: emit_conditional_move
-	       forces a stack adjustment via compare_from_rtx, and we
-	       lose the stack adjustment if the sequence we are about
-	       to create is discarded.  */
-	    do_pending_stack_adjust ();
-
 	    start_sequence ();
 
 	    /* Try to emit the conditional move.  */
--- gcc/expmed.c.jj	2013-12-02 14:33:26.156412923 +0100
+++ gcc/expmed.c	2013-12-02 15:10:18.606894232 +0100
@@ -3736,11 +3736,6 @@ expand_sdiv_pow2 (enum machine_mode mode
     {
       rtx temp2;
 
-      /* ??? emit_conditional_move forces a stack adjustment via
-	 compare_from_rtx so, if the sequence is discarded, it will
-	 be lost.  Do it now instead.  */
-      do_pending_stack_adjust ();
-
       start_sequence ();
       temp2 = copy_to_mode_reg (mode, op0);
       temp = expand_binop (mode, add_optab, temp2, gen_int_mode (d - 1, mode),
--- gcc/calls.c.jj	2013-11-22 21:03:14.000000000 +0100
+++ gcc/calls.c	2013-12-02 15:25:37.537126526 +0100
@@ -2672,8 +2672,7 @@ expand_call (tree exp, rtx target, int i
 	 recursion "call".  That way we know any adjustment after the tail
 	 recursion call can be ignored if we indeed use the tail
 	 call expansion.  */
-      int save_pending_stack_adjust = 0;
-      int save_stack_pointer_delta = 0;
+      saved_pending_stack_adjust save;
       rtx insns;
       rtx before_call, next_arg_reg, after_args;
 
@@ -2681,8 +2680,7 @@ expand_call (tree exp, rtx target, int i
 	{
 	  /* State variables we need to save and restore between
 	     iterations.  */
-	  save_pending_stack_adjust = pending_stack_adjust;
-	  save_stack_pointer_delta = stack_pointer_delta;
+	  save_pending_stack_adjust (&save);
 	}
       if (pass)
 	flags &= ~ECF_SIBCALL;
@@ -3438,8 +3436,7 @@ expand_call (tree exp, rtx target, int i
 	  /* Restore the pending stack adjustment now that we have
 	     finished generating the sibling call sequence.  */
 
-	  pending_stack_adjust = save_pending_stack_adjust;
-	  stack_pointer_delta = save_stack_pointer_delta;
+	  restore_pending_stack_adjust (&save);
 
 	  /* Prepare arg structure for next iteration.  */
 	  for (i = 0; i < num_actuals; i++)
--- gcc/testsuite/g++.dg/opt/pr58864.C.jj	2013-12-02 14:47:16.212105758 +0100
+++ gcc/testsuite/g++.dg/opt/pr58864.C	2013-12-02 14:47:16.212105758 +0100
@@ -0,0 +1,21 @@
+// PR target/58864
+// { dg-do compile }
+// { dg-options "-Os" }
+// { dg-additional-options "-march=i686" { target { { i?86-*-* x86_64-*-* } && ia32 } } }
+
+struct A { A (); ~A (); };
+struct B { B (); };
+
+float d, e;
+
+void
+foo ()
+{
+  A a;
+  float c = d;
+  while (1)
+    {
+      B b;
+      e = c ? -c : 0;
+    }
+}
