feat(sb-simd): add modular AVX-512_FP16 vector support (f16.32, f16.16, f16.8)

- cpu-identification.lisp: add avx512fp16-supported-p detection via CPUID
  leaf 7 subleaf 0 EDX bit 23.
- packages.lisp: export avx512fp16-supported-p and define sb-simd-avx512fp16
  package extending sb-simd-avx512dq.
- instruction-sets/avx512fp16.lisp: define :avx512fp16 instruction set
  introducing half-precision float vectors:
  * f16.32 (512-bit ZMM, 32 lanes)
  * f16.16 (256-bit YMM, 16 lanes)
  * f16.8 (128-bit XMM, 8 lanes)
  * Vector arithmetic (vaddph, vsubph, vmulph, vdivph, vsqrtph, vminph,
    vmaxph, vrcpph, vrsqrtph, vscalefph)
  * FMA with :encoding :fma (vfmadd213ph, vfmsub213ph, vfnmadd213ph, vfnmsub213ph)
  * Conversions (f32.16 <-> f16.16, s32.16 <-> f16.16)
  * Bitwise logic and casts
- define-custom-vops.lisp: add f16.32-not to def-not macrolet.
- x86-64-fake-vops.lisp: add f16.8-broadcast, f16.16-broadcast, and
  f16.32-broadcast fake VOPs.
- record.lisp & test-suite/utilities.lisp: replace deprecated
  :sb-simd-pack-256 and :sb-simd-pack-512 feature guards with :x86-64.
- test-packages.lisp: validate sb-simd-avx512fp16 symbol bindings.
This commit is contained in:
Aaron Estrada 2026-09-06 13:43:37 -06:00 committed by Stas Boukarev
parent 16a029c1e0
commit 0dc8bb88d2
9 changed files with 229 additions and 10 deletions

View file

@ -60,7 +60,12 @@
(defun avx512vl-supported-p ()
(and (>= (cpuid 0) 7)
(logbitp 31 (nth-value 1 (cpuid 7 0))))))
(logbitp 31 (nth-value 1 (cpuid 7 0)))))
(defun avx512fp16-supported-p ()
(and (>= (cpuid 0) 7)
(avx512f-supported-p)
(logbitp 23 (nth-value 3 (cpuid 7 0))))))
#-x86-64
(progn
@ -104,6 +109,9 @@
nil)
(defun avx512vl-supported-p ()
nil)
(defun avx512fp16-supported-p ()
nil))
(defun neon-supported-p ()

View file

@ -365,7 +365,8 @@
(def-not sb-simd-avx512bw::u8.64-not)
(def-not sb-simd-avx512bw::u16.32-not)
(def-not sb-simd-avx512bw::s8.64-not)
(def-not sb-simd-avx512bw::s16.32-not)))
(def-not sb-simd-avx512bw::s16.32-not)
(def-not sb-simd-avx512fp16::f16.32-not)))
;; Neon
#+arm64
(progn

View file

@ -0,0 +1,121 @@
(in-package #:sb-simd-avx512fp16)
(define-instruction-set :avx512fp16
(:test (avx512fp16-supported-p))
(:include :avx512dq)
(:scalars
(f16 16 (unsigned-byte 16) #:unsigned-num (#:unsigned-reg)))
(:simd-packs
(f16.32 f16 512 #:simd-pack-512-ub16 (#:int-avx512-reg))
(f16.16 f16 256 #:simd-pack-256-ub16 (#:int-avx2-reg))
(f16.8 f16 128 #:simd-pack-ub16 (#:int-sse-reg)))
(:simd-casts
(f16.32 f16.32-broadcast)
(f16.16 f16.16-broadcast)
(f16.8 f16.8-broadcast))
(:reinterpret-casts
(f16.32! f16.32!-from-p128 f16.32!-from-p256 f16.32!-from-p512)
(f16.16! f16.16!-from-p128 f16.16!-from-p256 f16.16!-from-p512)
(f16.8! f16.8!-from-p128 f16.8!-from-p256 f16.8!-from-p512))
(:instructions
;; Reinterprets
(f16.32!-from-p128 #:vmovdqu64 (f16.32) (p128) :cost 1 :encoding :move :always-translatable nil)
(f16.32!-from-p256 #:vmovdqu64 (f16.32) (p256) :cost 1 :encoding :move :always-translatable nil)
(f16.32!-from-p512 #:vmovdqu64 (f16.32) (p512) :cost 1 :encoding :move :always-translatable nil)
(f16.16!-from-p128 #:vmovdqu (f16.16) (p128) :cost 1 :encoding :move :always-translatable nil)
(f16.16!-from-p256 #:vmovdqu (f16.16) (p256) :cost 1 :encoding :move :always-translatable nil)
(f16.16!-from-p512 #:vextracti32x8 (f16.16) (p512) :cost 1 :suffix '(0) :always-translatable nil)
(f16.8!-from-p128 #:movdqu (f16.8) (p128) :cost 1 :encoding :move :always-translatable nil)
(f16.8!-from-p256 #:vextracti128 (f16.8) (p256) :cost 1 :suffix '(0) :always-translatable nil)
(f16.8!-from-p512 #:vextracti32x4 (f16.8) (p512) :cost 1 :suffix '(0) :always-translatable nil)
;; f16.32
(f16.32-broadcast nil (f16.32) (f16) :cost 1 :encoding :fake-vop)
(two-arg-f16.32+ #:vaddph (f16.32) (f16.32 f16.32) :cost 1 :associative t)
(two-arg-f16.32- #:vsubph (f16.32) (f16.32 f16.32) :cost 1)
(two-arg-f16.32* #:vmulph (f16.32) (f16.32 f16.32) :cost 1 :associative t)
(two-arg-f16.32/ #:vdivph (f16.32) (f16.32 f16.32) :cost 1)
(f16.32-sqrt #:vsqrtph (f16.32) (f16.32) :cost 1)
(two-arg-f16.32-min #:vminph (f16.32) (f16.32 f16.32) :cost 1 :associative t)
(two-arg-f16.32-max #:vmaxph (f16.32) (f16.32 f16.32) :cost 1 :associative t)
(f16.32-rcp #:vrcpph (f16.32) (f16.32) :cost 1)
(f16.32-rsqrt #:vrsqrtph (f16.32) (f16.32) :cost 1)
(f16.32-scalef #:vscalefph (f16.32) (f16.32 f16.32) :cost 1)
(f16.32-fmadd #:vfmadd213ph (f16.32) (f16.32 f16.32 f16.32) :cost 1 :encoding :fma)
(f16.32-fmsub #:vfmsub213ph (f16.32) (f16.32 f16.32 f16.32) :cost 1 :encoding :fma)
(f16.32-fnmadd #:vfnmadd213ph (f16.32) (f16.32 f16.32 f16.32) :cost 1 :encoding :fma)
(f16.32-fnmsub #:vfnmsub213ph (f16.32) (f16.32 f16.32 f16.32) :cost 1 :encoding :fma)
(two-arg-f16.32-and #:vpandd (f16.32) (f16.32 f16.32) :cost 1 :associative t)
(two-arg-f16.32-or #:vpord (f16.32) (f16.32 f16.32) :cost 1 :associative t)
(two-arg-f16.32-xor #:vpxord (f16.32) (f16.32 f16.32) :cost 1 :associative t)
(f16.32-andc1 #:vpandnd (f16.32) (f16.32 f16.32) :cost 1)
(f16.32-not nil (f16.32) (f16.32) :cost 1 :encoding :custom)
;; f16.16
(f16.16-broadcast nil (f16.16) (f16) :cost 1 :encoding :fake-vop)
(two-arg-f16.16+ #:vaddph (f16.16) (f16.16 f16.16) :cost 1 :associative t)
(two-arg-f16.16- #:vsubph (f16.16) (f16.16 f16.16) :cost 1)
(two-arg-f16.16* #:vmulph (f16.16) (f16.16 f16.16) :cost 1 :associative t)
(two-arg-f16.16/ #:vdivph (f16.16) (f16.16 f16.16) :cost 1)
(f16.16-sqrt #:vsqrtph (f16.16) (f16.16) :cost 1)
(two-arg-f16.16-min #:vminph (f16.16) (f16.16 f16.16) :cost 1 :associative t)
(two-arg-f16.16-max #:vmaxph (f16.16) (f16.16 f16.16) :cost 1 :associative t)
(f16.16-rcp #:vrcpph (f16.16) (f16.16) :cost 1)
(f16.16-rsqrt #:vrsqrtph (f16.16) (f16.16) :cost 1)
(f16.16-fmadd #:vfmadd213ph (f16.16) (f16.16 f16.16 f16.16) :cost 1 :encoding :fma)
(f16.16-fmsub #:vfmsub213ph (f16.16) (f16.16 f16.16 f16.16) :cost 1 :encoding :fma)
(f16.16-fnmadd #:vfnmadd213ph (f16.16) (f16.16 f16.16 f16.16) :cost 1 :encoding :fma)
(f16.16-fnmsub #:vfnmsub213ph (f16.16) (f16.16 f16.16 f16.16) :cost 1 :encoding :fma)
;; f16.8
(f16.8-broadcast nil (f16.8) (f16) :cost 1 :encoding :fake-vop)
(two-arg-f16.8+ #:vaddph (f16.8) (f16.8 f16.8) :cost 1 :associative t)
(two-arg-f16.8- #:vsubph (f16.8) (f16.8 f16.8) :cost 1)
(two-arg-f16.8* #:vmulph (f16.8) (f16.8 f16.8) :cost 1 :associative t)
(two-arg-f16.8/ #:vdivph (f16.8) (f16.8 f16.8) :cost 1)
(f16.8-sqrt #:vsqrtph (f16.8) (f16.8) :cost 1)
(two-arg-f16.8-min #:vminph (f16.8) (f16.8 f16.8) :cost 1 :associative t)
(two-arg-f16.8-max #:vmaxph (f16.8) (f16.8 f16.8) :cost 1 :associative t)
(f16.8-rcp #:vrcpph (f16.8) (f16.8) :cost 1)
(f16.8-rsqrt #:vrsqrtph (f16.8) (f16.8) :cost 1)
(f16.8-fmadd #:vfmadd213ph (f16.8) (f16.8 f16.8 f16.8) :cost 1 :encoding :fma)
(f16.8-fmsub #:vfmsub213ph (f16.8) (f16.8 f16.8 f16.8) :cost 1 :encoding :fma)
(f16.8-fnmadd #:vfnmadd213ph (f16.8) (f16.8 f16.8 f16.8) :cost 1 :encoding :fma)
(f16.8-fnmsub #:vfnmsub213ph (f16.8) (f16.8 f16.8 f16.8) :cost 1 :encoding :fma)
;; Conversions
(f32.16-from-f16.16 #:vcvtph2psx (f32.16) (f16.16) :cost 3)
(f16.16-from-f32.16 #:vcvtps2phx (f16.16) (f32.16) :cost 3)
(f16.16-from-s32.16 #:vcvtdq2ph (f16.16) (s32.16) :cost 3)
(s32.16-from-f16.16 #:vcvtph2dq (s32.16) (f16.16) :cost 3))
(:associatives
(f16.32+ two-arg-f16.32+ 0)
(f16.32* two-arg-f16.32* 1)
(f16.32-min two-arg-f16.32-min nil)
(f16.32-max two-arg-f16.32-max nil)
(f16.32-and two-arg-f16.32-and +u16-true+)
(f16.32-or two-arg-f16.32-or +u16-false+)
(f16.32-xor two-arg-f16.32-xor +u16-false+)
(f16.16+ two-arg-f16.16+ 0)
(f16.16* two-arg-f16.16* 1)
(f16.16-min two-arg-f16.16-min nil)
(f16.16-max two-arg-f16.16-max nil)
(f16.8+ two-arg-f16.8+ 0)
(f16.8* two-arg-f16.8* 1)
(f16.8-min two-arg-f16.8-min nil)
(f16.8-max two-arg-f16.8-max nil))
(:reducers
(f16.32- two-arg-f16.32- 0)
(f16.32/ two-arg-f16.32/ 1)
(f16.16- two-arg-f16.16- 0)
(f16.16/ two-arg-f16.16/ 1)
(f16.8- two-arg-f16.8- 0)
(f16.8/ two-arg-f16.8/ 1)))

View file

@ -257,6 +257,7 @@
#:avx512cd-supported-p
#:avx512bw-supported-p
#:avx512vl-supported-p
#:avx512fp16-supported-p
#:neon-supported-p))
(progn
@ -2513,6 +2514,83 @@
#:u64.8*
#:s64.8*))
#+x86-64
(defpackage #:sb-simd-avx512fp16
(:use #:common-lisp #:sb-simd-internals #:sb-simd-avx512dq)
#0#
#1#
#8#
#9#
#10#
#12#
#13#
#14#
#15=
(:export
#:f16
;; f16.32
#:f16.32
#:f16.32!
#:f16.32-broadcast
#:f16.32+
#:f16.32-
#:f16.32*
#:f16.32/
#:f16.32-sqrt
#:f16.32-min
#:f16.32-max
#:f16.32-rcp
#:f16.32-rsqrt
#:f16.32-scalef
#:f16.32-fmadd
#:f16.32-fmsub
#:f16.32-fnmadd
#:f16.32-fnmsub
#:f16.32-and
#:f16.32-or
#:f16.32-xor
#:f16.32-andc1
#:f16.32-not
;; f16.16
#:f16.16
#:f16.16!
#:f16.16-broadcast
#:f16.16+
#:f16.16-
#:f16.16*
#:f16.16/
#:f16.16-sqrt
#:f16.16-min
#:f16.16-max
#:f16.16-rcp
#:f16.16-rsqrt
#:f16.16-fmadd
#:f16.16-fmsub
#:f16.16-fnmadd
#:f16.16-fnmsub
;; f16.8
#:f16.8
#:f16.8!
#:f16.8-broadcast
#:f16.8+
#:f16.8-
#:f16.8*
#:f16.8/
#:f16.8-sqrt
#:f16.8-min
#:f16.8-max
#:f16.8-rcp
#:f16.8-rsqrt
#:f16.8-fmadd
#:f16.8-fmsub
#:f16.8-fnmadd
#:f16.8-fnmsub
;; conversions
#:f32.16-from-f16.16
#:f16.16-from-f32.16
#:f16.16-from-s32.16
#:s32.16-from-f16.16))
#+arm64
(defpackage #:sb-simd-arm64
(:use #:common-lisp #:sb-simd-internals #:sb-simd)

View file

@ -181,14 +181,14 @@
(defun scalar-record-p (x)
(typep x '(and value-record (not simd-record))))
#-sb-simd-pack-256
#-(or x86-64 sb-simd-pack-256)
(progn
(defstruct phony-simd-pack-256)
(deftype simd-pack-256 (&optional element-type)
(declare (ignore element-type))
'phony-simd-pack-256))
#-sb-simd-pack-512
#-(or x86-64 sb-simd-pack-512)
(progn
(defstruct phony-simd-pack-512)
(deftype simd-pack-512 (&optional element-type)
@ -202,10 +202,10 @@
(ecase bits
(128 (find-symbol "SIMD-PACK" "SB-EXT"))
(256 (or (find-symbol "SIMD-PACK-256" "SB-EXT")
#-sb-simd-pack-256
#-(or x86-64 sb-simd-pack-256)
'simd-pack-256))
(512 (or (find-symbol "SIMD-PACK-512" "SB-EXT")
#-sb-simd-pack-512
#-(or x86-64 sb-simd-pack-512)
'simd-pack-512)))))
(cond ((not base-type) 't)
((not scalar-record-name) base-type)

View file

@ -1545,3 +1545,12 @@
(define-fake-vop s16.32!-from-s16 (x)
(%s16.32-broadcast x))
(define-fake-vop sb-simd-avx512fp16:f16.8-broadcast (x)
(sb-simd-avx512fp16::%f16.8!-from-p128 (sb-simd-sse2::%u16.8-broadcast x)))
(define-fake-vop sb-simd-avx512fp16:f16.16-broadcast (x)
(sb-simd-avx512fp16::%f16.16!-from-p256 (sb-simd-avx::%u16.16-broadcast x)))
(define-fake-vop sb-simd-avx512fp16:f16.32-broadcast (x)
(sb-simd-avx512fp16::%f16.32!-from-p512 (sb-simd-avx512bw::%u16.32-broadcast x)))

View file

@ -34,6 +34,7 @@
(:file "avx512f" :if-feature :x86-64)
(:file "avx512bw" :if-feature :x86-64)
(:file "avx512dq" :if-feature :x86-64)
(:file "avx512fp16" :if-feature :x86-64)
(:file "arm64" :if-feature :arm64)
(:file "neon" :if-feature :arm64)))
(:file "define-types")

View file

@ -18,7 +18,8 @@
(check-package '#:sb-simd-avx2)
(check-package '#:sb-simd-avx512f :skip '(f32-fmaddsub f32-fmsubadd f64-fmaddsub f64-fmsubadd))
(check-package '#:sb-simd-avx512bw :skip '(f32-fmaddsub f32-fmsubadd f64-fmaddsub f64-fmsubadd))
(check-package '#:sb-simd-avx512dq :skip '(f32-fmaddsub f32-fmsubadd f64-fmaddsub f64-fmsubadd)))
(check-package '#:sb-simd-avx512dq :skip '(f32-fmaddsub f32-fmsubadd f64-fmaddsub f64-fmsubadd))
(check-package '#:sb-simd-avx512fp16 :skip '(f32-fmaddsub f32-fmsubadd f64-fmaddsub f64-fmsubadd)))
#+arm64
(check-package '#:sb-simd-neon)
;; Ensure that every instruction has a corresponding VOP.

View file

@ -43,7 +43,7 @@
(sb-vm::%simd-pack-ref-64 pack 2)
(sb-vm::%simd-pack-ref-64 pack 3)))
#+sb-simd-pack-512
#+(or x86-64 sb-simd-pack-512)
(defun %simd-pack-512-ub64s (pack)
(values (sb-vm::%simd-pack-ref-64 pack 0)
(sb-vm::%simd-pack-ref-64 pack 1)
@ -61,13 +61,13 @@
(multiple-value-bind (a0 a1) (%simd-pack-ub64s a)
(multiple-value-bind (b0 b1) (%simd-pack-ub64s b)
(and (= a0 b0) (= a1 b1))))))
#+sb-simd-pack-256
#+(or x86-64 sb-simd-pack-256)
(sb-ext:simd-pack-256
(when (sb-ext:simd-pack-256-p b)
(multiple-value-bind (a0 a1 a2 a3) (%simd-pack-256-ub64s a)
(multiple-value-bind (b0 b1 b2 b3) (%simd-pack-256-ub64s b)
(and (= a0 b0) (= a1 b1) (= a2 b2) (= a3 b3))))))
#+sb-simd-pack-512
#+(or x86-64 sb-simd-pack-512)
(sb-ext:simd-pack-512
(when (sb-ext:simd-pack-512-p b)
(multiple-value-bind (a0 a1 a2 a3 a4 a5 a6 a7) (%simd-pack-512-ub64s a)