* 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.
; :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
"%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"
"%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"
"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"
: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
(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
*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
(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
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))