From: Andrea Corallo <akrl@sdf.org>
Date: Mon, 18 Nov 2019 18:35:44 +0000 (+0100)
Subject: allow for pure function call removal optimization
X-Git-Tag: emacs-28.0.90~2727^2~972
X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=16fe8a4678d20eac893bd05941071396b67bc84d;p=emacs.git

allow for pure function call removal optimization
---

diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el
index f805540fcd4..b6a3662ec5d 100644
--- a/lisp/emacs-lisp/comp.el
+++ b/lisp/emacs-lisp/comp.el
@@ -1472,6 +1472,9 @@ PRE-LAMBDA and POST-LAMBDA are called in pre or post-order if non nil."
 
 ;;; propagate pass specific code.
 ;; A very basic propagation pass follows.
+;; This propagates values and types plus in the control flow graph.
+;; Is also responsible for removing function calls to pure functions when
+;; possible.
 
 (defsubst comp-strict-type-of (obj)
   "Given OBJ return its type understanding fixnums."
@@ -1506,29 +1509,39 @@ This can run just once."
        for insn in (comp-block-insns b)
        do (pcase insn
             (`(setimm ,lval ,_ ,v)
-             (setf (comp-mvar-const-vld lval) t)
-             (setf (comp-mvar-constant lval) v)
-             (setf (comp-mvar-type lval) (comp-strict-type-of v)))))))
+             (setf (comp-mvar-const-vld lval) t
+                   (comp-mvar-constant lval) v
+                   (comp-mvar-type lval) (comp-strict-type-of v)))))))
 
 (defsubst comp-mvar-propagate (lval rval)
   "Propagate into LVAL properties of RVAL."
-  (setf (comp-mvar-const-vld lval) (comp-mvar-const-vld rval))
-  (setf (comp-mvar-constant lval) (comp-mvar-constant rval))
-  (setf (comp-mvar-type lval) (comp-mvar-type rval)))
+  (setf (comp-mvar-const-vld lval) (comp-mvar-const-vld rval)
+        (comp-mvar-constant lval) (comp-mvar-constant rval)
+        (comp-mvar-type lval) (comp-mvar-type rval)))
+
+(defsubst comp-function-call-remove (insn f args)
+  "Given INSN when F is pure if all ARGS are known remove the function call."
+  (when (and (get f 'pure) ; Can we just optimize pure here? See byte-opt.el
+             (cl-every #'comp-mvar-const-vld args))
+    (let ((val (apply f (mapcar #'comp-mvar-constant args))))
+      (setf (car insn) 'setimm
+            (caddr insn) (comp-add-const-to-relocs val)))))
 
 (defun comp-propagate-insn (insn)
   "Propagate within INSN."
   (pcase insn
     (`(set ,lval ,rval)
      (pcase rval
-       (`(,(or 'call 'direct-call) ,f . ,_)
+       (`(,(or 'call 'direct-call) ,f . ,args)
         (setf (comp-mvar-type lval)
-              (alist-get f comp-known-ret-types)))
+              (alist-get f comp-known-ret-types))
+        (comp-function-call-remove insn f args))
        (`(,(or 'callref 'direct-callref) ,f . ,args)
         (cl-loop for v in args
                  do (setf (comp-mvar-ref v) t))
         (setf (comp-mvar-type lval)
-              (alist-get f comp-known-ret-types)))
+              (alist-get f comp-known-ret-types))
+        (comp-function-call-remove insn f args))
        (_
         (comp-mvar-propagate lval rval))))
     (`(phi ,lval . ,rest)
diff --git a/test/src/comp-test-funcs.el b/test/src/comp-test-funcs.el
index ca604b748f3..20d15ac0e7a 100644
--- a/test/src/comp-test-funcs.el
+++ b/test/src/comp-test-funcs.el
@@ -252,6 +252,11 @@
 (defun comp-tests-signal-f ()
   (signal 'foo t))
 
+(defun comp-tests-func-call-removal-f ()
+  (let ((a 10)
+	(b 3))
+    (% a b)))
+
 
 ;;;;;;;;;;;;;;;;;;;;
 ;; Tromey's tests ;;
diff --git a/test/src/comp-tests.el b/test/src/comp-tests.el
index 0a1d45724fa..b008dbd574e 100644
--- a/test/src/comp-tests.el
+++ b/test/src/comp-tests.el
@@ -317,6 +317,11 @@ Check that the resulting binaries do not differ."
                      (comp-tests-signal-f)
                    (t err))
                  '(foo . t))))
+
+(ert-deftest comp-tests-func-call-removal ()
+  ;; See `comp-propagate-insn' `comp-function-call-remove'.
+  (should (= (comp-tests-func-call-removal-f) 1)))
+
 
 ;;;;;;;;;;;;;;;;;;;;
 ;; Tromey's tests ;;