faster SVREF and (SETF SVREF) compilation
authorNikodemus Siivola <nikodemus@random-state.net>
Sun, 17 Mar 2013 11:54:17 +0000 (13:54 +0200)
committerNikodemus Siivola <nikodemus@random-state.net>
Sun, 17 Mar 2013 12:06:51 +0000 (14:06 +0200)
NEWS
src/compiler/array-tran.lisp

diff --git a/NEWS b/NEWS
index 2207042..27bca79 100644 (file)
--- 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)
index baeb93b..a595e63 100644 (file)
                   `(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