The following 2 silly functions reproduce the situation I'm facing
while optimizing a function that bins lots of line segments.

(defun test0 (xmin)
  (declare (single-float xmin)
           (optimize (safety 0) (speed 3)))
  (flet ((get-x-index (x)
           (declare (single-float x))
           (the fixnum (truncate (- x xmin)))))
    (loop for i of-type Fixnum from 0 to 10
          for x of-type Single-Float = (random 100.0)
          do (print (list (get-x-index x))))))

(defun test1 (xmin)
  (declare (single-float xmin)
           (optimize (safety 0) (speed 3)))
  (let ((x-ht (make-hash-table)))
    (declare (hash-table x-ht))
    (flet ((get-x-index (x)
             (declare (single-float x))
             (let ((index (gethash x x-ht nil)))
               (unless index
                 (setf index
                       (setf (gethash x x-ht)
                             (the fixnum (truncate (- x xmin))))))
               index)))
      (loop for i of-type Fixnum from 0 to 10
            for x of-type Single-Float = (random 100.0)
            do (print (list (get-x-index x)))))))

The only difference between TEST0 and TEST1 is the local function
GET-X-INDEX.  The one in TEST1 does memoization with a hash table;
the one in TEST1 does not.  Compiling TEST0 doesn't generate any
efficiency notes.  Compiling TEST1 generates 1 efficiency note:
* (compile 'test1)
; In: LAMBDA (XMIN)

;   (LOOP FOR I OF-TYPE FIXNUM ...)
; --> BLOCK LET LET ANSI-LOOP::LOOP-BODY TAGBODY ANSI-LOOP::LOOP-REALLY-DESETQ 
; ==>
;   (SETQ X (RANDOM 100.0))
; Note: Doing float to pointer coercion (cost 13) to X.
; 
; Compiling Top-Level Form: 

; Compilation unit finished.
;   1 note

As I understand from reading Sections 5.11.10 and 5.13.3 of the CMUCL
user's manual, GET-X-INDEX is local call and this "float to pointer coercion"
efficiency note probably should not be issued.  Could anybody show me how
to make the compiler not to make this float-to-pointer coercion?  So far I
have tried the following in vain:
  1. using (THE FIXNUM INDEX), instead of INDEX, at the end of GET-X-INDEX.
  2. adding a (ftype (function (single-float) fixnum) get-x-index) declaration.
  3. using a hast table whose HASH-TABLE-TEST was defined by
     (ext:define-hash-table-test 'sf=
                                 #'(lambda (x y)
                                     (declare (single-float x y))
                                     (= x y))
                                 #'(lambda (x)
                                     (declare (single-float x))
                                     (values (sxhash x) nil)))
     and using (ext:truly-the single-float x) in GETHASH.

Any ideas?  Thanks a lot.

-cph


Reply via email to