X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler%2Fx86%2Ftype-vops.lisp;h=4b8cd454b9f01ee66040239bbac11dca20cfc0de;hb=127fd3d2fb843c6bb7ad0763e143d81877e760e8;hp=949af27782178e0301a53106153518983c142f48;hpb=0d871fd7a98fc4af92a8b942a1154761466ad8c9;p=sbcl.git diff --git a/src/compiler/x86/type-vops.lisp b/src/compiler/x86/type-vops.lisp index 949af27..4b8cd45 100644 --- a/src/compiler/x86/type-vops.lisp +++ b/src/compiler/x86/type-vops.lisp @@ -13,25 +13,8 @@ ;;;; test generation utilities -;;; Emit the most compact form of the test immediate instruction, -;;; using an 8 bit test when the immediate is only 8 bits and the -;;; value is one of the four low registers (eax, ebx, ecx, edx) or the -;;; control stack. (defun generate-fixnum-test (value) - (let ((offset (tn-offset value))) - (cond ((and (sc-is value any-reg descriptor-reg) - (or (= offset eax-offset) (= offset ebx-offset) - (= offset ecx-offset) (= offset edx-offset))) - (inst test (make-random-tn :kind :normal - :sc (sc-or-lose 'byte-reg) - :offset offset) - 3)) - ((sc-is value control-stack) - (inst test (make-ea :byte :base ebp-tn - :disp (- (* (1+ offset) n-word-bytes))) - 3)) - (t - (inst test value 3))))) + (emit-optimized-test-inst value 3)) (defun %test-fixnum (value target not-p) (generate-fixnum-test value) @@ -85,65 +68,77 @@ (values :ne :a :b drop-through target) (values :e :na :nb target drop-through)) (%test-lowtag value when-false t lowtag al-loaded) - (inst mov al-tn (make-ea :byte :base value :disp (- lowtag))) - (do ((remaining headers (cdr remaining))) - ((null remaining)) - (let ((header (car remaining)) - (last (null (cdr remaining)))) - (cond - ((atom header) - (cond - ((and (not last) (null (cddr remaining)) - (atom (cadr remaining)) - (= (logcount (logxor header (cadr remaining))) 1)) - ;; BASE-STRING, (VECTOR NIL), BIT-VECTOR, (VECTOR T) - (inst and al-tn (ldb (byte 8 0) (logeqv header (cadr remaining)))) - (inst cmp al-tn (ldb (byte 8 0) (logand header (cadr remaining)))) - (inst jmp equal target) - (return)) - (t - (inst cmp al-tn header) - (if last + (cond + ((and (null (cdr headers)) + (numberp (car headers))) + ;; Optimize the common case: referencing the value from memory + ;; is slightly smaller than loading it and then doing the + ;; comparison. Doing this for other cases (e.g. range of + ;; [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 jmp equal target)) + (t + (inst mov al-tn (make-ea :byte :base value :disp (- lowtag))) + (do ((remaining headers (cdr remaining))) + ((null remaining)) + (let ((header (car remaining)) + (last (null (cdr remaining)))) + (cond + ((atom header) + (cond + ((and (not last) (null (cddr remaining)) + (atom (cadr remaining)) + (= (logcount (logxor header (cadr remaining))) 1)) + ;; BASE-STRING, (VECTOR NIL), BIT-VECTOR, (VECTOR T) + (inst and al-tn (ldb (byte 8 0) (logeqv header (cadr remaining)))) + (inst cmp al-tn (ldb (byte 8 0) (logand header (cadr remaining)))) (inst jmp equal target) - (inst jmp :e when-true))))) - (t - (let ((start (car header)) - (end (cdr header))) - (cond - ;; LAST = don't need al-tn later - ((and last (not (= start bignum-widetag)) - (= (+ start 4) end) (= (logcount (logxor start end)) 1)) - ;; SIMPLE-STRING - (inst and al-tn (ldb (byte 8 0) (logeqv start end))) - (inst cmp al-tn (ldb (byte 8 0) (logand start end))) - (inst jmp equal target)) - ((and (not last) (null (cddr remaining)) - (= (+ start 4) end) (= (logcount (logxor start end)) 1) - (listp (cadr remaining)) - (= (+ (caadr remaining) 4) (cdadr remaining)) - (= (logcount (logxor (caadr remaining) (cdadr remaining))) 1) - (= (logcount (logxor (caadr remaining) start)) 1)) - ;; STRING - (inst and al-tn (ldb (byte 8 0) (logeqv start (cdadr remaining)))) - (inst cmp al-tn (ldb (byte 8 0) (logand start (cdadr remaining)))) - (inst jmp equal target) - ;; we've shortcircuited the DO, so we must return. - ;; It's OK to do so, because (NULL (CDDR REMAINING)) - ;; was true. - (return)) - (t - (unless (= start bignum-widetag) - (inst cmp al-tn start) - (if (= end complex-array-widetag) - (progn - (aver last) - (inst jmp greater-or-equal target)) - (inst jmp :b when-false))) ; was :l - (unless (= end complex-array-widetag) - (inst cmp al-tn end) - (if last - (inst jmp less-or-equal target) - (inst jmp :be when-true)))))))))) ; was :le + (return)) + (t + (inst cmp al-tn header) + (if last + (inst jmp equal target) + (inst jmp :e when-true))))) + (t + (let ((start (car header)) + (end (cdr header))) + (cond + ;; LAST = don't need al-tn later + ((and last (not (= start bignum-widetag)) + (= (+ start 4) end) (= (logcount (logxor start end)) 1)) + ;; SIMPLE-STRING + (inst and al-tn (ldb (byte 8 0) (logeqv start end))) + (inst cmp al-tn (ldb (byte 8 0) (logand start end))) + (inst jmp equal target)) + ((and (not last) (null (cddr remaining)) + (= (+ start 4) end) (= (logcount (logxor start end)) 1) + (listp (cadr remaining)) + (= (+ (caadr remaining) 4) (cdadr remaining)) + (= (logcount (logxor (caadr remaining) (cdadr remaining))) 1) + (= (logcount (logxor (caadr remaining) start)) 1)) + ;; STRING + (inst and al-tn (ldb (byte 8 0) (logeqv start (cdadr remaining)))) + (inst cmp al-tn (ldb (byte 8 0) (logand start (cdadr remaining)))) + (inst jmp equal target) + ;; we've shortcircuited the DO, so we must return. + ;; It's OK to do so, because (NULL (CDDR REMAINING)) + ;; was true. + (return)) + (t + (unless (= start bignum-widetag) + (inst cmp al-tn start) + (if (= end complex-array-widetag) + (progn + (aver last) + (inst jmp greater-or-equal target)) + (inst jmp :b when-false))) ; was :l + (unless (= end complex-array-widetag) + (inst cmp al-tn end) + (if last + (inst jmp less-or-equal target) + (inst jmp :be when-true)))))))))))) ; was :le (emit-label drop-through)))) ;;;; type checking and testing