+ (= (double-float-high-bits x) (double-float-high-bits y))))
+
+\f
+;;;; modular functions
+(define-good-modular-fun logand :unsigned)
+(define-good-modular-fun logior :unsigned)
+;;; FIXME: XOR? ANDC1, ANDC2? -- CSR, 2003-09-16
+
+(macrolet
+ ((def (name class width)
+ (let ((type (ecase class
+ (:unsigned 'unsigned-byte)
+ (:signed 'signed-byte))))
+ `(progn
+ (defknown ,name (integer (integer 0)) (,type ,width)
+ (foldable flushable movable))
+ (define-modular-fun-optimizer ash ((integer count) ,class :width width)
+ (when (and (<= width ,width)
+ (or (and (constant-lvar-p count)
+ (plusp (lvar-value count)))
+ (csubtypep (lvar-type count)
+ (specifier-type '(and unsigned-byte fixnum)))))
+ (cut-to-width integer ,class width)
+ ',name))
+ (setf (gethash ',name (modular-class-versions (find-modular-class ',class)))
+ `(ash ,',width))))))
+ ;; This should really be dependent on SB!VM:N-WORD-BITS, but since we
+ ;; don't have a true Alpha64 port yet, we'll have to stick to
+ ;; SB!VM:N-MACHINE-WORD-BITS for the time being. --njf, 2004-08-14
+ #!+#.(cl:if (cl:= 32 sb!vm:n-machine-word-bits) '(and) '(or))
+ (progn
+ #!+x86 (def sb!vm::ash-left-smod30 :signed 30)
+ (def sb!vm::ash-left-mod32 :unsigned 32))
+ #!+#.(cl:if (cl:= 64 sb!vm:n-machine-word-bits) '(and) '(or))
+ (progn
+ #!+x86-64 (def sb!vm::ash-left-smod61 :signed 61)
+ (def sb!vm::ash-left-mod64 :unsigned 64)))
+
+\f
+;;;; word-wise logical operations
+
+;;; These transforms assume the presence of modular arithmetic to
+;;; generate efficient code.
+
+(define-source-transform word-logical-not (x)
+ `(logand (lognot (the sb!vm:word ,x)) #.(1- (ash 1 sb!vm:n-word-bits))))
+
+(deftransform word-logical-and ((x y))
+ '(logand x y))
+
+(deftransform word-logical-nand ((x y))
+ '(logand (lognand x y) #.(1- (ash 1 sb!vm:n-word-bits))))
+
+(deftransform word-logical-or ((x y))
+ '(logior x y))
+
+(deftransform word-logical-nor ((x y))
+ '(logand (lognor x y) #.(1- (ash 1 sb!vm:n-word-bits))))
+
+(deftransform word-logical-xor ((x y))
+ '(logxor x y))
+
+(deftransform word-logical-eqv ((x y))
+ '(logand (logeqv x y) #.(1- (ash 1 sb!vm:n-word-bits))))
+
+(deftransform word-logical-orc1 ((x y))
+ '(logand (logorc1 x y) #.(1- (ash 1 sb!vm:n-word-bits))))
+
+(deftransform word-logical-orc2 ((x y))
+ '(logand (logorc2 x y) #.(1- (ash 1 sb!vm:n-word-bits))))
+
+(deftransform word-logical-andc1 ((x y))
+ '(logand (logandc1 x y) #.(1- (ash 1 sb!vm:n-word-bits))))
+
+(deftransform word-logical-andc2 ((x y))
+ '(logand (logandc2 x y) #.(1- (ash 1 sb!vm:n-word-bits))))
+
+\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 ((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)))
+
+\f
+;;; Transform GET-LISP-OBJ-ADDRESS for constant immediates, since the normal
+;;; VOP can't handle them.
+
+(deftransform sb!vm::get-lisp-obj-address ((obj) ((constant-arg fixnum)))
+ (ash (lvar-value obj) sb!vm::n-fixnum-tag-bits))