Front end infrastructure for short vector SIMD packs
authorPaul Khuong <pvk@pvk.ca>
Tue, 21 May 2013 19:10:50 +0000 (15:10 -0400)
committerPaul Khuong <pvk@pvk.ca>
Tue, 21 May 2013 19:10:50 +0000 (15:10 -0400)
 * new feature, sb-simd-pack.

 * define a new IR1 type for SIMD packs:
   - (SB!KERNEL:SIMD-PACK [eltype]), where [eltype] is a subtype
     of the plaform-specific SIMD element type universe, or * (default),
     the union of all these possibilities;
   - Element types are always upgraded to the platform's element type
     (small) universe, so we can easily manipulate unions of SIMD-PACK
     types by working in terms of the element types.

 * immediately specify the universe of SIMD pack element types
   (sb!kernel:*simd-pack-element-types*) for x86-64, to ensure
   #!+sb-simd-pack buildability.

 * declare basic functions to create/manipulate SIMD packs:
   - simd-pack-p is the basic type predicate;
   - %simd-pack-tag returns a fixnum tag associated with each SIMD-PACK;
     currently, we suppose it only encodes the element type, as the
     position of the element type in *simd-pack-element-types*;
   - %make-simd-pack creates a 128-bit SIMD pack from a tag and two
     64 bit integers;
   - %make-simd-pack-double creates an appropriately-tagged pack from
     two double floats;
   - %make-simd-pack-single creates a tagged pack from four single
     floats;
   - %make-simd-pack-ub{32,64} creates a tagged pack from four 32 bit
     or two 64 bit integers;
   - %simd-pack-{low,high} returns the low/high integer half of a
     128 bit pack;
   - %simd-pack-ub{32,64}s returns the four integer quarters or two
     integer halves of a 128 bit pack;
   - %simd-pack-singles returns the four singles in a 128 bit pack;
   - %simd-pack-doubles returns the two doubles in a 128 bit pack.

Alexander Gavrilov kept a branch alive for the last couple years. The
creation/manipulation primitives are largely taken from that branch,
or informed by the branch's usage.

base-target-features.lisp-expr
package-data-list.lisp-expr
src/code/class.lisp
src/code/early-type.lisp
src/code/late-type.lisp
src/compiler/generic/vm-fndb.lisp
src/compiler/x86-64/parms.lisp

index 74bf083..131f517 100644 (file)
  ; :sb-hash-table-debug
 
  ;; Enabled automatically by make-config.sh for platforms which implement
+ ;; short vector SIMD intrinsics.
+ ;;
+ ; :sb-simd-pack
+
+ ;; Enabled automatically by make-config.sh for platforms which implement
  ;; the %READ-CYCLE-COUNTER VOP. Can be disabled manually: affects TIME.
  ;;
  ;; FIXME: Should this be :SB-CYCLE-COUNTER instead? If so, then the same goes
index a01f3d0..4b3c99b 100644 (file)
@@ -1370,6 +1370,11 @@ is a good idea, but see SB-SYS re. blurring of boundaries."
                "%MAKE-FUNCALLABLE-STRUCTURE-INSTANCE-ALLOCATOR"
                "%MAKE-RATIO" "%MAKE-LISP-OBJ"
                "%MAKE-INSTANCE"
+               #!+sb-simd-pack "%MAKE-SIMD-PACK"
+               #!+sb-simd-pack "%MAKE-SIMD-PACK-UB32"
+               #!+sb-simd-pack "%MAKE-SIMD-PACK-UB64"
+               #!+sb-simd-pack "%MAKE-SIMD-PACK-DOUBLE"
+               #!+sb-simd-pack "%MAKE-SIMD-PACK-SINGLE"
                "%MAKE-STRUCTURE-INSTANCE"
                "%MAKE-STRUCTURE-INSTANCE-ALLOCATOR"
                "%MAP" "%MAP-TO-SIMPLE-VECTOR-ARITY-1"
@@ -1433,6 +1438,13 @@ is a good idea, but see SB-SYS re. blurring of boundaries."
                "%SET-SYMBOL-HASH"
                "%SIN" "%SIN-QUICK" "%SINGLE-FLOAT"
                "%SINH" "%SQRT" "%SXHASH-SIMPLE-STRING"
+               #!+sb-simd-pack "%SIMD-PACK-TAG"
+               #!+sb-simd-pack "%SIMD-PACK-LOW"
+               #!+sb-simd-pack "%SIMD-PACK-HIGH"
+               #!+sb-simd-pack "%SIMD-PACK-UB32S"
+               #!+sb-simd-pack "%SIMD-PACK-UB64S"
+               #!+sb-simd-pack "%SIMD-PACK-SINGLES"
+               #!+sb-simd-pack "%SIMD-PACK-DOUBLES"
                "%SXHASH-SIMPLE-SUBSTRING" "%TAN" "%TAN-QUICK" "%TANH"
                "%UNARY-ROUND"
                "%UNARY-TRUNCATE"
@@ -1736,6 +1748,11 @@ is a good idea, but see SB-SYS re. blurring of boundaries."
                "SINGLE-FLOAT-INT-EXPONENT" "SINGLE-FLOAT-SIGNIFICAND"
                "SINGLE-VALUE-TYPE" "SINGLE-VALUE-SPECIFIER-TYPE"
                "SPECIALIZABLE" "SPECIALIZABLE-VECTOR" "SPECIFIER-TYPE"
+               #!+sb-simd-pack "SIMD-PACK"
+               #!+sb-simd-pack "SIMD-PACK-P"
+               #!+sb-simd-pack "SIMD-PACK-TYPE"
+               #!+sb-simd-pack "SIMD-PACK-TYPE-ELEMENT-TYPE"
+               #!+sb-simd-pack "*SIMD-PACK-ELEMENT-TYPES*"
                "STACK-REF" "STREAM-DESIGNATOR" "STRING-DESIGNATOR"
                "STRING-FILL*"
                "STRUCTURE-RAW-SLOT-TYPE-AND-SIZE" "SUB-GC"
index 19edd29..f6224ec 100644 (file)
       :inherits (complex number)
       :codes (#.sb!vm:complex-long-float-widetag)
       :prototype-form (complex 42l0 42l0))
+     #!+sb-simd-pack
+     (simd-pack
+      :translation simd-pack)
      (real :translation real :inherits (number))
      (float
       :translation float
index 1b395f1..20f1642 100644 (file)
          (t (values min :maybe))))
     ()))
 
+;;; A SIMD-PACK-TYPE is used to represent a SIMD-PACK type.
+#!+sb-simd-pack
+(defstruct (simd-pack-type
+            (:include ctype (class-info (type-class-or-lose 'simd-pack)))
+            (:constructor %make-simd-pack-type (element-type))
+            (:copier nil))
+  (element-type (missing-arg)
+   :type (cons #||(member #.*simd-pack-element-types*) ||#)
+   :read-only t))
+
+#!+sb-simd-pack
+(defun make-simd-pack-type (element-type)
+  (aver (neq element-type *wild-type*))
+  (if (eq element-type *empty-type*)
+      *empty-type*
+      (%make-simd-pack-type
+       (dolist (pack-type *simd-pack-element-types*
+                          (error "~S element type must be a subtype of ~
+                                     ~{~S~#[~;, or ~:;, ~]~}."
+                                 'simd-pack *simd-pack-element-types*))
+         (when (csubtypep element-type (specifier-type pack-type))
+           (return (list pack-type)))))))
+
 \f
 ;;;; type utilities
 
index 697b775..481a843 100644 (file)
@@ -3494,6 +3494,60 @@ used for a COMPLEX component.~:@>"
                                       *wild-type*
                                       (specifier-type element-type)))))
 \f
+;;;; SIMD-PACK types
+#!+sb-simd-pack
+(progn
+  (!define-type-class simd-pack)
+
+  (!def-type-translator simd-pack (&optional (element-type-spec '*))
+     (if (eql element-type-spec '*)
+         (%make-simd-pack-type *simd-pack-element-types*)
+         (make-simd-pack-type (single-value-specifier-type element-type-spec))))
+
+  (!define-type-method (simd-pack :negate) (type)
+     (let ((remaining (set-difference *simd-pack-element-types*
+                                      (simd-pack-type-element-type type)))
+           (not-simd-pack (make-negation-type :type (specifier-type 'simd-pack))))
+       (if remaining
+           (type-union2 not-simd-pack (%make-simd-pack-type remaining))
+           not-simd-pack)))
+
+  (!define-type-method (simd-pack :unparse) (type)
+     (let ((eltypes (simd-pack-type-element-type type)))
+       (cond ((equal eltypes *simd-pack-element-types*)
+              'simd-pack)
+             ((= 1 (length eltypes))
+              `(simd-pack ,(first eltypes)))
+             (t
+              `(or ,@(mapcar (lambda (eltype)
+                               `(simd-pack ,eltype))
+                             eltypes))))))
+
+  (!define-type-method (simd-pack :simple-=) (type1 type2)
+     (declare (type simd-pack-type type1 type2))
+     (null (set-exclusive-or (simd-pack-type-element-type type1)
+                             (simd-pack-type-element-type type2))))
+
+  (!define-type-method (simd-pack :simple-subtypep) (type1 type2)
+     (declare (type simd-pack-type type1 type2))
+     (subsetp (simd-pack-type-element-type type1)
+              (simd-pack-type-element-type type2)))
+
+  (!define-type-method (simd-pack :simple-union2) (type1 type2)
+     (declare (type simd-pack-type type1 type2))
+     (%make-simd-pack-type (union (simd-pack-type-element-type type1)
+                                  (simd-pack-type-element-type type2))))
+
+  (!define-type-method (simd-pack :simple-intersection2) (type1 type2)
+     (declare (type simd-pack-type type1 type2))
+     (let ((intersection (intersection (simd-pack-type-element-type type1)
+                                       (simd-pack-type-element-type type2))))
+       (if intersection
+           (%make-simd-pack-type intersection)
+           *empty-type*)))
+
+  (!define-superclasses simd-pack ((simd-pack)) !cold-init-forms))
+\f
 ;;;; utilities shared between cross-compiler and target system
 
 ;;; Does the type derived from compilation of an actual function
index c988c25..37273c1 100644 (file)
 (defknown make-value-cell (t) t
   (flushable movable))
 
+#!+sb-simd-pack
+(progn
+  (defknown simd-pack-p (t) boolean (foldable movable flushable))
+  (defknown %simd-pack-tag (simd-pack) fixnum (movable flushable))
+  (defknown %make-simd-pack (fixnum (unsigned-byte 64) (unsigned-byte 64))
+      simd-pack
+      (flushable movable foldable))
+  (defknown %make-simd-pack-double (double-float double-float)
+      (simd-pack double-float)
+      (flushable movable foldable))
+  (defknown %make-simd-pack-single (single-float single-float
+                                    single-float single-float)
+      (simd-pack single-float)
+      (flushable movable foldable))
+  (defknown %make-simd-pack-ub32 ((unsigned-byte 32) (unsigned-byte 32)
+                                  (unsigned-byte 32) (unsigned-byte 32))
+      (simd-pack integer)
+      (flushable movable foldable))
+  (defknown %make-simd-pack-ub64 ((unsigned-byte 64) (unsigned-byte 64))
+      (simd-pack integer)
+      (flushable movable foldable))
+  (defknown (%simd-pack-low %simd-pack-high) (simd-pack)
+      (unsigned-byte 64)
+      (flushable movable foldable))
+  (defknown %simd-pack-ub32s (simd-pack)
+      (values (unsigned-byte 32) (unsigned-byte 32)
+              (unsigned-byte 32) (unsigned-byte 32))
+      (flushable movable foldable))
+  (defknown %simd-pack-ub64s (simd-pack)
+      (values (unsigned-byte 64) (unsigned-byte 64))
+      (flushable movable foldable))
+  (defknown %simd-pack-singles (simd-pack)
+      (values single-float single-float single-float single-float)
+      (flushable movable foldable))
+  (defknown %simd-pack-doubles (simd-pack)
+      (values double-float double-float)
+      (flushable movable foldable)))
+
 ;;;; threading
 
 (defknown (dynamic-space-free-pointer binding-stack-pointer-sap
index 3bb0851..7d90673 100644 (file)
     sb!kernel:two-arg-xor
     sb!kernel:two-arg-gcd
     sb!kernel:two-arg-lcm))
+
+#!+sb-simd-pack
+(defvar *simd-pack-element-types* '(integer single-float double-float))