;;;; 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)
(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)))
(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)
(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)))
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
(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))))))
(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))))))
\f
;;;; %BYTE-BLT
:node node
:result result)
"32-bit implementation"
- (let ((dest (continuation-dest result)))
+ (let ((dest (lvar-dest result)))
(unless (and (combination-p dest)
- (eq (continuation-fun-name (combination-fun dest))
+ (eq (lvar-fun-name (combination-fun dest))
'logand))
(give-up-ir1-transform))
(unless (some (lambda (arg)
- (csubtypep (continuation-type arg)
+ (csubtypep (lvar-type arg)
(specifier-type '(unsigned-byte 32))))
(combination-args dest))
(give-up-ir1-transform))
(define-good-modular-fun logand)
(define-good-modular-fun logior)
+\f
+;;; 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 ((tub32 (x) `(truly-the (unsigned-byte 32) ,x))
+ (add (next-factor)
+ (setf result
+ (tub32
+ (if result
+ (progn (incf adds) `(+ ,result ,(tub32 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)
+ `(- ,(tub32 `(ash ,arg ,bitpos))
+ ,(tub32 `(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 `(- ,(tub32 `(ash ,arg 31))
+ ,(tub32 `(ash ,arg ,first-one))))))
+ (incf shifts)
+ (add `(ash ,arg 31))))
+ (values result adds shifts)))