[prev in list] [next in list] [prev in thread] [next in thread] 

List:       sbcl-commits
Subject:    [Sbcl-commits] master: x86-64: Combine successive shifts
From:       Douglas Katzman via Sbcl-commits <sbcl-commits () lists ! sourceforge ! net>
Date:       2021-08-23 2:29:17
Message-ID: 1629685757.358078.11370 () sfp-scm-5 ! v30 ! lw ! sourceforge ! com
[Download RAW message or body]

The branch "master" has been updated in SBCL:
       via  3552f1afb0178b12d9e7616665c3a86361a72c27 (commit)
      from  d93ec7996f9a3a60ebe49b0562273b0570ad8246 (commit)

- Log -----------------------------------------------------------------
commit 3552f1afb0178b12d9e7616665c3a86361a72c27
Author: Douglas Katzman <dougk@google.com>
Date:   Sun Aug 22 22:15:17 2021 -0400

    x86-64: Combine successive shifts
    
    based on patch in https://groups.google.com/g/sbcl-devel/c/ZXg32_13xBo/m/tFxhuGPUAwAJ
---
 src/compiler/x86-64/insts.lisp   | 24 ++++++++++++++++++++++++
 tests/x86-64-codegen.impure.lisp |  7 +++++++
 2 files changed, 31 insertions(+)

diff --git a/src/compiler/x86-64/insts.lisp b/src/compiler/x86-64/insts.lisp
index 86b0e93d6..445ef1e0d 100644
--- a/src/compiler/x86-64/insts.lisp
+++ b/src/compiler/x86-64/insts.lisp
@@ -3584,6 +3584,30 @@
       (delete-stmt stmt)
       next)))
 
+;;; "SAR x, imm1" + "SAR x, imm2" -> "SAR x, (imm1 + imm2)"
+;;; if imm1 and imm2 are constants and the sum is less than 64.
+;;; The checks on size1 and size2 may be more restrictive than needed.
+(defpattern "sar + sar -> sar" ((sar shr shl) (sar shr shl)) (stmt next)
+  (binding* (((size1 dst1 src1) (parse-2-operands stmt))
+             ((size2 dst2 src2) (parse-2-operands next)))
+    (flet ((compatible (first second)
+             (or (eq first second)
+                 ;; SHR followed by SAR is ok because the SHR will shift in
+                 ;; at least one 0 bit, and the SAR becomes equivalent to SHR.
+                 (and (eq first 'shr) (eq second 'sar)))))
+      (when (and (compatible (stmt-mnemonic stmt) (stmt-mnemonic next))
+                 (location= dst1 dst2)
+                 (eq size1 size2)
+                 (member size2 '(:dword :qword))
+                 (fixnump src1)
+                 (fixnump src2)
+                 (typep (+ src1 src2) `(mod ,(if (eq size1 :dword) 32 64))))
+      (setf (stmt-operands next)
+            `(,(encode-size-prefix size2) ,dst2 ,(+ src1 src2)))
+      (add-stmt-labels next (stmt-labels stmt))
+      (delete-stmt stmt)
+      next))))
+
 ;;; In "{AND,OR,...} reg, src ; TEST reg, reg ; {JMP,SET} {:z,:nz,:s,:ns}"
 ;;; the TEST is unnecessary since ALU operations set the Z and S flags.
 ;;; Per the processor manual, TEST clears OF and CF, so presumably
diff --git a/tests/x86-64-codegen.impure.lisp b/tests/x86-64-codegen.impure.lisp
index 18f5faf6d..297300ebd 100644
--- a/tests/x86-64-codegen.impure.lisp
+++ b/tests/x86-64-codegen.impure.lisp
@@ -1044,3 +1044,10 @@ sb-vm::(define-vop (cl-user::test)
                                 most-negative-fixnum)
   (try-logbitp-walking-bit-test bitsy-sw  :sw  64
                                 (sb-c::mask-signed-field 64 (ash 1 63))))
+
+(with-test (:name :shr+shr-combiner)
+  (let* ((f (compile nil '(lambda (x) (ash (truncate (truly-the sb-vm:word x) 2) -1))))
+         (lines (disassembly-lines f)))
+    (assert
+     (loop for line in lines
+           thereis (and (search "SHR " line) (search ", 2" line))))))

-----------------------------------------------------------------------


hooks/post-receive
-- 
SBCL


_______________________________________________
Sbcl-commits mailing list
Sbcl-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/sbcl-commits
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic