use LEA Y, [X+X] instead of LEA Y, [X*2] where appropriate on x86-64
authorNathan Froyd <froydnj@gmail.com>
Fri, 13 Apr 2012 15:05:18 +0000 (11:05 -0400)
committerNathan Froyd <froydnj@gmail.com>
Fri, 13 Apr 2012 17:26:34 +0000 (13:26 -0400)
The former instruction is slightly smaller.  Keep the old form around
for people who want to compile x86-64 with smaller fixnums.

src/compiler/x86-64/arith.lisp
src/compiler/x86-64/move.lisp

index 0e0be28..4878c68 100644 (file)
     (inst idiv eax y)
     (if (location= quo eax)
         (inst shl eax n-fixnum-tag-bits)
-        (inst lea quo (make-ea :qword :index eax
-                               :scale (ash 1 n-fixnum-tag-bits))))
+        (if (= n-fixnum-tag-bits 1)
+            (inst lea quo (make-ea :qword :base eax :index eax))
+            (inst lea quo (make-ea :qword :index eax
+                                   :scale (ash 1 n-fixnum-tag-bits)))))
     (move rem edx)))
 
 (define-vop (fast-truncate-c/fixnum=>fixnum fast-safe-arith-op)
     (inst idiv eax y-arg)
     (if (location= quo eax)
         (inst shl eax n-fixnum-tag-bits)
-        (inst lea quo (make-ea :qword :index eax
-                               :scale (ash 1 n-fixnum-tag-bits))))
+        (if (= n-fixnum-tag-bits 1)
+            (inst lea quo (make-ea :qword :base eax :index eax))
+            (inst lea quo (make-ea :qword :index eax
+                                   :scale (ash 1 n-fixnum-tag-bits)))))
     (move rem edx)))
 
 (define-vop (fast-truncate/unsigned=>unsigned fast-safe-arith-op)
index 1b084d0..7872710 100644 (file)
   (:generator 1
     (cond ((and (sc-is x signed-reg unsigned-reg)
                 (not (location= x y)))
-           ;; Uses 7 bytes, but faster on the Pentium
-           (inst lea y (make-ea :qword :index x
-                                :scale (ash 1 n-fixnum-tag-bits))))
+           (if (= n-fixnum-tag-bits 1)
+               (inst lea y (make-ea :qword :base x :index x))
+               (inst lea y (make-ea :qword :index x
+                                    :scale (ash 1 n-fixnum-tag-bits)))))
           (t
            ;; Uses: If x is a reg 2 + 3; if x = y uses only 3 bytes
            (move y x)
       ;; you change stuff here, make sure the sign flag doesn't get
       ;; overwritten before the CALL!
       (inst test x y)
-      ;; Faster but bigger then SHL Y 4. The cost of doing this
-      ;; speculatively should be noise compared to bignum consing if
-      ;; that is needed and saves one branch.
-      (inst lea y (make-ea :qword :index x :scale (ash 1 n-fixnum-tag-bits)))
+      ;; Using LEA is faster but bigger than MOV+SHL; it also doesn't
+      ;; twiddle the sign flag.  The cost of doing this speculatively
+      ;; should be noise compared to bignum consing if that is needed
+      ;; and saves one branch.
+      (if (= n-fixnum-tag-bits 1)
+          (inst lea y (make-ea :qword :base x :index x))
+          (inst lea y (make-ea :qword :index x
+                               :scale (ash 1 n-fixnum-tag-bits))))
       (inst jmp :z done)
       (inst mov y x)
       (inst lea temp-reg-tn