From: Nikodemus S. <de...@us...> - 2009-05-16 12:23:49
|
Update of /cvsroot/sbcl/sbcl/src/compiler/generic In directory fdv4jf1.ch3.sourceforge.com:/tmp/cvs-serv22761/src/compiler/generic Modified Files: vm-fndb.lisp vm-ir2tran.lisp Log Message: 1.0.28.51: better MAKE-ARRAY transforms * Add a source transform for MAKE-ARRAY that declaims LIST and VECTOR as NOTINLINE, so the the MAKE-ARRAY deftransforms are able to pick them apart (for DIMENSIONS and :INITIAL-CONTENTS.) * INITIALIZE-VECTOR is a new magic function with a IR2-CONVERT transform. It's purpose is to allow open coding :INITIAL-CONTENTS initialization without inhibiting stack allocation. * Turns out that making stack allocation decisions during locall analysis is not enough since optimization iterates: if a transform occurs and introduces new LVARs that would be good for DX after the locall analysis has run for the combination, the new LVARs will not get their share of stacky goodness. Therefore, after a transform propagate DX information to the new functional explicitly (see MAYBE-PROPAGATE-DYNAMIC-EXTENT.) * The new logic is in TRANSFORM-MAKE-ARRAY-VECTOR, which handles all the cases of vector allocation with a known element type: ** :INITIAL-CONTENTS (LIST ...), (VECTOR ...) and (BACKQ-LIST ...) are picked apart when the length matches the vector length, and their arguments are spliced into the call. Constant :INITIAL-CONTENTS is picked apart as well. Initialization is done using INITIALIZE-VECTOR. ** Otherwise :INITIAL-CONTENTS is splatted in place using REPLACE after we have checked that the length matches. ** :INITIAL-ELEMENT not EQL to the default element uses FILL. ** Otherwise the default initialization is fine. Some additional hair here, since MAYBE-PROPAGATE-DYNAMIC-EXTENT cannot deal with OPTIONAL-DISPATCH functionals. So to ensure we get full benefit of it, make sure the lambdas we transform to have only required arguments -- courtesy of new ELIMINATE-KEYWORD-ARGUMENT utility. (Note: it might be worth it to do something like this for many cases automatically, to reduce the number of lambdas the compiler generates. For inline lambdas we could do the whole &key handling _before_ the lambda is converted...) * Identify the case of (LIST N) as dimensions as being a vector, and delegate to TRANSFORM-MAKE-ARRAY-VECTOR. * More efficient allocation of simple multidimensional arrays in the presence of :INITIAL-CONTENTS (still slow, though) and :INITIAL-ELEMENT (not bad.) * Fix the source transform for VECTOR so that it too can stack allocate. * Updates tests and docs. Index: vm-fndb.lisp =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/compiler/generic/vm-fndb.lisp,v retrieving revision 1.52 retrieving revision 1.53 diff -u -d -r1.52 -r1.53 --- vm-fndb.lisp 16 May 2009 11:24:31 -0000 1.52 +++ vm-fndb.lisp 16 May 2009 12:23:14 -0000 1.53 @@ -88,6 +88,11 @@ (defknown %set-symbol-hash (symbol hash) t (unsafe)) +(defknown initialize-vector ((simple-array * (*)) &rest t) + (simple-array * (*)) + (always-translatable) + :result-arg 0) + (defknown vector-fill* (t t t t) vector (unsafe) :result-arg 0) Index: vm-ir2tran.lisp =================================================================== RCS file: /cvsroot/sbcl/sbcl/src/compiler/generic/vm-ir2tran.lisp,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- vm-ir2tran.lisp 16 May 2009 11:24:31 -0000 1.22 +++ vm-ir2tran.lisp 16 May 2009 12:23:14 -0000 1.23 @@ -16,13 +16,6 @@ (defoptimizer (%make-structure-instance stack-allocate-result) ((&rest args) node dx) t) -(defoptimizer (make-array stack-allocate-result) ((&rest args) node dx) - ;; The actual stack allocation decision will be made on the basis of what - ;; ALLOCATE-VECTOR, but this is needed so that (FILL (MAKE-ARRAY N) X) and - ;; (REPLACE (MAKE-ARRAY (LENGTH V)) V) can potentially stack allocate the - ;; new vector. - t) - (defoptimizer ir2-convert-reffer ((object) node block name offset lowtag) (let* ((lvar (node-lvar node)) (locs (lvar-result-tns lvar @@ -162,6 +155,52 @@ (emit-inits node block name result lowtag words `((:dd . ,c-dd) ,@c-slot-specs) args) (move-lvar-result node block locs lvar)))) +(defoptimizer (initialize-vector ir2-convert) + ((vector &rest initial-contents) node block) + (let* ((vector-ctype (lvar-type vector)) + (elt-ctype (if (array-type-p vector-ctype) + (array-type-specialized-element-type vector-ctype) + (bug "Unknow vector type in IR2 conversion for ~S." + 'initialize-vector))) + (saetp (find-saetp-by-ctype elt-ctype)) + (lvar (node-lvar node)) + (locs (lvar-result-tns lvar (list (primitive-type vector-ctype)))) + (result (first locs)) + (elt-ptype (primitive-type elt-ctype)) + (tmp (make-normal-tn elt-ptype))) + (emit-move node block (lvar-tn node block vector) result) + (flet ((compute-setter () + (macrolet + ((frob () + (let ((*package* (find-package :sb!vm)) + (clauses nil)) + (map nil (lambda (s) + (when (sb!vm:saetp-specifier s) + (push + `(,(sb!vm:saetp-typecode s) + (lambda (index tn) + #!+(or x86 x86-64) + (vop ,(symbolicate "DATA-VECTOR-SET-WITH-OFFSET/" + (sb!vm:saetp-primitive-type-name s)) + node block result index tn 0 tn) + #!-(or x86 x86-64) + (vop ,(symbolicate "DATA-VECTOR-SET/" + (sb!vm:saetp-primitive-type-name s)) + node block result index tn tn))) + clauses))) + sb!vm:*specialized-array-element-type-properties*) + `(ecase (sb!vm:saetp-typecode saetp) + ,@(nreverse clauses))))) + (frob))) + (tnify (index) + (constant-tn (find-constant index)))) + (let ((setter (compute-setter)) + (length (length initial-contents))) + (dotimes (i length) + (emit-move node block (lvar-tn node block (pop initial-contents)) tmp) + (funcall setter (tnify i) tmp)))) + (move-lvar-result node block locs lvar))) + ;;; :SET-TRANS (in objdef.lisp DEFINE-PRIMITIVE-OBJECT) doesn't quite ;;; cut it for symbols, where under certain compilation options ;;; (e.g. #!+SB-THREAD) we have to do something complicated, rather |