X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=OPTIMIZATIONS;h=42119acef2c0fd7a33780ca56d3204fa5fd5ec6a;hb=HEAD;hp=d234ce3d432b468991a5460afaea9236847fb055;hpb=f68d0f59fa6f9c448b3a147b5940937af03f940a;p=sbcl.git diff --git a/OPTIMIZATIONS b/OPTIMIZATIONS index d234ce3..42119ac 100644 --- a/OPTIMIZATIONS +++ b/OPTIMIZATIONS @@ -157,20 +157,6 @@ sbcl-0.8.12.30, this affects at least DUMP-OBJECT through COMPOUND-OBJECT-P, and (LABELS MAYBE-EMIT-MAKE-LOAD-FORMS GROVEL) through TYPEP UNBOXED-ARRAY, within the compiler itself. -------------------------------------------------------------------------------- -#18 -(lambda (x) (declare (null x)) (sxhash x)) goes through SYMBOL-HASH -rather than either constant-folding or manipulating NIL-VALUE or -NULL-TN directly. --------------------------------------------------------------------------------- -#19 - (let ((dx (if (foo) - (list x) - (list y z)))) - (declare (dynamic-extent dx)) - ...) - -DX is not allocated on stack. --------------------------------------------------------------------------------- #20 (defun-with-dx foo (x) (flet ((make (x) @@ -182,26 +168,13 @@ DX is not allocated on stack. (declare (dynamic-extent l)) (mapc #'print l)))) -Result of MAKE is not stack allocated, which means that -stack-allocation of structures is impossible. --------------------------------------------------------------------------------- -#21 -(defun-with-dx foo () - (let ((dx (list (list 1 2) (list 3 4)))) - (declare (dynamic-extent dx)) - ...)) - -External list in DX is allocated on stack, but internal are not. +Result of MAKE is not stack allocated. -------------------------------------------------------------------------------- #22 IR2 does not perform unused code flushing. -------------------------------------------------------------------------------- -#23 -Python does not know that &REST lists are LISTs (and cannot derive it). --------------------------------------------------------------------------------- #24 -a. Iterations on &REST lists, returning them as VALUES could be - rewritten with &MORE vectors. +a. Iterations on &REST lists could be rewritten with &MORE vectors. b. Implement local unknown-values mv-call (useful for fast type checking). -------------------------------------------------------------------------------- #26 @@ -224,6 +197,16 @@ Initialization of stack-allocated arrays is inefficient: we always fill the vector with zeroes, even when it is not needed (as for platforms with conservative GC or for arrays of unboxed objectes) and is performed later explicitely. + +(This is harder than it might look at first glance, as MAKE-ARRAY is smart +enough to eliminate something like ':initial-element 0'. Such an optimization +is valid if the vector is being allocated in the heap, but not if it is being +allocated on the stack. You could remove this optimization, but that makes +the heap-allocated case somewhat slower...) + +To do this, extend ALLOCATE-VECTOR with ALLOW-JUNK argument, and when +stack allocating don't zero if it is true -- and probably ALLOW-JUNK iff +the vector is a specialized one (cannot have pointers.) -------------------------------------------------------------------------------- #28 a. Accessing raw slots in structure instances is more inefficient than @@ -258,21 +241,6 @@ vm-support-routine COMBINATION-IMPLEMENTATION-STYLE and its use in src/compiler/ir1opt.lisp, IR1-OPTIMIZE-COMBINATION. The above optimizations are left as an exercise for the reader.) -------------------------------------------------------------------------------- -#30 -(defun foo (x y) - (< x y)) - -FOO's IR1 representation is roughly: - -(defun foo (x y) - (if (< x y) - T - NIL)) - -However, if a full call is generated for < (and similarly for other -predicate functions), then the IF is unnecessary, since the return value -of (< x y) is already T or NIL. --------------------------------------------------------------------------------- #31 The typecheck generated for a declaration like (integer 0 45) on x86 looks like: @@ -322,32 +290,6 @@ using the x86 FP stack. It would be nice if SBCL included an SSE2-based floating point backend with a compile-time option to switch between the two. -------------------------------------------------------------------------------- -#34 -Compiling - -(defun foo (x y) - (declare (type (integer 0 45) x y)) - (+ x y)) - -results in the following error trapping code for type-checking the -arguments: - -; 424: L0: 8B058CE31812 MOV EAX, [#x1218E38C] ; '(MOD 46) -; 42A: 0F0B0A BREAK 10 ; error trap -; 42D: 05 BYTE #X05 -; 42E: 1F BYTE #X1F ; OBJECT-NOT-TYPE-ERROR -; 42F: FECE01 BYTE #XFE, #XCE, #X01 ; EDI -; 432: 0E BYTE #X0E ; EAX -; 433: L1: 8B0590E31812 MOV EAX, [#x1218E390] ; '(MOD 46) -; 439: 0F0B0A BREAK 10 ; error trap -; 43C: 03 BYTE #X03 -; 43D: 1F BYTE #X1F ; OBJECT-NOT-TYPE-ERROR -; 43E: 8E BYTE #X8E ; EDX -; 43F: 0E BYTE #X0E ; EAX - -Notice that '(MOD 46) has two entries in the constant vector. Having -one would be preferable. --------------------------------------------------------------------------------- #35 Compiling @@ -405,8 +347,60 @@ all three comparisons or b) eliminated the necessity of the MOV(s) altogether. The former option is probably easier than the latter. -------------------------------------------------------------------------------- -#37 +#38 + +(setf (subseq s1 start1 end1) (subseq s2 start2 end1)) + +could be transformed into + +(let ((#:s2 s2) + (#:start2 start2) + (#:end2 end2)) + (replace s1 #:s2 :start1 start1 :end1 end1 :start2 #:start2 :end2 #:end2)) + +when the return value is unused, avoiding the need to cons up the new sequence. + +-------------------------------------------------------------------------------- +#39 + +(let ((*foo* 42)) ...) + +currently compiles to code that ensures the TLS index at runtime, which +is both a decently large chunk of code and unnecessary, as we could ensure +the TLS index at load-time as well. + +-------------------------------------------------------------------------------- +#40 + +When FTYPE is declared -- to say (function (t t t t t) t), and +function has a compiler-macro, + + (apply #'foo 'x1 x2 'x3 more) + +can be transformed into + + (apply (lambda (x2 x4 x5) (foo 'x1 x2 'x3 x4 x5)) x2 more) + +which allows compiler-macro-expansion for FOO. (Only constant +arguments can be moved inside the new lambda -- otherwise evaluation +order is altered.) + +-------------------------------------------------------------------------------- +#41 + +The unibyte external formats are written in a very generic way. Three +optimizations immediately applicable that could be automatically +generated: + +(a) if the external format merely permutes the first 256 characters, a + constant-time lookup (rather than a binary search) could be + performed on output. This applies at least to EBCDIC, which + currently has a hand-rolled mapper instead. -Dynamic extent allocation doesn't currently work for one-element lists, -since there's a source transform from (LIST X) to (CONS X NIL). +(b) if there are no undefined characters corresponding to the 256 + codes, then no error checking need be done on input. +(c) if there is a way to use particular bits of the exceptional + characters, constant-time output (rather than binary search) can + still be achieved as used to be done by the latin-9 external + format before 1.0.31.