Index: /trunk/source/compiler/X86/x862.lisp
===================================================================
--- /trunk/source/compiler/X86/x862.lisp	(revision 14966)
+++ /trunk/source/compiler/X86/x862.lisp	(revision 14967)
@@ -3370,19 +3370,47 @@
                                       (vinsn-sequence-sets-reg-p
                                        push-vinsn pop-vinsn popped-reg))))
-            (unless (and pushed-reg-is-set popped-reg-is-set)
-              (unless same-reg
-                (let* ((copy (if (eq (hard-regspec-class pushed-reg)
-                                     hard-reg-class-fpr)
-                               (if (= (get-regspec-mode pushed-reg)
-                                      hard-reg-class-fpr-mode-double)
-                                 (! copy-double-float popped-reg pushed-reg)
-                                 (! copy-single-float popped-reg pushed-reg))
-                               (! copy-gpr popped-reg pushed-reg))))
-                  (remove-dll-node copy)
-                  (if pushed-reg-is-set
-                    (insert-dll-node-after copy push-vinsn)
-                    (insert-dll-node-before copy push-vinsn))))
-              (elide-vinsn push-vinsn)
-              (elide-vinsn pop-vinsn))))))))
+            (cond
+	      ((not (and pushed-reg-is-set popped-reg-is-set))
+	       (unless same-reg
+		 (let* ((copy (if (eq (hard-regspec-class pushed-reg)
+				      hard-reg-class-fpr)
+				(if (= (get-regspec-mode pushed-reg)
+				       hard-reg-class-fpr-mode-double)
+				  (! copy-double-float popped-reg pushed-reg)
+				  (! copy-single-float popped-reg pushed-reg))
+				(! copy-gpr popped-reg pushed-reg))))
+		   (remove-dll-node copy)
+		   (if pushed-reg-is-set
+		     (insert-dll-node-after copy push-vinsn)
+		     (insert-dll-node-before copy push-vinsn))))
+	       (elide-vinsn push-vinsn)
+	       (elide-vinsn pop-vinsn))
+	      ((and (eql (hard-regspec-class pushed-reg) hard-reg-class-fpr)
+		    (eql (get-regspec-mode pushed-reg)
+			 hard-reg-class-fpr-mode-double))
+	       ;; If we're pushing a double-float register that gets
+	       ;; set by the intervening vinsns, try to copy it to and
+	       ;; from a free FPR instead.
+	       (multiple-value-bind (used-gprs used-fprs)
+		   (regs-set-in-vinsn-sequence push-vinsn pop-vinsn)
+		 (declare (ignore used-gprs))
+		 (let* ((nfprs (target-arch-case
+				(:x8632 6)
+				(:x8664 14))) ;xmm7 (or xmm15) is fpzero.
+			(free-fpr
+			 (dotimes (r nfprs nil)
+			   (unless (logtest (target-fpr-mask r :double-float)
+					    used-fprs)
+			     (return r)))))
+		   (when free-fpr
+		     (let* ((reg ($ free-fpr :class :fpr :mode :double-float))
+			    (save (! copy-double-float reg pushed-reg))
+			    (restore (! copy-double-float popped-reg reg)))
+		       (remove-dll-node save)
+		       (insert-dll-node-after save push-vinsn)
+		       (remove-dll-node restore)
+		       (insert-dll-node-before restore pop-vinsn)
+		       (elide-vinsn push-vinsn)
+		       (elide-vinsn pop-vinsn)))))))))))))
                 
         
