Micro-optimizations in MOVE-IMMEDIATE and MOVE-ARG on x86-64
authorLutz Euler <lutz.euler@freenet.de>
Wed, 25 Apr 2012 22:49:06 +0000 (00:49 +0200)
committerLutz Euler <lutz.euler@freenet.de>
Wed, 25 Apr 2012 22:49:06 +0000 (00:49 +0200)
In MOVE-IMMEDIATE, when the target is in memory, avoid using a temporary
register for more values than currently: The MOV instruction can move
immediate values of type (SIGNED-BYTE 32) into 64-bit memory locations,
not only (SIGNED-BYTE 31).

Simplify a TYPE-CASE in MOVE-ARG: merge two clauses that generated
exactly the same MOV instruction; spare a call to MOVE-IMMEDIATE and
get rid of two ugly literal 29s thereby.

Add a test.

src/compiler/x86-64/move.lisp
tests/compiler.pure.lisp

index 7872710..cc0a777 100644 (file)
           (sc-is target signed-reg unsigned-reg descriptor-reg any-reg))
      (inst mov target val))
     ;; Likewise if the value is small enough.
-    ((typep val '(signed-byte 31))
+    ((typep val '(signed-byte 32))
      (inst mov target val))
     ;; Otherwise go through the temporary register
     (tmp-tn
              (etypecase val
                ((integer 0 0)
                 (zeroize y))
-               ((or (signed-byte 29) (unsigned-byte 29))
-                (inst mov y (fixnumize val)))
                (integer
-                (move-immediate y (fixnumize val)))
+                (inst mov y (fixnumize val)))
                (symbol
                 (load-symbol y val))
                (character
index fe4bd64..68b37d1 100644 (file)
           (unless (= (funcall fun 16) (logand 15 (1- (ash 1 width))))
             (push (cons width extra) result)))))
     (assert (null result))))
+
+;; On x86-64 MOVE-IMMEDIATE of fixnum values into memory either directly
+;; uses a MOV into memory or goes through a temporary register if the
+;; value is larger than a certain number of bits. Check that it respects
+;; the limits of immediate arguments to the MOV instruction (if not, the
+;; assembler will fail an assertion) and doesn't have sign-extension
+;; problems. (The test passes fixnum constants through the MOVE VOP
+;; which calls MOVE-IMMEDIATE.)
+(with-test (:name :constant-fixnum-move)
+  (let ((f (compile nil `(lambda (g)
+                           (funcall g
+                                    ;; The first three args are
+                                    ;; uninteresting as they are
+                                    ;; passed in registers.
+                                    1 2 3
+                                    ,@(loop for i from 27 to 32
+                                            collect (expt 2 i)))))))
+    (assert (every #'plusp (funcall f #'list)))))