X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler%2Fgeneric%2Fvm-tran.lisp;h=fa3bee30cc691e921069a21255faa9dea09d2bd5;hb=5dcf5905dc38232b3cc5ec6b309ea5c6424db957;hp=3f17ce6023117a60b487f793185fab5687d45fab;hpb=d4e3d480732ff18fd53b4d772fd32e941adb7551;p=sbcl.git diff --git a/src/compiler/generic/vm-tran.lisp b/src/compiler/generic/vm-tran.lisp index 3f17ce6..fa3bee3 100644 --- a/src/compiler/generic/vm-tran.lisp +++ b/src/compiler/generic/vm-tran.lisp @@ -42,7 +42,7 @@ ;;;; simplifying HAIRY-DATA-VECTOR-REF and HAIRY-DATA-VECTOR-SET (deftransform hairy-data-vector-ref ((string index) (simple-string t)) - (let ((ctype (continuation-type string))) + (let ((ctype (lvar-type string))) (if (array-type-p ctype) ;; the other transform will kick in, so that's OK (give-up-ir1-transform) @@ -74,7 +74,7 @@ (deftransform data-vector-ref ((array index) (simple-array t)) - (let ((array-type (continuation-type array))) + (let ((array-type (lvar-type array))) (unless (array-type-p array-type) (give-up-ir1-transform)) (let ((dims (array-type-dimensions array-type))) @@ -91,7 +91,7 @@ (deftransform hairy-data-vector-set ((string index new-value) (simple-string t t)) - (let ((ctype (continuation-type string))) + (let ((ctype (lvar-type string))) (if (array-type-p ctype) ;; the other transform will kick in, so that's OK (give-up-ir1-transform) @@ -126,7 +126,7 @@ (deftransform data-vector-set ((array index new-value) (simple-array t t)) - (let ((array-type (continuation-type array))) + (let ((array-type (lvar-type array))) (unless (array-type-p array-type) (give-up-ir1-transform)) (let ((dims (array-type-dimensions array-type))) @@ -143,7 +143,7 @@ new-value))))) (defoptimizer (%data-vector-and-index derive-type) ((array index)) - (let ((atype (continuation-type array))) + (let ((atype (lvar-type array))) (when (array-type-p atype) (values-specifier-type `(values (simple-array ,(type-specifier @@ -341,17 +341,10 @@ (unless (= numx numy) (return nil)))))))) -;;; FIXME: it is probably worth doing something like this for -;;; SIMPLE-BASE-STRINGs too, if only so that (MAKE-STRING 100000 -;;; :INITIAL-ELEMENT #\Space) doesn't surprise the user with its -;;; performance characteristics. Getting it right is harder than with -;;; bit-vectors, though, as one needs to be more careful with the loop -;;; epilogue so as not to overwrite the convenient extra null byte -;;; (for SB-ALIEN/C termination convention convenience). (deftransform fill ((sequence item) (simple-bit-vector bit) * :policy (>= speed space)) - (let ((value (if (constant-continuation-p item) - (if (= (continuation-value item) 0) + (let ((value (if (constant-lvar-p item) + (if (= (lvar-value item) 0) 0 #.(1- (ash 1 32))) `(if (= item 0) 0 #.(1- (ash 1 32)))))) @@ -372,6 +365,30 @@ (declare (optimize (speed 3) (safety 0)) (type index index end-1)) (setf (%raw-bits sequence index) value)))))) + +(deftransform fill ((sequence item) (simple-base-string base-char) * + :policy (>= speed space)) + (let ((value (if (constant-lvar-p item) + (let* ((char (lvar-value item)) + (code (sb!xc:char-code char))) + (logior code (ash code 8) (ash code 16) (ash code 24))) + `(let ((code (sb!xc:char-code item))) + (logior code (ash code 8) (ash code 16) (ash code 24)))))) + `(let ((length (length sequence)) + (value ,value)) + (multiple-value-bind (times rem) + (truncate length 4) + (do ((index sb!vm:vector-data-offset (1+ index)) + (end (+ times sb!vm:vector-data-offset))) + ((= index end) + (let ((place (* times 4))) + (declare (fixnum place)) + (dotimes (j rem sequence) + (declare (index j)) + (setf (schar sequence (the index (+ place j))) item)))) + (declare (optimize (speed 3) (safety 0)) + (type index index)) + (setf (%raw-bits sequence index) value)))))) ;;;; %BYTE-BLT @@ -422,25 +439,80 @@ (= (double-float-high-bits x) (double-float-high-bits y)))) -;;;; 32-bit operations -#!-x86 ; on X86 it is a modular function -(deftransform lognot ((x) ((unsigned-byte 32)) * - :node node - :result result) - "32-bit implementation" - (let ((dest (continuation-dest result))) - (unless (and (combination-p dest) - (eq (continuation-fun-name (combination-fun dest)) - 'logand)) - (give-up-ir1-transform)) - (unless (some (lambda (arg) - (csubtypep (continuation-type arg) - (specifier-type '(unsigned-byte 32)))) - (combination-args dest)) - (give-up-ir1-transform)) - (setf (node-derived-type node) - (values-specifier-type '(values (unsigned-byte 32) &optional))) - '(32bit-logical-not x))) - +;;;; modular functions (define-good-modular-fun logand) (define-good-modular-fun logior) +;;; FIXME: XOR? ANDC1, ANDC2? -- CSR, 2003-09-16 + +#!-alpha +(progn + (defknown #1=sb!vm::ash-left-mod32 (integer (integer 0)) (unsigned-byte 32) + (foldable flushable movable)) + (define-modular-fun-optimizer ash ((integer count) :width width) + (when (and (<= width 32) + (constant-lvar-p count) ; ? + (plusp (lvar-value count))) + (cut-to-width integer width) + '#1#)) + (setf (gethash '#1# *modular-versions*) '(ash 32))) +#!+alpha +(progn + (defknown #1=sb!vm::ash-left-mod64 (integer (integer 0)) (unsigned-byte 64) + (foldable flushable movable)) + (define-modular-fun-optimizer ash ((integer count) :width width) + (when (and (<= width 64) + (constant-lvar-p count) ; ? + (plusp (lvar-value count))) + (cut-to-width integer width) + '#1#) + (setf (gethash '#1# *modular-versions*) '(ash 64)))) + + +;;; There are two different ways the multiplier can be recoded. The +;;; more obvious is to shift X by the correct amount for each bit set +;;; in Y and to sum the results. But if there is a string of bits that +;;; are all set, you can add X shifted by one more then the bit +;;; position of the first set bit and subtract X shifted by the bit +;;; position of the last set bit. We can't use this second method when +;;; the high order bit is bit 31 because shifting by 32 doesn't work +;;; too well. +(defun ub32-strength-reduce-constant-multiply (arg num) + (declare (type (unsigned-byte 32) num)) + (let ((adds 0) (shifts 0) + (result nil) first-one) + (labels ((add (next-factor) + (setf result + (if result + (progn (incf adds) `(+ ,result ,next-factor)) + next-factor)))) + (declare (inline add)) + (dotimes (bitpos 32) + (if first-one + (when (not (logbitp bitpos num)) + (add (if (= (1+ first-one) bitpos) + ;; There is only a single bit in the string. + (progn (incf shifts) `(ash ,arg ,first-one)) + ;; There are at least two. + (progn + (incf adds) + (incf shifts 2) + `(- (ash ,arg ,bitpos) + (ash ,arg ,first-one))))) + (setf first-one nil)) + (when (logbitp bitpos num) + (setf first-one bitpos)))) + (when first-one + (cond ((= first-one 31)) + ((= first-one 30) (incf shifts) (add `(ash ,arg 30))) + (t + (incf shifts 2) + (incf adds) + (add `(- (ash ,arg 31) + (ash ,arg ,first-one))))) + (incf shifts) + (add `(ash ,arg 31)))) + (values (if (plusp adds) + `(logand ,result #.(1- (ash 1 32))) ; using modular arithmetic + result) + adds + shifts)))