Raymond Toy pushed to branch master at cmucl / cmucl
Commits: 04225fe5 by Raymond Toy at 2024-03-22T09:55:30-07:00 Fix #284: Optimize signed-byte-32-int-len VOP
Take advantage of the fact that `BSR` will not modify the destination register if the source is 0. We already use this idea for the `unsigne-byte-32-int-len` VOP, so let's do the same for this VOP. It saves an instruction and a branch.
- - - - - 274feae4 by Raymond Toy at 2024-03-22T09:58:37-07:00 Update release notes for #284
- - - - - b68de43f by Raymond Toy at 2024-03-22T10:02:07-07:00 Remove comment to rtfm for signed-byte-32-len
Not sure what the comment is referring too. It came in the huge commit [c0c98ded6c]. I think the implementation is correct.
- - - - - 4ffad32e by Raymond Toy at 2024-03-22T13:08:11-07:00 Optimize unsigned-byte-32-int-len some more
Take advantage of the fact that BSR actually moves the src to the dst register when the src is 0. The Intel docs don't says this, but gcc, LLVM, and MSVC compilers basically assume this when generating code that uses BSR.
- - - - - 5538e622 by Raymond Toy at 2024-03-22T19:48:37-07:00 Add some tests for integer-length of signed and unsigned 32-bit ints
Define functions that use the VOPs for integer-length of signed and unsigned 32-bit integers.
Test a few "interesting" integers with these functions.
- - - - - d82f9b92 by Raymond Toy at 2024-03-23T03:09:38+00:00 Merge branch 'issue-284-optimize-signed-byte-32-int-len-vop' into 'master'
Fix #284: Optimize signed and unsigned 32-bit integer length VOPs
Closes #284
See merge request cmucl/cmucl!195 - - - - -
3 changed files:
- src/compiler/x86/arith.lisp - src/general-info/release-21f.md - + tests/integer.lisp
Changes:
===================================== src/compiler/x86/arith.lisp ===================================== @@ -731,7 +731,6 @@ DONE))
-;;; note documentation for this function is wrong - rtfm (define-vop (signed-byte-32-len) (:translate integer-length) (:note _N"inline (signed-byte 32) integer-length") @@ -747,12 +746,9 @@ (inst not res) POS (inst bsr res res) - (inst jmp :z zero) + (inst jmp :z DONE) (inst inc res) (inst shl res 2) - (inst jmp done) - ZERO - (inst xor res res) DONE))
(define-vop (unsigned-byte-32-len) @@ -764,12 +760,11 @@ (:results (res :scs (any-reg))) (:result-types positive-fixnum) (:generator 30 - (move res arg) ;; The Intel docs say that BSR leaves the destination register - ;; undefined if the source is 0. But AMD64 says the destination - ;; register is unchanged. This also appears to be the case for - ;; GCC and LLVM. - (inst bsr res res) + ;; undefined if the source is 0. However, gcc, LLVM, and MSVC + ;; generate code that pretty much says BSR basically moves the + ;; source to the destination if the source is 0. + (inst bsr res arg) (inst jmp :z DONE) ;; The result of BSR is one too small for what we want, so ;; increment the result.
===================================== src/general-info/release-21f.md ===================================== @@ -61,6 +61,7 @@ public domain. least-positive-float * ~~#278~~ Add some more debugging prints to gencgc * ~~#283~~ Add VOP for `integer-length` for `(unsigned-byte 32)` arg. + * ~~#284~~ Microoptimize `signed-byte-32-int-len` VOP for x86. * Other changes: * Improvements to the PCL implementation of CLOS: * Changes to building procedure:
===================================== tests/integer.lisp ===================================== @@ -0,0 +1,38 @@ +;; Tests of integer functions + +(defpackage :integer-tests + (:use :cl :lisp-unit)) + +(in-package "INTEGER-TESTS") + +;; Simple functions for testing INTEGER-LENGTH for numbers of type +;; (unsigned-byte 32) and (signed-byte 32). +(defun integer-length-u32 (n) + (declare (type (unsigned-byte 32) n)) + (integer-length n)) + +(defun integer-length-s32 (n) + (declare (type (signed-byte 32) n)) + (integer-length n)) + +(define-test integer-length.unsigned-byte-32 + (:tag :issues) + (assert-equal 0 (integer-length-u32 0)) + (assert-equal 1 (integer-length-u32 1)) + (assert-equal 31 (integer-length-u32 #x70000000)) + (assert-equal 31 (integer-length-u32 #x7fffffff)) + (assert-equal 32 (integer-length-u32 #xffffffff))) + +(define-test integer-length.signed-byte-32 + (:tag :issues) + (assert-equal 0 (integer-length-s32 0)) + (assert-equal 1 (integer-length-s32 1)) + (assert-equal 31 (integer-length-s32 #x70000000)) + (assert-equal 31 (integer-length-s32 #x7fffffff)) + (assert-equal 0 (integer-length-s32 -1)) + (assert-equal 1 (integer-length-s32 -2)) + (assert-equal 31 (integer-length-s32 #x-70000000)) + (assert-equal 31 (integer-length-s32 #x-7fffffff)) + (assert-equal 31 (integer-length-s32 #x-80000000))) + +
View it on GitLab: https://gitlab.common-lisp.net/cmucl/cmucl/-/compare/62c23d276620926d311ea9c...