In aliencomp.c #+(and ppc darwin) should be #!+(and ppc darwin), which
[sbcl.git] / OPTIMIZATIONS
index df2c49b..3795bf4 100644 (file)
@@ -11,9 +11,6 @@
 
 * On X86 I is represented as a tagged integer.
 
-* EQL uses "CMP reg,reg" instead of "CMP reg,im". This causes
-  allocation of an extra register and an extra move.
-
 * Unnecessary move:
   3: SLOT S!11[EDX] {SB-C::VECTOR-LENGTH 1 7} => t23[EAX]
   4: MOVE t23[EAX] => t24[EBX]
@@ -65,54 +62,14 @@ VOP DATA-VECTOR-SET/SIMPLE-STRING V2!14[EDI] t32[EAX] t30[S2]>t33[CL]
 
 * And why two moves?
 --------------------------------------------------------------------------------
-#5
-(loop repeat 1.5)
-
-uses generic arithmetic
---------------------------------------------------------------------------------
-#6
-09:49:05 <jtra> I have found a case in those where suboptimal code is
-  generate with nested loops, it might be moderately easy to fix that
-09:49:28 <jtra> see
-  http://www.bagley.org/~doug/shootout/bench/nestedloop/nestedloop.cmucl
-09:50:30 <jtra> if you add declarations to dotimes, generated code is
-  almost optimal, but most inner loops run out of registers and use
-  memory location for iteration variable
-
-;;; -*- mode: lisp -*-
-;;; http://www.bagley.org/~doug/shootout/
-;;; from Friedrich Dominicus
-
-(defun main ()
-  (let ((n (parse-integer (or (car (last extensions:*command-line-strings*)) "1")))
-        (x 0))
-    (declare (fixnum n)
-             (fixnum x)
-             (optimize (speed 3) (debug 0) (safety 0)))
-    (dotimes (a n)
-      (dotimes (b n)
-        (dotimes (c n)
-          (dotimes (d n)
-            (dotimes (e n)
-              (dotimes (f n)
-                (incf x)))))))
-   (format t "~A~%" x)))
---------------------------------------------------------------------------------
-#7
-(defun foo (x)
-  (declare (optimize speed (debug 0)))
-  (if (< x 0) x (foo (1- x))))
-
-SBCL generates a full call of FOO (but CMUCL does not).
---------------------------------------------------------------------------------
 #8
 (defun foo (d)
   (declare (optimize (speed 3) (safety 0) (debug 0)))
   (declare (type (double-float 0d0 1d0) d))
   (loop for i fixnum from 1 to 5
-     for x1 double-float = (sin d) ;;; !!!
-     do (loop for j fixnum from 1 to 4
-             sum x1 double-float)))
+        for x1 double-float = (sin d) ;;; !!!
+        do (loop for j fixnum from 1 to 4
+                 sum x1 double-float)))
 
 Without the marked declaration Python will use boxed representation for X1.
 
@@ -162,3 +119,156 @@ It could be optimized to
 
 tests lowtag.
 --------------------------------------------------------------------------------
+#13
+FAST-+/FIXNUM and similar should accept unboxed arguments in interests
+of representation selection. Problem: inter-TN dependencies.
+--------------------------------------------------------------------------------
+#14
+The derived type of (/ (THE (DOUBLE-FLOAT (0D0)) X) (THE (DOUBLE-FLOAT
+1D0) Y)) is (DOUBLE-FLOAT 0.0d0). While it might be reasonable, it is
+better to derive (OR (MEMBER 0.0d0) (DOUBLE-FLOAT (0.0d0))).
+--------------------------------------------------------------------------------
+#15
+On the alpha, the system is reluctant to refer directly to a constant bignum,
+preferring to load a large constant through a slow sequence of instructions,
+then cons up a bignum for it:
+
+(LAMBDA (A)
+  (DECLARE (OPTIMIZE (SAFETY 1) (SPEED 3) (DEBUG 1))
+           (TYPE (INTEGER -10000 10000) A)
+           (IGNORABLE A))
+  (CASE A
+    ((89 125 16) (ASH A (MIN 18 -706)))
+    (T (DPB -3 (BYTE 30 30) -1))))
+--------------------------------------------------------------------------------
+#16
+(do ((i 0 (1+ i)))
+    ((= i (the (integer 0 100) n)))
+  ...)
+
+It is commonly expected for Python to derive (FIXNUMP I). (If ``='' is
+replaced with ``>='', Python will do.)
+--------------------------------------------------------------------------------
+#17 
+Type tests for (ARRAY BIT), (ARRAY T) and similar go through full
+%TYPEP, even though it is relatively simple to establish the arrayness
+of an object and also to obtain the element type of an array.  As of
+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)
+           (let ((l (list nil nil)))
+             (setf (first l) x)
+             (setf (second l) (1- x))
+             l)))
+    (let ((l (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.
+--------------------------------------------------------------------------------
+#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.
+b. Implement local unknown-values mv-call (useful for fast type checking).
+--------------------------------------------------------------------------------
+#26
+SBCL cannot derive upper bound for I and uses generic arithmetic here:
+
+(defun foo (l)
+  (declare (vector l))
+  (dotimes (i (length l))
+    (if (block nil
+          (map-foo (lambda (x) (if x (return t)))
+                   l))
+        t
+        nil)))
+
+(So the constraint propagator or a possible future SSA-convertor
+should know the connection between an NLE and its CLEANUP.)
+--------------------------------------------------------------------------------
+#27
+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.
+--------------------------------------------------------------------------------
+#28
+a. Accessing raw slots in structure instances is more inefficient than
+it could be; if we placed raw slots before the header word, we would
+not need to do arithmetic at runtime to access them.  (But beware:
+this would complicate handling of the interior pointer).
+
+b. (Also note that raw slots are currently disabled on HPPA)
+--------------------------------------------------------------------------------
+#29
+Python is overly zealous when converting high-level CL functions, such
+as MIN/MAX, LOGBITP, and LOGTEST, to low-level CL functions.  Reducing
+Python's aggressiveness would make it easier to effect changes such as
+
+x86-64:
+* direct MIN/MAX on {SINGLE,DOUBLE}-FLOATs ({MIN,MAX}S{S,D})
+
+x86-64:
+* direct LOGBITP on word-sized integers and fixnums (BT + JC)
+
+x86{,-64}/PPC:
+* branch-free MIN/MAX on word-sized integers and fixnums (floats could
+  be handled too, modulo safety considerations on the PPC)
+
+x86-64:
+* efficient LOGTESTs on word-sized integers and fixnums (TEST)
+
+etc., etc.
+
+(The framework for this has been implemented as of 0.9.9.18; see the
+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.