diff --git a/src/compiler/x86/arith.lisp b/src/compiler/x86/arith.lisp
index 5751abbf7de4851cb5a6ce50b568f9d0e90f91a3..6739f9b221d30fc31a10160dca11a000268923c1 100644
--- a/src/compiler/x86/arith.lisp
+++ b/src/compiler/x86/arith.lisp
@@ -474,6 +474,7 @@
 	(inst lea quo (make-ea :dword :index eax :scale 4)))
     (move rem edx)))
 
+#+nil
 (define-vop (fast-truncate-c/fixnum=>fixnum fast-safe-arith-op)
   (:translate truncate)
   (:args (x :scs (any-reg) :target eax))
@@ -527,6 +528,7 @@
     (move quo eax)
     (move rem edx)))
 
+#+nil
 (define-vop (fast-truncate-c/unsigned=>unsigned fast-safe-arith-op)
   (:translate truncate)
   (:args (x :scs (unsigned-reg) :target eax))
@@ -551,6 +553,44 @@
     (move quo eax)
     (move rem edx)))
 
+(define-vop (fast-truncate-c/unsigned=>unsigned fast-unsigned-binop-c)
+  (:translate truncate)
+  (:args (x :scs (unsigned-reg)))
+  (:info y)
+  (:arg-types unsigned-num (:constant (integer 2 #.(1- (ash 1 vm:word-bits)))))
+  (:results (r :scs (unsigned-reg))
+            (rem :scs (unsigned-reg)))
+  (:result-types unsigned-num unsigned-num)
+  (:note "inline (unsigned-byte 32) arithmetic")
+  (:temporary (:sc unsigned-reg :offset edx-offset) edx)
+  (:temporary (:sc unsigned-reg :offset eax-offset) eax)
+  (:generator 6
+    (multiple-value-bind (recip shift overflowp)
+        (c::find-unsigned-reciprocal y vm:word-bits)
+      ;; q = floor(M*x/2^32)
+      (inst mov eax recip)
+      (inst mul eax x)			; edx:eax = x*recip
+      (cond (overflowp
+	     ;; The case where the sum overflows.  X86 has a rotate
+	     ;; with carry instruction so use that to get the MSB of
+	     ;; the sum and then a regular shift to get the correct
+	     ;; number of shifts.
+	     (inst add edx x)
+	     (inst rcr edx 1)
+	     (when (> shift 1)
+	       (inst shr edx (1- shift))))
+            (t
+             ;; The easy case
+             (unless (zerop shift)
+               (inst shr edx shift))))
+      ;; Compute the remainder
+      (move rem x)			; Save x in case r is the same tn
+      (move r edx)
+      (move eax edx)
+      (inst mov edx y)
+      (inst mul eax edx)
+      (inst sub rem eax))))
+
 (define-vop (fast-truncate/signed=>signed fast-safe-arith-op)
   (:translate truncate)
   (:args (x :scs (signed-reg) :target eax)
@@ -578,6 +618,7 @@
     (move quo eax)
     (move rem edx)))
 
+#+nil
 (define-vop (fast-truncate-c/signed=>signed fast-safe-arith-op)
   (:translate truncate)
   (:args (x :scs (signed-reg) :target eax))
@@ -602,6 +643,43 @@
     (move quo eax)
     (move rem edx)))
 
+(define-vop (fast-truncate-c/signed=>signed fast-signed-binop-c)
+  (:translate truncate)
+  (:args (x :scs (signed-reg)))
+  (:info y)
+  (:arg-types signed-num (:constant (integer 2 #.(1- (ash 1 vm:word-bits)))))
+  (:results (r :scs (signed-reg))
+            (rem :scs (signed-reg)))
+  (:result-types signed-num signed-num)
+  (:note "inline (signed-byte 32) arithmetic")
+  (:temporary (:sc signed-reg :offset edx-offset) edx)
+  (:temporary (:sc signed-reg :offset eax-offset) eax)
+  (:generator 13
+    (multiple-value-bind (recip shift)
+        (c::find-signed-reciprocal y vm:word-bits)
+      ;; Compute q = floor(M*n/2^32).  That is, the high half of the
+      ;; product.
+      (inst mov eax recip)
+      (inst imul x)			; edx:eax = x * recip
+      ;; Adjust if the M is negative.
+      (when (minusp recip)
+        (inst add edx x))
+      ;; Shift quotient as needed.
+      (unless (zerop shift)
+	(inst sar edx shift))
+      ;; Add one to quotient if X is negative.  This is done by right
+      ;; shifting X to give either -1 or 0.  Then subtract this from
+      ;; the quotient.  (NOTE: in the book, the sample code has this
+      ;; wrong and ADDS instead of SUBTRACTS.)
+      (move eax x)
+      (inst sar eax 31)
+      (inst sub edx eax)
+
+      ;; Now compute the remainder.
+      (move rem x)
+      (move r edx)			; Save quotient for return
+      (inst imul edx y)			; edx = q * y
+      (inst sub rem edx))))
 
 
 ;;;; Shifting
diff --git a/src/general-info/release-20e.txt b/src/general-info/release-20e.txt
index e5b7331011041f3cffdecee514bcf71fc08e48c5..8d14c5833f2e49f97198ba408c48ddf78c56555f 100644
--- a/src/general-info/release-20e.txt
+++ b/src/general-info/release-20e.txt
@@ -31,7 +31,9 @@ New in this release:
     * The sparc port can be built using gcc once again.
     * The old Cheney stop-and-copy GC supported on sparc once again.
       However, there are no plans on supplying sparc binaries with
-      this GC. 
+      this GC.
+    * For x86, optimize TRUNCATE when the second arg is a compile-time
+      constant.  (Sparc and ppc already had this optimization)
 
   * ANSI compliance fixes: