master: sb-simd: Fix a bunch of bugs
stassats via Sbcl-commits <[email protected]>
| Newsgroups | gmane.lisp.steel-bank.cvs |
|---|---|
| Message-ID | <[email protected]> |
The branch "master" has been updated in SBCL:
via e4e628ab84b1832297cedeb2d2613509cb6a601d (commit)
from 62f4bd103264bf1c92fb4fc68305b8307fdd06fb (commit)
- Log -----------------------------------------------------------------
commit e4e628ab84b1832297cedeb2d2613509cb6a601d
Author: Sylvia Harrington <[email protected]>
Date: Wed Aug 26 19:02:38 2026 +0100
sb-simd: Fix a bunch of bugs
64-bit integer min/max don't have actual instructions, fake instead
Fix signed lane extraction not sign-extending
Add float abs/neg
Fix fsqrt encoding
Fix u32.4-from-u64.2/s32.4-from-s64.2 family, wrong size
Remove 64-bit integer vector mul, instruction doesn't exist
Add missing exports for integer min/max
Align spilled neon registers properly
Validate more vector instruction forms properly
Fix movi immediates
---
contrib/sb-simd/code/arm64-fake-vops.lisp | 12 ++
contrib/sb-simd/code/define-custom-vops.lisp | 5 +-
contrib/sb-simd/code/instruction-sets/neon.lisp | 34 ++--
contrib/sb-simd/code/packages.lisp | 22 ++-
.../sb-simd/test-suite/test-arm64-regressions.lisp | 179 +++++++++++++++++++++
.../test-simple-simd-functions-arm64.lisp | 20 +++
src/compiler/arm64/insts.lisp | 145 +++++++++--------
src/compiler/arm64/simd-pack.lisp | 8 +-
src/compiler/arm64/vm.lisp | 6 +-
tests/sb-simd.impure.lisp | 1 +
10 files changed, 340 insertions(+), 92 deletions(-)
diff --git a/contrib/sb-simd/code/arm64-fake-vops.lisp b/contrib/sb-simd/code/arm64-fake-vops.lisp
index c8a6f7605..cacdde336 100644
--- a/contrib/sb-simd/code/arm64-fake-vops.lisp
+++ b/contrib/sb-simd/code/arm64-fake-vops.lisp
@@ -109,6 +109,12 @@
(define-fake-vop u64.2-horizontal+ (a)
(sb-simd::%two-arg-u64+ (%u64.2-lane-extract a 0) (%u64.2-lane-extract a 1)))
+(define-fake-vop two-arg-u64.2-min (a b)
+ (%u64.2-bit-select (%two-arg-u64.2> b a) a b))
+
+(define-fake-vop two-arg-u64.2-max (a b)
+ (%u64.2-bit-select (%two-arg-u64.2> a b) a b))
+
(define-fake-vop s64.2-pair-min (a b)
(%make-s64.2 (sb-simd::%two-arg-s64-min (%s64.2-lane-extract a 0) (%s64.2-lane-extract a 1))
(sb-simd::%two-arg-s64-min (%s64.2-lane-extract b 0) (%s64.2-lane-extract b 1))))
@@ -129,3 +135,9 @@
(define-fake-vop s64.2-horizontal+ (a)
(sb-simd::%two-arg-s64+ (%s64.2-lane-extract a 0) (%s64.2-lane-extract a 1)))
+
+(define-fake-vop two-arg-s64.2-min (a b)
+ (%s64.2-bit-select (%two-arg-s64.2> b a) a b))
+
+(define-fake-vop two-arg-s64.2-max (a b)
+ (%s64.2-bit-select (%two-arg-s64.2> a b) a b))
diff --git a/contrib/sb-simd/code/define-custom-vops.lisp b/contrib/sb-simd/code/define-custom-vops.lisp
index af0456cc4..873f55176 100644
--- a/contrib/sb-simd/code/define-custom-vops.lisp
+++ b/contrib/sb-simd/code/define-custom-vops.lisp
@@ -313,7 +313,10 @@
(:info lane)
(:results (dst :scs (,scalar-reg)))
(:generator
- (inst umov dst src lane ,element)))
+ (inst ,(if (and (eql sign :s) (not (eql width 64)))
+ 'smov
+ 'umov)
+ dst src lane ,element)))
(define-custom-vop ,(name "~a~d.~d-LANE-INSERT" sign width count)
(:args (src1 :scs (int-neon-reg) :target dst)
(src2 :scs (,scalar-reg) :to :save))
diff --git a/contrib/sb-simd/code/instruction-sets/neon.lisp b/contrib/sb-simd/code/instruction-sets/neon.lisp
index 52d2f9c3d..096d583a5 100644
--- a/contrib/sb-simd/code/instruction-sets/neon.lisp
+++ b/contrib/sb-simd/code/instruction-sets/neon.lisp
@@ -85,6 +85,8 @@
(f32.4-andc2 #:bic (f32.4) (f32.4 f32.4) :cost 1 :suffix '(:16b))
(f32.4-not #:not (f32.4) (f32.4) :cost 1 :suffix '(:16b))
(f32.4-sqrt #:fsqrt (f32.4) (f32.4) :cost 15 :suffix '(:4s))
+ (f32.4-abs #:fabs (f32.4) (f32.4) :cost 1 :suffix '(:4s))
+ (f32.4-neg #:fneg (f32.4) (f32.4) :cost 1 :suffix '(:4s))
(f32.4-bit-select #:bsl (f32.4) (u32.4 f32.4 f32.4) :cost 1 :encoding :neon-rmw :suffix '(:16b))
(f32.4-lane-extract nil (f32) (f32.4 imm2) :cost 1 :encoding :custom)
(f32.4-lane-insert nil (f32.4) (f32.4 f32 imm2) :cost 1 :encoding :custom)
@@ -133,6 +135,8 @@
(f64.2-andc2 #:bic (f64.2) (f64.2 f64.2) :cost 1 :suffix '(:16b))
(f64.2-not #:not (f64.2) (f64.2) :cost 1 :suffix '(:16b))
(f64.2-sqrt #:fsqrt (f64.2) (f64.2) :cost 15 :suffix '(:2d))
+ (f64.2-abs #:fabs (f64.2) (f64.2) :cost 1 :suffix '(:2d))
+ (f64.2-neg #:fneg (f64.2) (f64.2) :cost 1 :suffix '(:2d))
(f64.2-bit-select #:bsl (f64.2) (u64.2 f64.2 f64.2) :cost 1 :encoding :neon-rmw :suffix '(:16b))
(f64.2-lane-extract nil (f64) (f64.2 imm1) :cost 1 :encoding :custom)
(f64.2-lane-insert nil (f64.2) (f64.2 f64 imm1) :cost 1 :encoding :custom)
@@ -266,10 +270,10 @@
(u32.4-from-f32.4 #:fcvtnu (u32.4) (f32.4) :cost 5 :suffix '(:4s))
(u32.4-from-u16.8 nil (u32.4) (u16.8) :cost 1 :encoding :custom)
(u32.4-from-u16.8-hi nil (u32.4) (u16.8) :cost 1 :encoding :custom)
- (u32.4-from-u64.2 #:xtn (u32.4) (u64.2) :cost 1 :suffix '(:4h))
- (u32.4-from-u64.2-hi #:xtn2 (u32.4) (u32.4 u64.2) :cost 1 :encoding :neon-rmw :suffix '(:8h))
- (u32.4-from-u64.2-saturating #:uqxtn (u32.4) (u64.2) :cost 1 :suffix '(:4h))
- (u32.4-from-u64.2-saturating-hi #:uqxtn2 (u32.4) (u32.4 u64.2) :cost 1 :encoding :neon-rmw :suffix '(:8h))
+ (u32.4-from-u64.2 #:xtn (u32.4) (u64.2) :cost 1 :suffix '(:2s))
+ (u32.4-from-u64.2-hi #:xtn2 (u32.4) (u32.4 u64.2) :cost 1 :encoding :neon-rmw :suffix '(:4s))
+ (u32.4-from-u64.2-saturating #:uqxtn (u32.4) (u64.2) :cost 1 :suffix '(:2s))
+ (u32.4-from-u64.2-saturating-hi #:uqxtn2 (u32.4) (u32.4 u64.2) :cost 1 :encoding :neon-rmw :suffix '(:4s))
(make-u32.4 nil (u32.4) (u32 u32 u32 u32) :cost 1 :encoding :fake-vop)
(u32.4-values nil (u32 u32 u32 u32) (u32.4) :cost 1 :encoding :fake-vop)
(u32.4-broadcast #:dup (u32.4) (u32) :cost 1 :suffix '(:4s))
@@ -329,8 +333,8 @@
(two-arg-u64.2-and #:and (u64.2) (u64.2 u64.2) :cost 1 :associative t :suffix '(:16b))
(two-arg-u64.2-or #:orr (u64.2) (u64.2 u64.2) :cost 1 :associative t :suffix '(:16b))
(two-arg-u64.2-xor #:eor (u64.2) (u64.2 u64.2) :cost 1 :associative t :suffix '(:16b))
- (two-arg-u64.2-max #:umax (u64.2) (u64.2 u64.2) :cost 3 :associative t :suffix '(:2d))
- (two-arg-u64.2-min #:umin (u64.2) (u64.2 u64.2) :cost 3 :associative t :suffix '(:2d))
+ (two-arg-u64.2-max nil (u64.2) (u64.2 u64.2) :cost 3 :associative t :encoding :fake-vop)
+ (two-arg-u64.2-min nil (u64.2) (u64.2 u64.2) :cost 3 :associative t :encoding :fake-vop)
(u64.2-andc1 nil (u64.2) (u64.2 u64.2) :cost 1 :encoding :fake-vop)
(u64.2-andc2 #:bic (u64.2) (u64.2 u64.2) :cost 1 :suffix '(:16b))
(u64.2-not #:not (u64.2) (u64.2) :cost 1 :suffix '(:16b))
@@ -338,7 +342,6 @@
(two-arg-u64.2+-saturating #:uqadd (u64.2) (u64.2 u64.2) :cost 2 :suffix '(:2d) :associative t)
(two-arg-u64.2- #:sub (u64.2) (u64.2 u64.2) :cost 2 :suffix '(:2d))
(two-arg-u64.2--saturating #:uqsub (u64.2) (u64.2 u64.2) :cost 2 :suffix '(:2d))
- (two-arg-u64.2* #:mul (u64.2) (u64.2 u64.2) :cost 2 :suffix '(:2d) :associative t)
(two-arg-u64.2= #:cmeq (u64.2) (u64.2 u64.2) :cost 1 :suffix '(:2d))
(two-arg-u64.2/= nil (u64.2) (u64.2 u64.2) :cost 2 :associative t :encoding :fake-vop)
(two-arg-u64.2> #:cmhi (u64.2) (u64.2 u64.2) :cost 1 :suffix '(:2d))
@@ -478,10 +481,10 @@
(s32.4-from-f32.4 #:fcvtns (s32.4) (f32.4) :cost 5 :suffix '(:4s))
(s32.4-from-s16.8 nil (s32.4) (s16.8) :cost 1 :encoding :custom)
(s32.4-from-s16.8-hi nil (s32.4) (s16.8) :cost 1 :encoding :custom)
- (s32.4-from-s64.2 #:xtn (s32.4) (s64.2) :cost 1 :suffix '(:4h))
- (s32.4-from-s64.2-hi #:xtn2 (s32.4) (s32.4 s64.2) :cost 1 :encoding :neon-rmw :suffix '(:8h))
- (s32.4-from-s64.2-saturating #:sqxtn (s32.4) (s64.2) :cost 1 :suffix '(:4h))
- (s32.4-from-s64.2-saturating-hi #:sqxtn2 (s32.4) (s32.4 s64.2) :cost 1 :encoding :neon-rmw :suffix '(:8h))
+ (s32.4-from-s64.2 #:xtn (s32.4) (s64.2) :cost 1 :suffix '(:2s))
+ (s32.4-from-s64.2-hi #:xtn2 (s32.4) (s32.4 s64.2) :cost 1 :encoding :neon-rmw :suffix '(:4s))
+ (s32.4-from-s64.2-saturating #:sqxtn (s32.4) (s64.2) :cost 1 :suffix '(:2s))
+ (s32.4-from-s64.2-saturating-hi #:sqxtn2 (s32.4) (s32.4 s64.2) :cost 1 :encoding :neon-rmw :suffix '(:4s))
(make-s32.4 nil (s32.4) (s32 s32 s32 s32) :cost 1 :encoding :fake-vop)
(s32.4-values nil (s32 s32 s32 s32) (s32.4) :cost 1 :encoding :fake-vop)
(s32.4-broadcast #:dup (s32.4) (s32) :cost 1 :suffix '(:4s))
@@ -539,8 +542,8 @@
(two-arg-s64.2-and #:and (s64.2) (s64.2 s64.2) :cost 1 :associative t :suffix '(:16b))
(two-arg-s64.2-or #:orr (s64.2) (s64.2 s64.2) :cost 1 :associative t :suffix '(:16b))
(two-arg-s64.2-xor #:eor (s64.2) (s64.2 s64.2) :cost 1 :associative t :suffix '(:16b))
- (two-arg-s64.2-max #:smax (s64.2) (s64.2 s64.2) :cost 3 :associative t :suffix '(:2d))
- (two-arg-s64.2-min #:smin (s64.2) (s64.2 s64.2) :cost 3 :associative t :suffix '(:2d))
+ (two-arg-s64.2-max nil (s64.2) (s64.2 s64.2) :cost 3 :associative t :encoding :fake-vop)
+ (two-arg-s64.2-min nil (s64.2) (s64.2 s64.2) :cost 3 :associative t :encoding :fake-vop)
(s64.2-andc1 nil (s64.2) (s64.2 s64.2) :cost 1 :encoding :fake-vop)
(s64.2-andc2 #:bic (s64.2) (s64.2 s64.2) :cost 1 :suffix '(:16b))
(s64.2-not #:not (s64.2) (s64.2) :cost 1 :suffix '(:16b))
@@ -548,7 +551,6 @@
(two-arg-s64.2+-saturating #:sqadd (s64.2) (s64.2 s64.2) :cost 2 :suffix '(:2d) :associative t)
(two-arg-s64.2- #:sub (s64.2) (s64.2 s64.2) :cost 2 :suffix '(:2d))
(two-arg-s64.2--saturating #:sqsub (s64.2) (s64.2 s64.2) :cost 2 :suffix '(:2d))
- (two-arg-s64.2* #:mul (s64.2) (s64.2 s64.2) :cost 2 :suffix '(:2d) :associative t)
(two-arg-s64.2= #:cmeq (u64.2) (s64.2 s64.2) :cost 1 :suffix '(:2d))
(two-arg-s64.2/= nil (u64.2) (s64.2 s64.2) :cost 2 :associative t :encoding :fake-vop)
(two-arg-s64.2> #:cmgt (u64.2) (s64.2 s64.2) :cost 1 :suffix '(:2d))
@@ -646,7 +648,6 @@
(u64.2-min two-arg-u64.2-min nil)
(u64.2+ two-arg-u64.2+ 0)
(u64.2+-saturating two-arg-u64.2+-saturating 0)
- (u64.2* two-arg-u64.2* 1)
(s8.16-and two-arg-s8.16-and +s8-true+)
(s8.16-or two-arg-s8.16-or +s8-false+)
(s8.16-xor two-arg-s8.16-xor +s8-false+)
@@ -677,8 +678,7 @@
(s64.2-max two-arg-s64.2-max nil)
(s64.2-min two-arg-s64.2-min nil)
(s64.2+ two-arg-s64.2+ 0)
- (s64.2+-saturating two-arg-s64.2+-saturating 0)
- (s64.2* two-arg-s64.2* 1))
+ (s64.2+-saturating two-arg-s64.2+-saturating 0))
(:comparisons
(f32.4= two-arg-f32.4= u32.4-and +u32-true+)
(f32.4< two-arg-f32.4< u32.4-and +u32-true+)
diff --git a/contrib/sb-simd/code/packages.lisp b/contrib/sb-simd/code/packages.lisp
index d28bdcc86..aca8836b3 100644
--- a/contrib/sb-simd/code/packages.lisp
+++ b/contrib/sb-simd/code/packages.lisp
@@ -2170,6 +2170,8 @@
#:f32.4-max
#:f32.4-min
#:f32.4-sqrt
+ #:f32.4-abs
+ #:f32.4-neg
#:f32.4+
#:f32.4-
#:f32.4*
@@ -2220,6 +2222,8 @@
#:f64.2-max
#:f64.2-min
#:f64.2-sqrt
+ #:f64.2-abs
+ #:f64.2-neg
#:f64.2+
#:f64.2-
#:f64.2*
@@ -2268,6 +2272,8 @@
#:u8.16-andc1
#:u8.16-andc2
#:u8.16-not
+ #:u8.16-min
+ #:u8.16-max
#:u8.16+
#:u8.16+-saturating
#:u8.16*
@@ -2326,6 +2332,8 @@
#:u16.8-andc1
#:u16.8-andc2
#:u16.8-not
+ #:u16.8-min
+ #:u16.8-max
#:u16.8+
#:u16.8+-saturating
#:u16.8*
@@ -2382,6 +2390,8 @@
#:u32.4-andc1
#:u32.4-andc2
#:u32.4-not
+ #:u32.4-min
+ #:u32.4-max
#:u32.4+
#:u32.4+-saturating
#:u32.4*
@@ -2438,9 +2448,10 @@
#:u64.2-andc1
#:u64.2-andc2
#:u64.2-not
+ #:u64.2-min
+ #:u64.2-max
#:u64.2+
#:u64.2+-saturating
- #:u64.2*
#:u64.2-
#:u64.2--saturating
#:u64.2=
@@ -2487,6 +2498,8 @@
#:s8.16-andc1
#:s8.16-andc2
#:s8.16-not
+ #:s8.16-min
+ #:s8.16-max
#:s8.16+
#:s8.16+-saturating
#:s8.16*
@@ -2540,6 +2553,8 @@
#:s16.8-andc1
#:s16.8-andc2
#:s16.8-not
+ #:s16.8-min
+ #:s16.8-max
#:s16.8+
#:s16.8+-saturating
#:s16.8*
@@ -2594,6 +2609,8 @@
#:s32.4-andc1
#:s32.4-andc2
#:s32.4-not
+ #:s32.4-min
+ #:s32.4-max
#:s32.4+
#:s32.4+-saturating
#:s32.4*
@@ -2644,9 +2661,10 @@
#:s64.2-andc1
#:s64.2-andc2
#:s64.2-not
+ #:s64.2-min
+ #:s64.2-max
#:s64.2+
#:s64.2+-saturating
- #:s64.2*
#:s64.2-
#:s64.2--saturating
#:s64.2=
diff --git a/contrib/sb-simd/test-suite/test-arm64-regressions.lisp b/contrib/sb-simd/test-suite/test-arm64-regressions.lisp
new file mode 100644
index 000000000..f125a7730
--- /dev/null
+++ b/contrib/sb-simd/test-suite/test-arm64-regressions.lisp
@@ -0,0 +1,179 @@
+;;; Regression tests for AdvSIMD bugs found by auditing sb-simd against
+;;; the A64 instruction set. Each test targets a bug that once produced
+;;; wrong results or illegal instructions rather than a clean error.
+
+(in-package #:sb-simd-neon)
+
+;;; Values that sit on both sides of the signed/unsigned wrap-around
+;;; point. Random sampling almost never generates pairs like
+;;; (0, #xFFFFFFFFFFFFFFFF), so test them exhaustively.
+(defparameter *u64-boundary-values*
+ (list 0 1 2 3 5
+ #x7FFFFFFFFFFFFFFE #x7FFFFFFFFFFFFFFF
+ #x8000000000000000 #x8000000000000001
+ #xFFFFFFFFFFFFFFFD #xFFFFFFFFFFFFFFFE #xFFFFFFFFFFFFFFFF))
+
+(defparameter *s64-boundary-values*
+ (list -9223372036854775808 -9223372036854775807 -1 0 1 42
+ 9223372036854775806 9223372036854775807))
+
+;;; Issue: UMAX/UMIN/SMAX/SMIN have no .2d form; max/min are fake vops
+;;; built from CMHI/CMGT plus BSL.
+(sb-simd-test-suite:define-test u64.2-max-min-boundaries
+ (dolist (a *u64-boundary-values*)
+ (dolist (b *u64-boundary-values*)
+ (let ((pa (make-u64.2 a a))
+ (pb (make-u64.2 b b)))
+ (sb-simd-test-suite:is (= (u64.2-lane-extract (u64.2-max pa pb) 0) (max a b)))
+ (sb-simd-test-suite:is (= (u64.2-lane-extract (u64.2-min pa pb) 0) (min a b)))))))
+
+(sb-simd-test-suite:define-test s64.2-max-min-boundaries
+ (dolist (a *s64-boundary-values*)
+ (dolist (b *s64-boundary-values*)
+ (let ((pa (make-s64.2 a a))
+ (pb (make-s64.2 b b)))
+ (sb-simd-test-suite:is (= (s64.2-lane-extract (s64.2-max pa pb) 0) (max a b)))
+ (sb-simd-test-suite:is (= (s64.2-lane-extract (s64.2-min pa pb) 0) (min a b)))))))
+
+;;; Random cross-check of the same fake vops against the scalar
+;;; reference implementation.
+(sb-simd-test-suite:define-test u64.2-max-min-random
+ (flet ((to-signed (x) (if (logbitp 63 x) (- x (ash 1 64)) x)))
+ (dotimes (i 2000)
+ (let* ((bits (lambda () (logior (ash (random (ash 1 32)) 32)
+ (random (ash 1 32)))))
+ (a0 (funcall bits)) (a1 (funcall bits))
+ (b0 (funcall bits)) (b1 (funcall bits))
+ (ua (make-u64.2 a0 a1))
+ (ub (make-u64.2 b0 b1))
+ (sa (make-s64.2 (to-signed a0) (to-signed a1)))
+ (sb (make-s64.2 (to-signed b0) (to-signed b1))))
+ (sb-simd-test-suite:is (= (u64.2-lane-extract (u64.2-max ua ub) 0) (max a0 b0)))
+ (sb-simd-test-suite:is (= (u64.2-lane-extract (u64.2-min ua ub) 1) (min a1 b1)))
+ (sb-simd-test-suite:is (= (s64.2-lane-extract (s64.2-max sa sb) 0)
+ (max (to-signed a0) (to-signed b0))))
+ (sb-simd-test-suite:is (= (s64.2-lane-extract (s64.2-min sa sb) 1)
+ (min (to-signed a1) (to-signed b1))))))))
+
+;;; Issue: the XTN-family narrowing records used .4h/.8h suffixes,
+;;; silently computing a 32-to-16-bit narrowing on 64-bit lanes.
+(sb-simd-test-suite:define-test u32.4-from-u64.2-narrowing
+ ;; Plain narrowing takes the low half of each lane and zeroes the rest.
+ (let ((r (u32.4-from-u64.2 (make-u64.2 #x1111111122222222
+ #x3333333344444444))))
+ (sb-simd-test-suite:is (= (u32.4-lane-extract r 0) #x22222222))
+ (sb-simd-test-suite:is (= (u32.4-lane-extract r 1) #x44444444))
+ (sb-simd-test-suite:is (= (u32.4-lane-extract r 2) 0))
+ (sb-simd-test-suite:is (= (u32.4-lane-extract r 3) 0)))
+ ;; Saturating narrowing clamps into the target range.
+ (let ((r (u32.4-from-u64.2-saturating (make-u64.2 #xFFFFFFFFFFFFFFFF 3))))
+ (sb-simd-test-suite:is (= (u32.4-lane-extract r 0) #xFFFFFFFF))
+ (sb-simd-test-suite:is (= (u32.4-lane-extract r 1) 3)))
+ ;; The -hi variants append to the high half and preserve the low half.
+ (let ((r (u32.4-from-u64.2-hi (make-u32.4 10 20 30 40)
+ (make-u64.2 #x1111111122222222
+ #x3333333344444444))))
+ (sb-simd-test-suite:is (= (u32.4-lane-extract r 0) 10))
+ (sb-simd-test-suite:is (= (u32.4-lane-extract r 1) 20))
+ (sb-simd-test-suite:is (= (u32.4-lane-extract r 2) #x22222222))
+ (sb-simd-test-suite:is (= (u32.4-lane-extract r 3) #x44444444)))
+ (let ((r (u32.4-from-u64.2-saturating-hi
+ (make-u32.4 10 20 30 40)
+ (make-u64.2 #xFFFFFFFFFFFFFFFF #xFFFFFFFFFFFFFFFF))))
+ (sb-simd-test-suite:is (= (u32.4-lane-extract r 0) 10))
+ (sb-simd-test-suite:is (= (u32.4-lane-extract r 1) 20))
+ (sb-simd-test-suite:is (= (u32.4-lane-extract r 2) #xFFFFFFFF))
+ (sb-simd-test-suite:is (= (u32.4-lane-extract r 3) #xFFFFFFFF))))
+
+(sb-simd-test-suite:define-test s32.4-from-s64.2-narrowing
+ (let ((r (s32.4-from-s64.2 (make-s64.2 -5 #x7000000011112222))))
+ (sb-simd-test-suite:is (= (s32.4-lane-extract r 0) -5))
+ (sb-simd-test-suite:is (= (s32.4-lane-extract r 1) #x11112222))
+ (sb-simd-test-suite:is (= (s32.4-lane-extract r 2) 0))
+ (sb-simd-test-suite:is (= (s32.4-lane-extract r 3) 0)))
+ ;; Saturation clamps in both directions.
+ (let ((r (s32.4-from-s64.2-saturating
+ (make-s64.2 #x7FFFFFFFFFFFFFFF -99999999999999))))
+ (sb-simd-test-suite:is (= (s32.4-lane-extract r 0) most-positive-s32))
+ (sb-simd-test-suite:is (= (s32.4-lane-extract r 1) most-negative-s32)))
+ (let ((r (s32.4-from-s64.2-hi (make-s32.4 10 20 30 40)
+ (make-s64.2 -5 #x7000000011112222))))
+ (sb-simd-test-suite:is (= (s32.4-lane-extract r 0) 10))
+ (sb-simd-test-suite:is (= (s32.4-lane-extract r 1) 20))
+ (sb-simd-test-suite:is (= (s32.4-lane-extract r 2) -5))
+ (sb-simd-test-suite:is (= (s32.4-lane-extract r 3) #x11112222))))
+
+;;; Issue: signed lane extraction returned zero-extended values because
+;;; the custom vops emitted UMOV instead of SMOV.
+(sb-simd-test-suite:define-test signed-lane-extraction-sign-extends
+ (let ((v (make-s8.16 -128 -1 127 42 0 -42 1 -127 2 -2 3 -3 4 -4 5 -5)))
+ (loop for expected in '(-128 -1 127 42 0 -42 1 -127 2 -2 3 -3 4 -4 5 -5)
+ for i from 0
+ do (sb-simd-test-suite:is (= (s8.16-lane-extract v i) expected))))
+ (let ((v (make-s16.8 -32768 -1 32767 12345 -5432 0 1 -1)))
+ (loop for expected in '(-32768 -1 32767 12345 -5432 0 1 -1)
+ for i from 0
+ do (sb-simd-test-suite:is (= (s16.8-lane-extract v i) expected))))
+ (let ((v (make-s32.4 -2147483648 -1 2147483647 42)))
+ (loop for expected in '(-2147483648 -1 2147483647 42)
+ for i from 0
+ do (sb-simd-test-suite:is (= (s32.4-lane-extract v i) expected))))
+ ;; Unsigned shapes must remain unaffected.
+ (let ((v (make-u8.16 255 254 253 252 0 1 2 3 4 5 6 7 8 9 10 11)))
+ (sb-simd-test-suite:is (= (u8.16-lane-extract v 0) 255))
+ (sb-simd-test-suite:is (= (u8.16-lane-extract v 3) 252))))
+
+;;; Issue: emit-movi-vector-imm passed replicated broadcast patterns to
+;;; MOVI instead of lane immediates, aborting compilation with "bad
+;;; immediate". Every constant below is materialized through that code
+;;; path; several exercise the shifted-cmode forms. The tests are split
+;;; into several functions because packing too many distinct vector
+;;; constants into one function currently overflows the LDR spill
+;;; offset range - see issue about large SIMD constant pools.
+(sb-simd-test-suite:define-test integer-broadcast-constants-simple
+ ;; The original reproducer: 1 does not fit MOVI's simple .8h form.
+ (let ((r (u16.8-and (u16.8-broadcast 5) 1)))
+ (sb-simd-test-suite:is (= (u16.8-lane-extract r 0) 1))
+ (sb-simd-test-suite:is (= (u16.8-lane-extract r 7) 1)))
+ ;; Shifted immediates (low byte zero).
+ (let ((r (u16.8-and (u16.8-broadcast #x0100) #x0100)))
+ (sb-simd-test-suite:is (= (u16.8-lane-extract r 3) #x0100)))
+ ;; Byte-replicated patterns.
+ (dolist (c (list 0 1 #x7F #x80 #xFF))
+ (let ((r (u8.16-or (u8.16-broadcast c) (u8.16-broadcast c))))
+ (sb-simd-test-suite:is (= (u8.16-lane-extract r 15) c)))))
+
+(sb-simd-test-suite:define-test integer-broadcast-constants-word
+ ;; 32-bit constants with shifted bytes.
+ (dolist (c (list 0 1 255 256 #xFFFF #x10000 #xFF0000 #xFF000000))
+ (let ((r (u32.4-and (u32.4-broadcast c) (u32.4-broadcast c))))
+ (sb-simd-test-suite:is (= (u32.4-lane-extract r 0) c)))))
+
+;;; Bit-replication patterns (.2d MOVI form): every byte is 0 or #xFF.
+(sb-simd-test-suite:define-test integer-broadcast-constants-bit-replicated
+ (dolist (c (list #xFF00FF00FF00FF00
+ #x8000000000000000
+ #xFFFFFFFFFFFFFFFF
+ #x7F7F7F7F7F7F7F7F
+ #x00FF00FF00FF00FF))
+ (let ((r (u64.2-and (u64.2-broadcast c) (u64.2-broadcast c))))
+ (sb-simd-test-suite:is (= (u64.2-lane-extract r 0) c))
+ (sb-simd-test-suite:is (= (u64.2-lane-extract r 1) c)))))
+
+;;; Patterns that fit no MOVI form fall back to register synthesis
+;;; (MOVZ/DUP or logical-immediate ORR).
+(sb-simd-test-suite:define-test integer-broadcast-constants-synthesized
+ (dolist (c (list #x0102030405060708 #xDEADBEEFCAFEBABE))
+ (let ((r (u64.2-and (u64.2-broadcast c) (u64.2-broadcast c))))
+ (sb-simd-test-suite:is (= (u64.2-lane-extract r 1) c)))))
+
+;;; Float constants take a different path (movi-immediate-p guarded);
+;;; keep them covered too.
+(sb-simd-test-suite:define-test float-broadcast-constants
+ (let ((r (f32.4-max (make-f32.4 0.5 -1.0 2.0 3.0) 1.0f0)))
+ (sb-simd-test-suite:is (= (f32.4-lane-extract r 0) 1.0f0))
+ (sb-simd-test-suite:is (= (f32.4-lane-extract r 1) 1.0f0))
+ (sb-simd-test-suite:is (= (f32.4-lane-extract r 2) 2.0f0)))
+ (let ((r (f64.2-min (make-f64.2 0.5d0 -5d0) -1d0)))
+ (sb-simd-test-suite:is (= (f64.2-lane-extract r 0) -1d0))
+ (sb-simd-test-suite:is (= (f64.2-lane-extract r 1) -5d0))))
diff --git a/contrib/sb-simd/test-suite/test-simple-simd-functions-arm64.lisp b/contrib/sb-simd/test-suite/test-simple-simd-functions-arm64.lisp
index 280d4184b..8ad454e4c 100644
--- a/contrib/sb-simd/test-suite/test-simple-simd-functions-arm64.lisp
+++ b/contrib/sb-simd/test-suite/test-simple-simd-functions-arm64.lisp
@@ -8,6 +8,8 @@
(sb-simd-test-suite:define-simple-simd-test f32.4-not (f32.4) (f32.4) f32-not)
(sb-simd-test-suite:define-simple-simd-test f32.4-max (f32.4) (f32.4 &rest f32.4) f32-max)
(sb-simd-test-suite:define-simple-simd-test f32.4-min (f32.4) (f32.4 &rest f32.4) f32-min)
+(sb-simd-test-suite:define-simple-simd-test f32.4-abs (f32.4) (f32.4) abs)
+(sb-simd-test-suite:define-simple-simd-test f32.4-neg (f32.4) (f32.4) -)
(sb-simd-test-suite:define-simple-simd-test f32.4+ (f32.4) (&rest f32.4) f32+)
(sb-simd-test-suite:define-simple-simd-test f32.4- (f32.4) (f32.4 &rest f32.4) f32-)
(sb-simd-test-suite:define-simple-simd-test f32.4* (f32.4) (&rest f32.4) f32*)
@@ -26,6 +28,8 @@
(sb-simd-test-suite:define-simple-simd-test f64.2-not (f64.2) (f64.2) f64-not)
(sb-simd-test-suite:define-simple-simd-test f64.2-max (f64.2) (f64.2 &rest f64.2) f64-max)
(sb-simd-test-suite:define-simple-simd-test f64.2-min (f64.2) (f64.2 &rest f64.2) f64-min)
+(sb-simd-test-suite:define-simple-simd-test f64.2-abs (f64.2) (f64.2) abs)
+(sb-simd-test-suite:define-simple-simd-test f64.2-neg (f64.2) (f64.2) -)
(sb-simd-test-suite:define-simple-simd-test f64.2+ (f64.2) (&rest f64.2) f64+)
(sb-simd-test-suite:define-simple-simd-test f64.2- (f64.2) (f64.2 &rest f64.2) f64-)
(sb-simd-test-suite:define-simple-simd-test f64.2* (f64.2) (&rest f64.2) f64*)
@@ -42,6 +46,8 @@
(sb-simd-test-suite:define-simple-simd-test u8.16-xor (u8.16) (&rest u8.16) u8-xor)
(sb-simd-test-suite:define-simple-simd-test u8.16-andc1 (u8.16) (u8.16 u8.16) u8-andc1)
(sb-simd-test-suite:define-simple-simd-test u8.16-not (u8.16) (u8.16) u8-not)
+(sb-simd-test-suite:define-simple-simd-test u8.16-max (u8.16) (u8.16 &rest u8.16) u8-max)
+(sb-simd-test-suite:define-simple-simd-test u8.16-min (u8.16) (u8.16 &rest u8.16) u8-min)
(sb-simd-test-suite:define-simple-simd-test u8.16+ (u8.16) (&rest u8.16) u8+)
(sb-simd-test-suite:define-simple-simd-test u8.16- (u8.16) (u8.16 &rest u8.16) u8-)
(sb-simd-test-suite:define-simple-simd-test u8.16= (u8.16) (u8.16 &rest u8.16) u8=)
@@ -56,6 +62,8 @@
(sb-simd-test-suite:define-simple-simd-test u16.8-xor (u16.8) (&rest u16.8) u16-xor)
(sb-simd-test-suite:define-simple-simd-test u16.8-andc1 (u16.8) (u16.8 u16.8) u16-andc1)
(sb-simd-test-suite:define-simple-simd-test u16.8-not (u16.8) (u16.8) u16-not)
+(sb-simd-test-suite:define-simple-simd-test u16.8-max (u16.8) (u16.8 &rest u16.8) u16-max)
+(sb-simd-test-suite:define-simple-simd-test u16.8-min (u16.8) (u16.8 &rest u16.8) u16-min)
(sb-simd-test-suite:define-simple-simd-test u16.8+ (u16.8) (&rest u16.8) u16+)
(sb-simd-test-suite:define-simple-simd-test u16.8- (u16.8) (u16.8 &rest u16.8) u16-)
(sb-simd-test-suite:define-simple-simd-test u16.8= (u16.8) (u16.8 &rest u16.8) u16=)
@@ -70,6 +78,8 @@
(sb-simd-test-suite:define-simple-simd-test u32.4-xor (u32.4) (&rest u32.4) u32-xor)
(sb-simd-test-suite:define-simple-simd-test u32.4-andc1 (u32.4) (u32.4 u32.4) u32-andc1)
(sb-simd-test-suite:define-simple-simd-test u32.4-not (u32.4) (u32.4) u32-not)
+(sb-simd-test-suite:define-simple-simd-test u32.4-max (u32.4) (u32.4 &rest u32.4) u32-max)
+(sb-simd-test-suite:define-simple-simd-test u32.4-min (u32.4) (u32.4 &rest u32.4) u32-min)
(sb-simd-test-suite:define-simple-simd-test u32.4+ (u32.4) (&rest u32.4) u32+)
(sb-simd-test-suite:define-simple-simd-test u32.4- (u32.4) (u32.4 &rest u32.4) u32-)
(sb-simd-test-suite:define-simple-simd-test u32.4= (u32.4) (u32.4 &rest u32.4) u32=)
@@ -84,6 +94,8 @@
(sb-simd-test-suite:define-simple-simd-test u64.2-xor (u64.2) (&rest u64.2) u64-xor)
(sb-simd-test-suite:define-simple-simd-test u64.2-andc1 (u64.2) (u64.2 u64.2) u64-andc1)
(sb-simd-test-suite:define-simple-simd-test u64.2-not (u64.2) (u64.2) u64-not)
+(sb-simd-test-suite:define-simple-simd-test u64.2-max (u64.2) (u64.2 &rest u64.2) u64-max)
+(sb-simd-test-suite:define-simple-simd-test u64.2-min (u64.2) (u64.2 &rest u64.2) u64-min)
(sb-simd-test-suite:define-simple-simd-test u64.2+ (u64.2) (&rest u64.2) u64+)
(sb-simd-test-suite:define-simple-simd-test u64.2- (u64.2) (u64.2 &rest u64.2) u64-)
(sb-simd-test-suite:define-simple-simd-test u64.2= (u64.2) (u64.2 &rest u64.2) u64=)
@@ -98,6 +110,8 @@
(sb-simd-test-suite:define-simple-simd-test s8.16-xor (s8.16) (&rest s8.16) s8-xor)
(sb-simd-test-suite:define-simple-simd-test s8.16-andc1 (s8.16) (s8.16 s8.16) s8-andc1)
(sb-simd-test-suite:define-simple-simd-test s8.16-not (s8.16) (s8.16) s8-not)
+(sb-simd-test-suite:define-simple-simd-test s8.16-max (s8.16) (s8.16 &rest s8.16) s8-max)
+(sb-simd-test-suite:define-simple-simd-test s8.16-min (s8.16) (s8.16 &rest s8.16) s8-min)
(sb-simd-test-suite:define-simple-simd-test s8.16+ (s8.16) (&rest s8.16) s8+)
(sb-simd-test-suite:define-simple-simd-test s8.16- (s8.16) (s8.16 &rest s8.16) s8-)
(sb-simd-test-suite:define-simple-simd-test s8.16= (u8.16) (s8.16 &rest s8.16) s8=)
@@ -112,6 +126,8 @@
(sb-simd-test-suite:define-simple-simd-test s16.8-xor (s16.8) (&rest s16.8) s16-xor)
(sb-simd-test-suite:define-simple-simd-test s16.8-andc1 (s16.8) (s16.8 s16.8) s16-andc1)
(sb-simd-test-suite:define-simple-simd-test s16.8-not (s16.8) (s16.8) s16-not)
+(sb-simd-test-suite:define-simple-simd-test s16.8-max (s16.8) (s16.8 &rest s16.8) s16-max)
+(sb-simd-test-suite:define-simple-simd-test s16.8-min (s16.8) (s16.8 &rest s16.8) s16-min)
(sb-simd-test-suite:define-simple-simd-test s16.8+ (s16.8) (&rest s16.8) s16+)
(sb-simd-test-suite:define-simple-simd-test s16.8- (s16.8) (s16.8 &rest s16.8) s16-)
(sb-simd-test-suite:define-simple-simd-test s16.8= (u16.8) (s16.8 &rest s16.8) s16=)
@@ -126,6 +142,8 @@
(sb-simd-test-suite:define-simple-simd-test s32.4-xor (s32.4) (&rest s32.4) s32-xor)
(sb-simd-test-suite:define-simple-simd-test s32.4-andc1 (s32.4) (s32.4 s32.4) s32-andc1)
(sb-simd-test-suite:define-simple-simd-test s32.4-not (s32.4) (s32.4) s32-not)
+(sb-simd-test-suite:define-simple-simd-test s32.4-max (s32.4) (s32.4 &rest s32.4) s32-max)
+(sb-simd-test-suite:define-simple-simd-test s32.4-min (s32.4) (s32.4 &rest s32.4) s32-min)
(sb-simd-test-suite:define-simple-simd-test s32.4+ (s32.4) (&rest s32.4) s32+)
(sb-simd-test-suite:define-simple-simd-test s32.4- (s32.4) (s32.4 &rest s32.4) s32-)
(sb-simd-test-suite:define-simple-simd-test s32.4= (u32.4) (s32.4 &rest s32.4) s32=)
@@ -140,6 +158,8 @@
(sb-simd-test-suite:define-simple-simd-test s64.2-xor (s64.2) (&rest s64.2) s64-xor)
(sb-simd-test-suite:define-simple-simd-test s64.2-andc1 (s64.2) (s64.2 s64.2) s64-andc1)
(sb-simd-test-suite:define-simple-simd-test s64.2-not (s64.2) (s64.2) s64-not)
+(sb-simd-test-suite:define-simple-simd-test s64.2-max (s64.2) (s64.2 &rest s64.2) s64-max)
+(sb-simd-test-suite:define-simple-simd-test s64.2-min (s64.2) (s64.2 &rest s64.2) s64-min)
(sb-simd-test-suite:define-simple-simd-test s64.2+ (s64.2) (&rest s64.2) s64+)
(sb-simd-test-suite:define-simple-simd-test s64.2- (s64.2) (s64.2 &rest s64.2) s64-)
(sb-simd-test-suite:define-simple-simd-test s64.2= (u64.2) (s64.2 &rest s64.2) s64=)
diff --git a/src/compiler/arm64/insts.lisp b/src/compiler/arm64/insts.lisp
index 234b9b5c3..70023117c 100644
--- a/src/compiler/arm64/insts.lisp
+++ b/src/compiler/arm64/insts.lisp
@@ -2810,38 +2810,42 @@
(fpr-offset rd)))))
(defmacro def-fp-data-processing-1+simd (name op
- simd-u simd-neg simd-op)
+ simd-u simd-neg simd-op6 simd-op)
`(define-instruction ,name (segment rd rn &optional vector-size)
(:printer fp-data-processing-1 ((op ,op)))
- (:printer simd-two-same-float ((u ,simd-u) (neg ,simd-neg) (op ,simd-op)))
+ (:printer simd-two-same-float ((u ,simd-u) (neg ,simd-neg) (op6 ,simd-op6)
+ (op ,simd-op)))
(:emitter
(assert (and (eq (tn-sc rd)
(tn-sc rn)))
(rd rn)
"Arguments should have the same FP storage class: ~s ~s." rd rn)
- (if vector-size
- (multiple-value-bind (q size) (encode-vector-size vector-size)
- (emit-simd-two-same-float
- segment
- q
- ,simd-u
- ,simd-neg
- (logand 1 size)
- ,simd-op
- (fpr-offset rn)
- (fpr-offset rd)))
- (emit-fp-data-processing-1 segment
- (fp-reg-type rn)
- ,op
- (fpr-offset rn)
- (fpr-offset rd))))))
+ (cond (vector-size
+ (aver (member vector-size '(:2s :4s :2d)))
+ (multiple-value-bind (q size) (encode-vector-size vector-size)
+ (emit-simd-two-same-float
+ segment
+ q
+ ,simd-u
+ ,simd-neg
+ (logand 1 size)
+ ,simd-op6
+ ,simd-op
+ (fpr-offset rn)
+ (fpr-offset rd))))
+ (t
+ (emit-fp-data-processing-1 segment
+ (fp-reg-type rn)
+ ,op
+ (fpr-offset rn)
+ (fpr-offset rd)))))))
(def-fp-data-processing-1+simd fabs #b0001
- #b0 #b1 #b11111)
+ #b0 #b1 #b00000 #b11111)
(def-fp-data-processing-1+simd fneg #b0010
- #b1 #b1 #b11111)
+ #b1 #b1 #b00000 #b11111)
(def-fp-data-processing-1+simd fsqrt #b0011
- #b1 #b0 #b11111)
+ #b1 #b1 #b00001 #b11111)
(def-fp-data-processing-1 frintn #b1000)
(def-fp-data-processing-1 frintp #b1001)
(def-fp-data-processing-1 frintm #b1010)
@@ -2888,24 +2892,26 @@
(:printer fp-data-processing-2 ((op ,op)))
(:printer simd-three-same-float ((u ,simd-u) (neg ,simd-neg) (op ,simd-op)))
(:emitter
- (if vector-size
- (multiple-value-bind (q size) (encode-vector-size vector-size)
- (emit-simd-three-same-float
- segment
- q
- ,simd-u
- ,simd-neg
- (logand 1 size)
- (fpr-offset rm)
- ,simd-op
- (fpr-offset rn)
- (fpr-offset rd)))
- (emit-fp-data-processing-2 segment
- (fp-reg-type rn)
- (fpr-offset rm)
- ,op
- (fpr-offset rn)
- (fpr-offset rd))))))
+ (cond (vector-size
+ (aver (member vector-size '(:2s :4s :2d)))
+ (multiple-value-bind (q size) (encode-vector-size vector-size)
+ (emit-simd-three-same-float
+ segment
+ q
+ ,simd-u
+ ,simd-neg
+ (logand 1 size)
+ (fpr-offset rm)
+ ,simd-op
+ (fpr-offset rn)
+ (fpr-offset rd))))
+ (t
+ (emit-fp-data-processing-2 segment
+ (fp-reg-type rn)
+ (fpr-offset rm)
+ ,op
+ (fpr-offset rn)
+ (fpr-offset rd)))))))
(def-fp-data-processing-2+simd fmul #b0000
#b1 #b0 #b11011)
@@ -3479,8 +3485,8 @@
(neg 1 23)
(size 1 22)
(#b1 1 21)
- (#b00000 5 16)
- (opc 5 11)
+ (op6 5 16)
+ (op 5 11)
(#b0 1 10)
(rn 5 5)
(rd 5 0))
@@ -3533,10 +3539,10 @@
(op3 :field (byte 1 31) :value #b0)
(u :field (byte 1 29))
(op4 :field (byte 5 24) :value #b01110)
- (neg :field (byte 1 23))
+ (neg :field (byte 1 23) :value #b1)
(size :field (byte 1 22))
(op5 :field (byte 1 21) :value #b1)
- (op6 :field (byte 5 16) :value #b00000)
+ (op6 :field (byte 5 16))
(op :field (byte 5 11))
(op7 :field (byte 1 10) :value #b0)
(rn :fields (list (byte 1 30) (byte 1 22) (byte 5 5)) :type 'simd-float-reg)
@@ -3612,7 +3618,9 @@
(def bit #b1 #b10 #b00011)
(def bif #b1 #b11 #b00011))
-(macrolet ((def (name u op &optional zero-u zero)
+(macrolet ((def (name u op &optional
+ (2d t)
+ zero-u zero)
`(define-instruction ,name (segment rd rn rm size)
,@(when op
`((:printer simd-three-same-sized ((u ,u) (op ,op)))))
@@ -3620,6 +3628,9 @@
`((:printer simd-two-misc ((u ,zero-u) (op ,zero))
'(:name :tab rd ", " rn ", " "#0"))))
(:emitter
+ (aver (member size ',(if 2d
+ '(:8b :16b :4h :8h :2s :4s :2d)
+ '(:8b :16b :4h :8h :2s :4s))))
(multiple-value-bind (q size) (encode-vector-size size)
(cond ,@(when zero
`(((eql rm 0)
@@ -3644,32 +3655,32 @@
(fpr-offset rd))
`(error "Can be compared only with zero, not ~s" rm)))))))))
(def cmtst #b0 #b10001)
- (def cmeq #b1 #b10001 0 #b01001)
- (def cmgt #b0 #b00110 0 #b01000)
- (def cmge #b0 #b00111 1 #b01000)
- (def cmlt nil nil 0 #b01010)
- (def cmle nil nil 1 #b01001)
+ (def cmeq #b1 #b10001 t 0 #b01001)
+ (def cmgt #b0 #b00110 t 0 #b01000)
+ (def cmge #b0 #b00111 t 1 #b01000)
+ (def cmlt nil nil t 0 #b01010)
+ (def cmle nil nil t 1 #b01001)
(def cmhi #b1 #b00110)
(def cmhs #b1 #b00111)
- (def umin #b1 #b01101)
- (def umax #b1 #b01100)
- (def smin #b0 #b01101)
- (def smax #b0 #b01100)
- (def uhadd #b1 #b00000)
+ (def umin #b1 #b01101 nil)
+ (def umax #b1 #b01100 nil)
+ (def smin #b0 #b01101 nil)
+ (def smax #b0 #b01100 nil)
+ (def uhadd #b1 #b00000 nil)
(def uqadd #b1 #b00001)
- (def urhadd #b1 #b00010)
- (def uhsub #b1 #b00100)
+ (def urhadd #b1 #b00010 nil)
+ (def uhsub #b1 #b00100 nil)
(def uqsub #b1 #b00101)
(def addp #b0 #b10111)
- (def shadd #b0 #b00000)
+ (def shadd #b0 #b00000 nil)
(def sqadd #b0 #b00001)
- (def srhadd #b0 #b00010)
- (def shsub #b0 #b00100)
+ (def srhadd #b0 #b00010 nil)
+ (def shsub #b0 #b00100 nil)
(def sqsub #b0 #b00101)
- (def uminp #b1 #b10101)
- (def umaxp #b1 #b10100)
- (def sminp #b0 #b10101)
- (def smaxp #b0 #b10100)
+ (def uminp #b1 #b10101 nil)
+ (def umaxp #b1 #b10100 nil)
+ (def sminp #b0 #b10101 nil)
+ (def smaxp #b0 #b10100 nil)
(def sshl #b0 #b01001)
(def ushl #b1 #b01001))
@@ -3677,6 +3688,7 @@
`(define-instruction ,name (segment rd rn rm size)
(:printer simd-three-same-float ((u ,u) (neg ,neg) (op ,op)))
(:emitter
+ (aver (member size '(:2s :4s :2d)))
(multiple-value-bind (q size) (encode-vector-size size)
(emit-simd-three-same-float
segment
@@ -3759,6 +3771,7 @@
(fpr-offset rn)
(fpr-offset rd)))
(t
+ (aver (member vector-size '(:2s :4s :2d)))
(multiple-value-bind (q size) (encode-vector-size vector-size)
(emit-simd-three-same-float
segment
@@ -4082,6 +4095,7 @@
(:printer simd-across-lanes ((u ,u) (op ,op)
(rd nil :type 'vbhs)))
(:emitter
+ (aver (member size '(:8b :16b :4h :8h :2s :4s)))
(multiple-value-bind (q size) (encode-vector-size size)
(emit-simd-across-lanes
segment
@@ -4171,6 +4185,7 @@
`(define-instruction ,name (segment rd rn size)
(:printer simd-two-misc ((u ,u) (op ,op) (rd nil :type 'simd-reg-2x)))
(:emitter
+ (aver (member size '(:8b :16b :4h :8h :2s :4s)))
(multiple-value-bind (q size) (encode-vector-size size)
(emit-simd-two-misc segment
q
@@ -4366,8 +4381,8 @@
(fpr-offset rn)
(fpr-offset rd)))))))
(def shl #b0 #b01010 nil t)
- (def sli #b1 #b01010)
- (def sri #b1 #b01000 t)
+ (def sli #b1 #b01010 nil t)
+ (def sri #b1 #b01000 t t)
(def sshr #b0 #b00000 t t)
(def shrn #b0 #b10000 t)
(def ssra #b0 #b00010 t t)
diff --git a/src/compiler/arm64/simd-pack.lisp b/src/compiler/arm64/simd-pack.lisp
index 2f4811365..6cedbe04f 100644
--- a/src/compiler/arm64/simd-pack.lisp
+++ b/src/compiler/arm64/simd-pack.lisp
@@ -35,13 +35,13 @@
(zerop (dpb 0 (byte 8 8) (ldb (byte 32 0) value)))
(zerop (dpb 0 (byte 8 16) (ldb (byte 32 0) value)))
(zerop (dpb 0 (byte 8 24) (ldb (byte 32 0) value)))))
- (inst movi dst value :4s))
+ (inst movi dst (ldb (byte 32 0) value) :4s))
((and wordp
(or (zerop (dpb 0 (byte 8 0) (ldb (byte 16 0) value)))
(zerop (dpb 0 (byte 8 8) (ldb (byte 16 0) value)))))
- (inst movi dst value :8h))
+ (inst movi dst (ldb (byte 16 0) value) :8h))
(bytep
- (inst movi dst value :16b))
+ (inst movi dst (ldb (byte 8 0) value) :16b))
((and (member (ldb (byte 8 0) value) '(0 #xFF))
(member (ldb (byte 8 8) value) '(0 #xFF))
(member (ldb (byte 8 16) value) '(0 #xFF))
@@ -50,7 +50,7 @@
(member (ldb (byte 8 40) value) '(0 #xFF))
(member (ldb (byte 8 48) value) '(0 #xFF))
(member (ldb (byte 8 56) value) '(0 #xFF)))
- (inst movi value :2d))
+ (inst movi dst value :2d))
;; Can't do movi, try via the scalar regs.
(wordp
(inst movz tmp-tn (ldb (byte 16 0) value))
diff --git a/src/compiler/arm64/vm.lisp b/src/compiler/arm64/vm.lisp
index 7067eff56..e38541185 100644
--- a/src/compiler/arm64/vm.lisp
+++ b/src/compiler/arm64/vm.lisp
@@ -148,11 +148,11 @@
(complex-single-stack non-descriptor-stack)
(complex-double-stack non-descriptor-stack :element-size 2 :alignment 2)
#+sb-simd-pack
- (int-neon-stack non-descriptor-stack :element-size 2)
+ (int-neon-stack non-descriptor-stack :element-size 2 :alignment 2)
#+sb-simd-pack
- (double-neon-stack non-descriptor-stack :element-size 2)
+ (double-neon-stack non-descriptor-stack :element-size 2 :alignment 2)
#+sb-simd-pack
- (single-neon-stack non-descriptor-stack :element-size 2)
+ (single-neon-stack non-descriptor-stack :element-size 2 :alignment 2)
;; **** Things that can go in the integer registers.
diff --git a/tests/sb-simd.impure.lisp b/tests/sb-simd.impure.lisp
index 0e647a95c..a71bd9b8d 100644
--- a/tests/sb-simd.impure.lisp
+++ b/tests/sb-simd.impure.lisp
@@ -28,6 +28,7 @@
"test-horizontal-functions.lisp"
#+x86-64 "test-horizontal-functions-x86-64.lisp"
#+arm64 "test-horizontal-functions-arm64.lisp"
+ #+arm64 "test-arm64-regressions.lisp"
"test-hairy-simd-functions.lisp"
"test-packages.lisp"))
(load (merge-pathnames file #P"../contrib/sb-simd/test-suite/"))))
-----------------------------------------------------------------------
hooks/post-receive
--
SBCL