From: Nikodemus Siivola Date: Sun, 17 Mar 2013 11:54:17 +0000 (+0200) Subject: faster SVREF and (SETF SVREF) compilation X-Git-Url: http://repo.macrolet.net/gitweb/?a=commitdiff_plain;h=0892423b9a4f2f8f9ca0096964deb4680e8441de;p=sbcl.git faster SVREF and (SETF SVREF) compilation --- diff --git a/NEWS b/NEWS index 2207042..27bca79 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,8 @@ changes relative to sbcl-1.1.5: as a keyword argument to sb-c:defknown (after attributes). Useful to allow defknown to be re-loaded. Use with :allow-other-keys t for backward compatibility. + * optimization: compiler is much faster in compiling SVREF and (SETF SVREF) + forms. * bug fix: Prevent a make-array transform from modifying source forms causing problems for inlined code. Thanks to Bart Botta. (regression since 1.0.42.11-bis) diff --git a/src/compiler/array-tran.lisp b/src/compiler/array-tran.lisp index baeb93b..a595e63 100644 --- a/src/compiler/array-tran.lisp +++ b/src/compiler/array-tran.lisp @@ -1009,10 +1009,44 @@ `(aref (the ,',type ,a) ,i)) (define-source-transform ,setter (a i v) `(%aset (the ,',type ,a) ,i ,v))))) - (define-frob svref %svset simple-vector) (define-frob schar %scharset simple-string) (define-frob char %charset string)) +;;; We transform SVREF and %SVSET directly into DATA-VECTOR-REF/SET: this is +;;; around 100 times faster than going through the general-purpose AREF +;;; transform which ends up doing a lot of work -- and introducing many +;;; intermediate lambdas, each meaning a new trip through the compiler -- to +;;; get the same result. +;;; +;;; FIXME: [S]CHAR, and [S]BIT above would almost certainly benefit from a similar +;;; treatment. +(define-source-transform svref (vector index) + (let ((elt-type (or (when (symbolp vector) + (let ((var (lexenv-find vector vars))) + (when var + (type-specifier + (array-type-declared-element-type (lambda-var-type var)))))) + t))) + (with-unique-names (n-vector) + `(let ((,n-vector ,vector)) + (the ,elt-type (data-vector-ref + (the simple-vector ,n-vector) + (%check-bound ,n-vector (length ,n-vector) ,index))))))) + +(define-source-transform %svset (vector index value) + (let ((elt-type (or (when (symbolp vector) + (let ((var (lexenv-find vector vars))) + (when var + (type-specifier + (array-type-declared-element-type (lambda-var-type var)))))) + t))) + (with-unique-names (n-vector) + `(let ((,n-vector ,vector)) + (truly-the ,elt-type (data-vector-set + (the simple-vector ,n-vector) + (%check-bound ,n-vector (length ,n-vector) ,index) + (the ,elt-type ,value))))))) + (macrolet (;; This is a handy macro for computing the row-major index ;; given a set of indices. We wrap each index with a call ;; to %CHECK-BOUND to ensure that everything works out