Raymond Toy pushed to branch issue-294-xoroshiro-lisp-assem-routine at cmucl / cmucl
Commits: 91a947c4 by Raymond Toy at 2024-03-31T07:52:16-07:00 generate-return-sequence generated incorrect :raw return
When the return style is `:raw`, we generated the wrong sequence of instructions because `generate-return-sequence` is supposed to return a list of the instructions. We were returning the "instructions" `inst` and `ret` instead of `(inst ret)`.
- - - - - 06445c08 by Raymond Toy at 2024-03-31T07:54:58-07:00 Define a vop for the xoroshiro-update assembly routine.
The generated VOP basically does what we want and is the same as the hand-written one in compiler/x86/arith.lisp.
To make this work, just needed to add `:arg-types` and `:result-types` options.
- - - - - c42702ce by Raymond Toy at 2024-03-31T08:03:45-07:00 Some cleanups and comments
Rename `result[01]` back to `r[01]`. Add some comments and move the description of the algorithm from the body of the assembly routine to the comment before the definition of the assembly routine.
- - - - - 4910c4f0 by Raymond Toy at 2024-03-31T08:05:54-07:00 Remove the hand-written update VOP
This VOP is now generated by the assembly routine and is basically identical to what we wrote here. Hence, we don't need this, which was commented out anyway.
- - - - -
3 changed files:
- src/assembly/x86/arith.lisp - src/assembly/x86/support.lisp - src/compiler/x86/arith.lisp
Changes:
===================================== src/assembly/x86/arith.lisp ===================================== @@ -412,15 +412,41 @@ (inst pop k) (inst ret))
- -#+(and random-xoroshiro assembler) +;;; Support for the xoroshiro128** generator. See +;;; https://prng.di.unimi.it/xoroshiro128starstar.c for the official +;;; code. +;;; +;;; This is what we're implementing, where s[] is our state vector. +;;; +;;; static uint64_t s[2]; +;;; static inline uint64_t rotl(const uint64_t x, int k) { +;;; return (x << k) | (x >> (64 - k)); +;;; } +;;; +;;; uint64_t next(void) { +;;; const uint64_t s0 = s[0]; +;;; uint64_t s1 = s[1]; +;;; const uint64_t result = rotl(s0 * 5, 7) * 9; +;;; +;;; s1 ^= s0; +;;; s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b +;;; s[1] = rotl(s1, 37); // c +;;; +;;; return result; +;;; } +;;; +;;; A VOP is also generated to call this assembly routine. This +;;; routine computes a new 64-bit random number and also updates the +;;; state, which is (simple-array (double-float) (2)). +#+random-xoroshiro (define-assembly-routine (xoroshiro-update - (:translate kernel::xoroshiro-update) + (:translate kernel::random-xoroshiro-update) (:return-style :raw) (:cost 30) - (:policy :safe) - (:save-p t)) + (:policy :fast-safe) + (:arg-types simple-array-double-float) + (:result-types unsigned-num unsigned-num)) ((:arg state descriptor-reg eax-offset) (:res r1 unsigned-reg edx-offset) (:res r0 unsigned-reg ebx-offset) @@ -428,26 +454,6 @@ (:temp s1 double-reg xmm1-offset) (:temp t0 double-reg xmm2-offset) (:temp t1 double-reg xmm3-offset)) - ;; See https://prng.di.unimi.it/xoroshiro128starstar.c for the official code. - ;; - ;; This is what we're implementing, where s[] is our state vector. - ;; - ;; static uint64_t s[2]; - ;; static inline uint64_t rotl(const uint64_t x, int k) { - ;; return (x << k) | (x >> (64 - k)); - ;; } - ;; - ;; uint64_t next(void) { - ;; const uint64_t s0 = s[0]; - ;; uint64_t s1 = s[1]; - ;; const uint64_t result = rotl(s0 * 5, 7) * 9; - ;; - ;; s1 ^= s0; - ;; s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b - ;; s[1] = rotl(s1, 37); // c - ;; - ;; return result; - ;; }
;; s0 = state[0] (inst movsd s0 (make-ea :dword :base state @@ -522,5 +528,4 @@ vm:word-bytes) (* 8 1)) vm:other-pointer-type)) - s1) - (inst ret)) + s1))
===================================== src/assembly/x86/support.lisp ===================================== @@ -39,7 +39,7 @@ (def-vm-support-routine generate-return-sequence (style) (ecase style (:raw - `(inst ret)) + `((inst ret))) (:full-call `( (inst pop eax-tn)
===================================== src/compiler/x86/arith.lisp ===================================== @@ -1812,34 +1812,6 @@ )
#+random-xoroshiro -(progn (defknown kernel::random-xoroshiro-update ((simple-array double-float (2))) (values (unsigned-byte 32) (unsigned-byte 32)) (movable)) - - -(define-vop (random-xoroshiro-update) - (:policy :fast-safe) - (:translate kernel::random-xoroshiro-update) - (:args (state :scs (descriptor-reg) :target state-arg)) - (:arg-types simple-array-double-float) - (:results (hi :scs (unsigned-reg)) - (lo :scs (unsigned-reg))) - (:result-types unsigned-num unsigned-num) - (:temporary (:sc descriptor-reg :offset eax-offset) state-arg) - (:temporary (:sc double-reg :offset xmm0-offset) s0) - (:temporary (:sc double-reg :offset xmm1-offset) s1) - (:temporary (:sc double-reg :offset xmm2-offset) t0) - (:temporary (:sc double-reg :offset xmm3-offset) t1) - (:temporary (:sc unsigned-reg :offset edx-offset :target hi) r1) - (:temporary (:sc unsigned-reg :offset ebx-offset :target lo) r0) - (:generator 50 - (move state-arg state) - (move s0 s0) - (move s1 s1) - (move t0 t0) - (move t1 t1) - (inst call (make-fixup 'vm::xoroshiro-update :assembly-routine)) - (move hi r1) - (move lo r0))) -)
View it on GitLab: https://gitlab.common-lisp.net/cmucl/cmucl/-/compare/204c9c34731d07e2b274c29...