From c17392f461f177128fe189fc3f3efe30f836eec3 Mon Sep 17 00:00:00 2001
From: Raymond Toy <toy.raymond@gmail.com>
Date: Wed, 9 May 2012 23:14:00 -0700
Subject: [PATCH] Add popcnt instruction and use it in logcount vop if :sse3 is
 a feature.

 * src/compiler/x86/arith.lisp
   * Add vop for logcount that uses popcnt instruction.
 * src/compiler/x86/insts.lisp
   * Define popcnt instruction (but only for :sse3)
 * src/general-info/release-20d.txt:
   * Update.
---
 src/compiler/x86/arith.lisp      | 12 ++++++++++++
 src/compiler/x86/insts.lisp      | 18 ++++++++++++++++--
 src/general-info/release-20d.txt |  1 +
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/src/compiler/x86/arith.lisp b/src/compiler/x86/arith.lisp
index 69d342684..b4b43f75e 100644
--- a/src/compiler/x86/arith.lisp
+++ b/src/compiler/x86/arith.lisp
@@ -900,6 +900,18 @@
     (inst and temp #x0000ffff)
     (inst add result temp)))
 
+(define-vop (sse3-unsigned-byte-32-count)
+  (:translate logcount)
+  (:note _N"inline (unsigned-byte 32) logcount")
+  (:policy :fast-safe)
+  (:args (arg :scs (unsigned-reg)))
+  (:arg-types unsigned-num)
+  (:results (result :scs (unsigned-reg)))
+  (:result-types positive-fixnum)
+  (:temporary (:sc unsigned-reg :from (:argument 0)) temp)
+  (:guard (backend-featurep :sse3))
+  (:generator 2
+    (inst popcnt result arg)))
 
 
 ;;;; Binary conditional VOPs:
diff --git a/src/compiler/x86/insts.lisp b/src/compiler/x86/insts.lisp
index b7dad1536..e22a0139b 100644
--- a/src/compiler/x86/insts.lisp
+++ b/src/compiler/x86/insts.lisp
@@ -3091,6 +3091,17 @@
                                 :type 'sized-xmmreg/mem)
   (reg     :field (byte 3 27)   :type 'reg))
 
+;;; Like ext-reg-xmm/mem, but both are registers
+(disassem:define-instruction-format (ext-reg-reg/mem 32
+                                     :default-printer
+                                     '(:name :tab reg ", " reg/mem))
+  (prefix  :field (byte 8 0))
+  (x0f     :field (byte 8 8)    :value #x0f)
+  (op      :field (byte 8 16))
+  (reg/mem :fields (list (byte 2 30) (byte 3 24))
+                                :type 'reg/mem)
+  (reg     :field (byte 3 27)   :type 'reg))
+
 (disassem:define-instruction-format
     (ext-xmm-xmm/mem-imm 32
 			 :include 'ext-xmm-xmm/mem
@@ -3182,9 +3193,12 @@
   ;; dst[63:0] = dst[63:0]
   ;; dst[127:64] = src[63:0]
   (define-regular-sse-inst unpcklpd #x66 #x14 t)
-  (define-regular-sse-inst unpcklps nil  #x14 t)
+  (define-regular-sse-inst unpcklps nil  #x14 t))
 
-  )
+(define-instruction popcnt (segment dst src)
+  (:printer ext-reg-reg/mem
+	    ((prefix #xf3) (op #xb8)))
+  (:emitter (emit-sse-inst segment dst src #xf3 #xb8)))
 
 ;;; MOVSD, MOVSS
 (macrolet ((define-movsd/ss-sse-inst (name prefix op)
diff --git a/src/general-info/release-20d.txt b/src/general-info/release-20d.txt
index 5d4bce960..0a5c2246e 100644
--- a/src/general-info/release-20d.txt
+++ b/src/general-info/release-20d.txt
@@ -42,6 +42,7 @@ New in this release:
     * Updated to Unicode 6.1.0.
     * Many additional aliases for external formats added that match
       the glibc iconv aliases.
+    * Implement faster LOGCOUNT function, if :SSE3 feature is available.
       
   * ANSI compliance fixes:
     * CMUCL was not printing pathnames like (make-pathname :directory
-- 
GitLab