double->single float conversion isn't a no-op on x87 anymore
[sbcl.git] / src / compiler / x86-64 / pred.lisp
index 428c2c1..8f2abbd 100644 (file)
@@ -95,8 +95,7 @@
    the values, and VOP-name the name of the VOP that will be used
    to execute the conditional move.")
 
-(!def-vm-support-routine
-    convert-conditional-move-p (node dst-tn x-tn y-tn)
+(defun convert-conditional-move-p (node dst-tn x-tn y-tn)
   (declare (ignore node))
   (let* ((ptype (sb!c::tn-primitive-type dst-tn))
          (name  (sb!c::primitive-type-name ptype))
   (:conditional :e)
   (:policy :fast-safe)
   (:translate eq)
-  (:generator 3
+  (:generator 6
     (cond
      ((sc-is y immediate)
       (let ((val (tn-value y)))
                                character-widetag))))))
       (t
        (inst cmp x y)))))
+
+;; The template above is a very good fallback for the generic
+;; case.  However, it is sometimes possible to perform unboxed
+;; comparisons.  Repurpose char= and eql templates here, instead
+;; of forcing values to be boxed and then compared.
+;;
+;; We only weaken EQL => EQ for characters and fixnums, and detect
+;; when types definitely mismatch.  No need to import other EQL
+;; VOPs (e.g. floats).
+(macrolet ((def (eq-name eql-name cost)
+             `(define-vop (,eq-name ,eql-name)
+                (:translate eq)
+                (:variant-cost ,cost))))
+  (def fast-if-eq-character fast-char=/character 3)
+  (def fast-if-eq-character/c fast-char=/character/c 2)
+  (def fast-if-eq-fixnum fast-eql/fixnum 3)
+  (def fast-if-eq-fixnum/c fast-eql-c/fixnum 2)
+  (def fast-if-eq-signed fast-if-eql/signed 5)
+  (def fast-if-eq-signed/c fast-if-eql-c/signed 4)
+  (def fast-if-eq-unsigned fast-if-eql/unsigned 5)
+  (def fast-if-eq-unsigned/c fast-if-eql-c/unsigned 4))