Commit d1af0b85 authored by Raymond Toy's avatar Raymond Toy
Browse files

Optimize TRUNCATE when the second arg is a compile-time constant.

parent 089f104a
......@@ -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
......
......@@ -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:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment