Microoptimize type-tests on x86oids.
authorStas Boukarev <stassats@gmail.com>
Sun, 28 Jul 2013 15:42:41 +0000 (19:42 +0400)
committerStas Boukarev <stassats@gmail.com>
Sun, 28 Jul 2013 15:46:09 +0000 (19:46 +0400)
On x86-64 in %test-lowtag instead of doing:

MOV EAX, ECX
AND AL, 15
CMP AL, 15
do
LEA EAX, [RCX-15]
TEST AL, 15

Which allows to save one byte.

On x86 this optimization is already applied, but since LEA loads a
32-bit integer, EAX can be later used as an already untagged pointer
in %test-headers: MOV EAX, [ECX-7] => MOV EAX, [EAX], which takes one
byte less to encode.

src/compiler/x86-64/type-vops.lisp
src/compiler/x86/type-vops.lisp

index 589b2cb..7c12dc3 100644 (file)
   (%test-headers value target not-p nil headers drop-through))
 
 (defun %test-lowtag (value target not-p lowtag)
-  (move-qword-to-eax value)
-  (inst and al-tn lowtag-mask)
-  (inst cmp al-tn lowtag)
-  (inst jmp (if not-p :ne :e) target))
+  (inst lea eax-tn (make-ea :dword :base value :disp (- lowtag)))
+  (inst test al-tn lowtag-mask)
+  (inst jmp (if not-p :nz :z) target))
 
 (defun %test-headers (value target not-p function-p headers
                             &optional (drop-through (gen-label)))
index aca94f3..a1c6655 100644 (file)
@@ -65,6 +65,8 @@
         (if not-p
             (values :ne :a :b drop-through target)
             (values :e :na :nb target drop-through))
+      ;; %test-lowtag loads an untagged pointer into EAX, which allows
+      ;; to avoid untagging below
       (%test-lowtag value when-false t lowtag)
       (cond
         ((and (null (cdr headers))
          ;; [BIGNUM-WIDETAG..FOO-WIDETAG]) is also possible, but such
          ;; opportunities don't come up very often and the code would
          ;; get pretty hairy...
-         (inst cmp (make-ea :byte :base value :disp (- lowtag)) (car headers))
+         (inst cmp (make-ea :byte :base eax-tn) (car headers))
          (inst jmp equal target))
         (t
-         (inst mov al-tn (make-ea :byte :base value :disp (- lowtag)))
+         (inst mov al-tn (make-ea :byte :base eax-tn))
          (do ((remaining headers (cdr remaining)))
              ((null remaining))
            (let ((header (car remaining))