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.
(%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)))
(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))