Index: /trunk/source/compiler/X86/X8632/x8632-vinsns.lisp
===================================================================
--- /trunk/source/compiler/X86/X8632/x8632-vinsns.lisp	(revision 15410)
+++ /trunk/source/compiler/X86/X8632/x8632-vinsns.lisp	(revision 15411)
@@ -1260,4 +1260,10 @@
   (jmp lab))
 
+(define-x8632-vinsn return-or-fix-overflow (()
+                                            ())
+  (jo :fix)
+  (:byte #xf3) (ret)
+  :fix
+  (jmp (:@ .SPfix-overflow)))
 
 (define-x8632-vinsn add-constant (((dest :imm))
Index: /trunk/source/compiler/X86/X8664/x8664-vinsns.lisp
===================================================================
--- /trunk/source/compiler/X86/X8664/x8664-vinsns.lisp	(revision 15410)
+++ /trunk/source/compiler/X86/X8664/x8664-vinsns.lisp	(revision 15411)
@@ -1391,4 +1391,11 @@
    (movq (:%q x8664::arg_z) (:%q val)))
   (jmp lab))
+
+(define-x8664-vinsn return-or-fix-overflow (()
+                                            ())
+  (jo :fix)
+  (:byte #xf3) (ret)
+  :fix
+  (jmp (:@ .SPfix-overflow)))
 
 (define-x8664-vinsn add-constant (((dest :imm))
Index: /trunk/source/compiler/X86/x862.lisp
===================================================================
--- /trunk/source/compiler/X86/x862.lisp	(revision 15410)
+++ /trunk/source/compiler/X86/x862.lisp	(revision 15411)
@@ -5749,5 +5749,5 @@
          (label nil)
          (vstack nil)
-         (foldp (not *x862-open-code-inline*)))
+         (foldp (x862-fold-popj)))
     (if (%izerop mask) (setq mask nil))
     (with-x86-local-vinsn-macros (seg)
@@ -6083,5 +6083,14 @@
        (eq 0 *x862-undo-count*)))
 
-(defun x862-mv-p (cd)
+;;; on x86, branching to a shared exit point can sometimes be
+;;; larger than simply exiting, but it's hard to know that in
+;;; advance.  If the exit point involves restoring nvrs, then
+;;; it's likely that branching will be smaller.
+(defun x862-fold-popj ()
+  (unless *x862-open-code-inline* ;  never fold if speed>space
+    *x862-register-restore-ea*))  ;  fold if we'll need to restore nvrs.
+  
+
+(defun x862-mv-p (cd) 
   (or (eq cd $backend-return) (x862-mvpass-p cd)))
 
@@ -7753,5 +7762,5 @@
                  (falselabel (backend-get-next-label))
                  (need-else (unless false-is-goto (or (not (nx-null false)) (x862-for-value-p vreg))))
-                 (both-single-valued (and (not *x862-open-code-inline*)
+                 (both-single-valued (and (x862-fold-popj)
                                           (eq xfer $backend-return)
                                           (x862-for-value-p vreg)
@@ -7927,9 +7936,13 @@
 
 (defun x862-inline-sub2 (seg vreg xfer form1 form2)
-  (let* ((v2 (acode-fixnum-form-p form2)))
+  (let* ((v2 (acode-fixnum-form-p form2))
+         (tailp (and (x862-tailcallok xfer) (not (x862-fold-popj)))))
     (if (and v2 (not (eql v2 most-negative-fixnum)))
       (x862-inline-add2 seg vreg xfer form1 (make-acode (%nx1-operator fixnum) (- v2)))
       (with-x86-local-vinsn-macros (seg vreg xfer)
         (x862-two-targeted-reg-forms seg form1 ($ *x862-arg-y*) form2 ($ *x862-arg-z*))
+        (when tailp
+        (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count* t)
+        (! restore-full-lisp-context))
     (let* ((out-of-line (backend-get-next-label))
            (done (backend-get-next-label)))
@@ -7941,10 +7954,16 @@
             (! branch-unless-both-args-fixnums ($ *x862-arg-y*) ($ *x862-arg-z*) (aref *backend-labels* out-of-line))))
         (! fixnum-sub2 ($ *x862-arg-z*) ($ *x862-arg-y*) ($ *x862-arg-z*))
-        (x862-check-fixnum-overflow seg ($ *x862-arg-z*) done)
+        (if tailp
+          (! return-or-fix-overflow)
+          (x862-check-fixnum-overflow seg ($ *x862-arg-z*) done))
         (@ out-of-line)
+        (if tailp
+          (! jump-subprim (subprim-name->offset '.SPbuiltin-minus))
+          (progn
         (! call-subprim-2 ($ *x862-arg-z*) (subprim-name->offset '.SPbuiltin-minus) ($ *x862-arg-y*) ($ *x862-arg-z*))
         (@ done)
-        (x862-copy-register seg target ($ *x862-arg-z*)))
-      (^))))))
+        (x862-copy-register seg target ($ *x862-arg-z*)))))
+      (unless tailp
+        (^)))))))
 
 (defun x862-inline-add2 (seg vreg xfer form1 form2)
@@ -7957,8 +7976,12 @@
 			form2
 			(if fix2
-			  form1))))
+			  form1)))
+           (tailp (and (x862-tailcallok xfer) (not (x862-fold-popj)))))
       (if otherform
         (x862-one-targeted-reg-form seg otherform ($ *x862-arg-z*))
         (x862-two-targeted-reg-forms seg form1 ($ *x862-arg-y*) form2 ($ *x862-arg-z*)))
+      (when tailp
+        (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count* t)
+        (! restore-full-lisp-context))
       (let* ((out-of-line (backend-get-next-label))
              (done (backend-get-next-label)))
@@ -7975,12 +7998,18 @@
             (! add-constant ($ *x862-arg-z*) (ash (or fix1 fix2) *x862-target-fixnum-shift*))
             (! fixnum-add2 ($ *x862-arg-z*) ($ *x862-arg-y*)))
-          (x862-check-fixnum-overflow seg ($ *x862-arg-z*) done)
+          (if tailp
+            (! return-or-fix-overflow)
+            (x862-check-fixnum-overflow seg ($ *x862-arg-z*) done))
           (@ out-of-line)
           (if otherform
             (x862-lri seg ($ *x862-arg-y*) (ash (or fix1 fix2) *x862-target-fixnum-shift*)))
-          (! call-subprim-2 ($ *x862-arg-z*) (subprim-name->offset '.SPbuiltin-plus) ($ *x862-arg-y*) ($ *x862-arg-z*))
-          (@ done)
-          (x862-copy-register seg target ($ *x862-arg-z*)))
-        (^)))))
+          (if tailp
+            (! jump-subprim (subprim-name->offset '.SPbuiltin-plus))
+            (progn
+              (! call-subprim-2 ($ *x862-arg-z*) (subprim-name->offset '.SPbuiltin-plus) ($ *x862-arg-y*) ($ *x862-arg-z*))
+              (@ done)
+              (x862-copy-register seg target ($ *x862-arg-z*)))))
+        (unless tailp
+          (^))))))
            
 (defx862 x862-add2 add2 (seg vreg xfer form1 form2)
@@ -8018,5 +8047,6 @@
                (fiximm (if fixval (<= (integer-length fixval)
                                       (- 31 *x862-target-fixnum-shift*))))
-               (otherform (when fiximm (if fix1 form2 form1))))
+               (otherform (when fiximm (if fix1 form2 form1)))
+               (tailp (and (x862-tailcallok xfer) (not (x862-fold-popj)))))
           (let* ((out-of-line (backend-get-next-label))
                  (done (backend-get-next-label)))
@@ -8025,4 +8055,7 @@
                 (x862-one-targeted-reg-form seg otherform ($ *x862-arg-z*))
                 (x862-two-targeted-reg-forms seg form1 ($ *x862-arg-y*) form2 ($ *x862-arg-z*)))
+              (when tailp
+                (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count* t)
+                (! restore-full-lisp-context))
               (if otherform
                 (unless (acode-fixnum-form-p otherform)
@@ -8036,12 +8069,18 @@
                 (! %logior-c ($ *x862-arg-z*) ($ *x862-arg-z*) (ash fixval *x862-target-fixnum-shift*))
                 (! %logior2 ($ *x862-arg-z*) ($ *x862-arg-z*) ($ *x862-arg-y*)))
-              (-> done)
+              (if tailp
+                (! jump-return-pc)
+                (-> done))
               (@ out-of-line)
               (if otherform
                 (x862-lri seg ($ *x862-arg-y*) (ash fixval *x862-target-fixnum-shift*)))
-              (! call-subprim-2 ($ *x862-arg-z*) (subprim-name->offset '.SPbuiltin-logior) ($ *x862-arg-y*) ($ *x862-arg-z*))
-              (@ done)
-              (x862-copy-register seg target ($ *x862-arg-z*)))
-            (^)))))))
+              (if tailp
+                (! jump-subprim (subprim-name->offset '.SPbuiltin-logior))
+                (progn
+                  (! call-subprim-2 ($ *x862-arg-z*) (subprim-name->offset '.SPbuiltin-logior) ($ *x862-arg-y*) ($ *x862-arg-z*))
+                  (@ done)
+                  (x862-copy-register seg target ($ *x862-arg-z*)))))
+            (unless tailp
+              (^))))))))
 
 (defx862 x862-logior2 logior2 (seg vreg xfer form1 form2)
@@ -8065,5 +8104,6 @@
                (fiximm (if fixval (<= (integer-length fixval)
                                       (- 31 *x862-target-fixnum-shift*))))
-               (otherform (when fiximm (if fix1 form2 form1))))
+               (otherform (when fiximm (if fix1 form2 form1)))
+               (tailp (and (x862-tailcallok xfer) (not (x862-fold-popj)))))
           (let* ((out-of-line (backend-get-next-label))
                  (done (backend-get-next-label)))
@@ -8072,4 +8112,7 @@
                 (x862-one-targeted-reg-form seg otherform ($ *x862-arg-z*))
                 (x862-two-targeted-reg-forms seg form1 ($ *x862-arg-y*) form2 ($ *x862-arg-z*)))
+              (when tailp
+                (x862-restore-nvrs seg *x862-register-restore-ea* *x862-register-restore-count* t)
+                (! restore-full-lisp-context))
               (if otherform
                 (unless (acode-fixnum-form-p otherform)
@@ -8083,12 +8126,17 @@
                 (! %logand-c ($ *x862-arg-z*) ($ *x862-arg-z*) (ash fixval *x862-target-fixnum-shift*))
                 (! %logand2 ($ *x862-arg-z*) ($ *x862-arg-z*) ($ *x862-arg-y*)))
-              (-> done)
+              (if tailp
+                (! jump-return-pc)
+                (-> done))
               (@ out-of-line)
               (if otherform
                 (x862-lri seg ($ *x862-arg-y*) (ash fixval *x862-target-fixnum-shift*)))
-              (! call-subprim-2 ($ *x862-arg-z*) (subprim-name->offset '.SPbuiltin-logand) ($ *x862-arg-y*) ($ *x862-arg-z*))
-              (@ done)
-              (x862-copy-register seg target ($ *x862-arg-z*)))
-            (^)))))))
+              (if tailp
+                (! jump-subprim (subprim-name->offset '.SPbuiltin-logand))
+                (progn
+                  (! call-subprim-2 ($ *x862-arg-z*) (subprim-name->offset '.SPbuiltin-logand) ($ *x862-arg-y*) ($ *x862-arg-z*))
+                  (@ done)
+                  (x862-copy-register seg target ($ *x862-arg-z*)))))
+              (^)))))))
 
 (defx862 x862-logand2 logand2 (seg vreg xfer form1 form2)
