sb-simd: Trouble with sse+xmm0 encoding
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
SBCL |
Fix Released
|
Undecided
|
Unassigned |
Bug Description
There is an issue with the sse+xmm0 encoding in https:/
(require "SB-SIMD")
(setf sb-ext:
(macrolet
((fudge ()
(sb-simd-
(sb-simd-
(sb-simd-
(values (fudge) (let ((bar (fudge))) bar)))
=> #<SIMD-PACK +18014398509481984 +8>, #<SIMD-PACK -34359738367 -4294967295>
Here is a snippet of the output of the following:
(flet ((foo (a b mask)
(declare (optimize (debug 1)))
(sb-simd-
(sb-disassem:
; 4ED: F30F6F5DB8 MOVDQU XMM3, [RBP-72]
; 4F2: 660F6F5201 MOVDQA XMM2, [RDX+1]
; 4F7: F30F6F45C8 MOVDQU XMM0, [RBP-56]
; 4FC: 660F6FC2 MOVDQA XMM0, XMM2
; 500: 660F6FD0 MOVDQA XMM2, XMM0
; 504: 660F3810D3 PBLENDVB XMM2, XMM3, XMM0
It appears that XMM2 (mask) overwrites XMM0 (a).
Compare that to the snippet from
(flet ((foo (a b mask)
(declare (optimize (debug 3)))
(sb-simd-
(sb-disassem:
; 2DF: 660F6F6801 MOVDQA XMM5, [RAX+1]
; 2E4: 66410F6F6001 MOVDQA XMM4, [R8+1]
; 2EA: 660F6F5A01 MOVDQA XMM3, [RDX+1]
; 2EF: 41807D0800 CMP BYTE PTR [R13+8], 0 ; thread.stepping
; 2F4: 7402 JEQ L3
; 2F6: CC0E INT3 14 ; single-step trap (before)
; 2F8: L3: 660F6FC3 MOVDQA XMM0, XMM3
; 2FC: 660F6FD5 MOVDQA XMM2, XMM5
; 300: 660F3810D4 PBLENDVB XMM2, XMM4, XMM0
and, given (s64.2-blend a b mask) == (s64.2-if mask b a), note that
(values
(sb-simd:s64-if 18014398509481984 -35184372088833 -34359738367)
(sb-simd:s64-if 8 31 -4294967295))
=> -34359738367, -4294967295
(values
(sb-simd:s64-if 18014398509481984 -35184372088833 18014398509481984)
(sb-simd:s64-if 8 31 8))
=> 18014398509481984, 8
which explains the behavior of the test case.
I attached a patch which modifies the routine to check if xmm0 is in use before assigning to it. The test suite currently passes with and without the current patch. But if you apply the diff below and then run the test suite (or just the code following the diff), you will see that the tests for the sse4.1 -if functions fail with the current code and pass with this patch.
---
contrib/
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/contrib/
index 79fba2e9f.
--- a/contrib/
+++ b/contrib/
@@ -62,7 +62,7 @@
(let ((name (intern-test-name test-name)))
`(prog1 ',name
(defun ,name ()
- (declare (optimize (debug 3) (safety 3)))
+ (declare (optimize (debug 1) (safety 3)))
--
2.39.1
;; From tests/sb-
(with-compilati
(dolist (file '("packages.lisp"
"numbers.lisp"
"utilities.
"test-
"test-
"test-
"test-
"test-
"test-
(load (merge-pathnames file #P"../contrib/
(dolist (test sb-simd-
(when (and (search "SSE4.1" (symbol-name test))
(search "IF" (symbol-name test)))
(handler-case (funcall test)
(simple-error (c) (format t ": ~A~%" c)))))
One more thing: if you open contrib/
Changed in sbcl: | |
status: | New → Fix Committed |
Changed in sbcl: | |
status: | Fix Committed → Fix Released |