From: Paul Khuong Date: Tue, 21 May 2013 19:10:50 +0000 (-0400) Subject: Front end infrastructure for short vector SIMD packs X-Git-Url: http://repo.macrolet.net/gitweb/?a=commitdiff_plain;h=b38f10027f48f657f77b290719da4fec30064e25;p=sbcl.git Front end infrastructure for short vector SIMD packs * 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. --- diff --git a/base-target-features.lisp-expr b/base-target-features.lisp-expr index 74bf083..131f517 100644 --- a/base-target-features.lisp-expr +++ b/base-target-features.lisp-expr @@ -152,6 +152,11 @@ ; :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 diff --git a/package-data-list.lisp-expr b/package-data-list.lisp-expr index a01f3d0..4b3c99b 100644 --- a/package-data-list.lisp-expr +++ b/package-data-list.lisp-expr @@ -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" diff --git a/src/code/class.lisp b/src/code/class.lisp index 19edd29..f6224ec 100644 --- a/src/code/class.lisp +++ b/src/code/class.lisp @@ -1104,6 +1104,9 @@ :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 diff --git a/src/code/early-type.lisp b/src/code/early-type.lisp index 1b395f1..20f1642 100644 --- a/src/code/early-type.lisp +++ b/src/code/early-type.lisp @@ -533,6 +533,29 @@ (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))))))) + ;;;; type utilities diff --git a/src/code/late-type.lisp b/src/code/late-type.lisp index 697b775..481a843 100644 --- a/src/code/late-type.lisp +++ b/src/code/late-type.lisp @@ -3494,6 +3494,60 @@ used for a COMPLEX component.~:@>" *wild-type* (specifier-type element-type))))) +;;;; 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)) + ;;;; utilities shared between cross-compiler and target system ;;; Does the type derived from compilation of an actual function diff --git a/src/compiler/generic/vm-fndb.lisp b/src/compiler/generic/vm-fndb.lisp index c988c25..37273c1 100644 --- a/src/compiler/generic/vm-fndb.lisp +++ b/src/compiler/generic/vm-fndb.lisp @@ -199,6 +199,44 @@ (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 diff --git a/src/compiler/x86-64/parms.lisp b/src/compiler/x86-64/parms.lisp index 3bb0851..7d90673 100644 --- a/src/compiler/x86-64/parms.lisp +++ b/src/compiler/x86-64/parms.lisp @@ -204,3 +204,6 @@ 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))