Optimize (unsigned-byte 32/64) type tests on x86oids.
authorStas Boukarev <stassats@gmail.com>
Sun, 28 Jul 2013 16:41:58 +0000 (20:41 +0400)
committerStas Boukarev <stassats@gmail.com>
Sun, 28 Jul 2013 16:41:58 +0000 (20:41 +0400)
Instead of doing
TEST CL, 3
MOV EAX, ECX

do
MOV EAX, ECX
TEST AL, 3

AL has shorter encoding and can save 1 byte with ECX or 4 bytes with
ESI, which doesn't have SIL on x86.

Also revert a part of the previous commit which used untagged
pointers, which can cause problems with the GC.

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

index 7c12dc3..5f2e78f 100644 (file)
               (values not-target target)
               (values target not-target))
         ;; Is it a fixnum?
-        (generate-fixnum-test value)
+        ;; Is it a fixnum?
         (move rax-tn value)
+        (inst test al-tn fixnum-tag-mask)
         (inst jmp :e fixnum)
 
         ;; If not, is it an other pointer?
index a1c6655..fd4b9d0 100644 (file)
@@ -14,7 +14,7 @@
 ;;;; test generation utilities
 
 (defun generate-fixnum-test (value)
-  (emit-optimized-test-inst value 3))
+  (emit-optimized-test-inst value fixnum-tag-mask))
 
 (defun %test-fixnum (value target not-p)
   (generate-fixnum-test value)
@@ -65,8 +65,6 @@
         (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 eax-tn) (car headers))
+         (inst cmp (make-ea :byte :base value :disp (- lowtag)) (car headers))
          (inst jmp equal target))
         (t
-         (inst mov al-tn (make-ea :byte :base eax-tn))
+         (inst mov al-tn (make-ea :byte :base value :disp (- lowtag)))
          (do ((remaining headers (cdr remaining)))
              ((null remaining))
            (let ((header (car remaining))
               (values not-target target)
               (values target not-target))
         ;; Is it a fixnum?
-        (generate-fixnum-test value)
         (move eax-tn value)
+        (inst test al-tn fixnum-tag-mask)
         (inst jmp :e fixnum)
 
         ;; If not, is it an other pointer?