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)
(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
should know the connection between an NLE and its CLEANUP.)
--------------------------------------------------------------------------------
#27
-(We always zeroize stack-allocated arrays of boxed elements. The
-previous note here suggested that we could avoid that step on
-platforms with conservative GC; it's not clear to me (NJF) that
-doing so is a wise idea.)
-
-x86 and x86-64 do not zeroize stack-allocated arrays of unboxed
-elements; other platforms could copy what they do.
+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
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:
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
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.