diff options
| author | Andrea Corallo | 2020-12-15 23:53:29 +0100 |
|---|---|---|
| committer | Andrea Corallo | 2020-12-21 20:22:03 +0100 |
| commit | 07b75deea9febd2cb6fd4d3467e909df341e96fb (patch) | |
| tree | 4059a350554164e34a28b72d645eaec49b34f51f | |
| parent | 23791cf74da9c2e6369f2c15ef180ef2a8c21656 (diff) | |
| download | emacs-07b75deea9febd2cb6fd4d3467e909df341e96fb.tar.gz emacs-07b75deea9febd2cb6fd4d3467e909df341e96fb.zip | |
Enhance type inference constraining function arguments
* lisp/emacs-lisp/comp.el: Add some commentary.
(comp-cond-cstrs-target-mvar): Rename and update docstring.
(comp-add-cond-cstrs): Update to use
`comp-cond-cstrs-target-mvar'.
(comp-emit-call-cstr, comp-lambda-list-gen, comp-add-call-cstr):
New functions.
(comp-add-cstrs): Call `comp-add-call-cstr'.
* test/src/comp-tests.el (comp-tests-type-spec-tests): Update two
type specifier tests.
| -rw-r--r-- | lisp/emacs-lisp/comp.el | 80 | ||||
| -rw-r--r-- | test/src/comp-tests.el | 4 |
2 files changed, 73 insertions, 11 deletions
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index e8db2383c41..6f1ef26ac78 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el | |||
| @@ -1868,7 +1868,19 @@ into the C code forwarding the compilation unit." | |||
| 1868 | (comp-add-func-to-ctxt (comp-limplify-top-level t)))) | 1868 | (comp-add-func-to-ctxt (comp-limplify-top-level t)))) |
| 1869 | 1869 | ||
| 1870 | 1870 | ||
| 1871 | ;;; conditional branches rewrite pass specific code. | 1871 | ;;; add-cstrs pass specific code. |
| 1872 | |||
| 1873 | ;; This pass is responsible for adding constraints, these are | ||
| 1874 | ;; generated from: | ||
| 1875 | ;; | ||
| 1876 | ;; - Conditional branches: each branch taken or non taken can be used | ||
| 1877 | ;; in the CFG to infer infomations on the tested variables. | ||
| 1878 | ;; | ||
| 1879 | ;; - Function calls: function calls to function assumed to be not | ||
| 1880 | ;; redefinable can be used to add constrains on the function | ||
| 1881 | ;; arguments. Ex: if we execute successfully (= x y) we know that | ||
| 1882 | ;; afterwards both x and y must satisfy the (or number marker) | ||
| 1883 | ;; type specifier. | ||
| 1872 | 1884 | ||
| 1873 | (defun comp-emit-assume (target rhs bb negated) | 1885 | (defun comp-emit-assume (target rhs bb negated) |
| 1874 | "Emit an assume for mvar TARGET being RHS. | 1886 | "Emit an assume for mvar TARGET being RHS. |
| @@ -1907,10 +1919,10 @@ The assume is emitted at the beginning of the block BB." | |||
| 1907 | (cl-return (puthash bb-symbol new-bb (comp-func-blocks comp-func))) | 1919 | (cl-return (puthash bb-symbol new-bb (comp-func-blocks comp-func))) |
| 1908 | finally (cl-assert nil))) | 1920 | finally (cl-assert nil))) |
| 1909 | 1921 | ||
| 1910 | (defun comp-add-cond-cstrs-target-mvar (mvar exit-insn bb) | 1922 | ;; Cheap substitute to a copy propagation pass... |
| 1911 | "Given MVAR search in BB what we'll use as assume target. | 1923 | (defun comp-cond-cstrs-target-mvar (mvar exit-insn bb) |
| 1912 | Keep on searching till EXIT-INSN is encountered. | 1924 | "Given MVAR search in BB the original mvar MVAR got assigned from. |
| 1913 | Return the corresponding rhs mvar." | 1925 | Keep on searching till EXIT-INSN is encountered." |
| 1914 | (cl-flet ((targetp (x) | 1926 | (cl-flet ((targetp (x) |
| 1915 | ;; Ret t if x is an mvar and target the correct slot number. | 1927 | ;; Ret t if x is an mvar and target the correct slot number. |
| 1916 | (and (comp-mvar-p x) | 1928 | (and (comp-mvar-p x) |
| @@ -1955,10 +1967,8 @@ TARGET-BB-SYM is the symbol name of the target block." | |||
| 1955 | (comment ,_comment-str) | 1967 | (comment ,_comment-str) |
| 1956 | (cond-jump ,cond ,(pred comp-mvar-p) . ,blocks)) | 1968 | (cond-jump ,cond ,(pred comp-mvar-p) . ,blocks)) |
| 1957 | (cl-loop | 1969 | (cl-loop |
| 1958 | with target-mvar1 = (comp-add-cond-cstrs-target-mvar op1 (car insns-seq) | 1970 | with target-mvar1 = (comp-cond-cstrs-target-mvar op1 (car insns-seq) b) |
| 1959 | b) | 1971 | with target-mvar2 = (comp-cond-cstrs-target-mvar op2 (car insns-seq) b) |
| 1960 | with target-mvar2 = (comp-add-cond-cstrs-target-mvar op2 (car insns-seq) | ||
| 1961 | b) | ||
| 1962 | for branch-target-cell on blocks | 1972 | for branch-target-cell on blocks |
| 1963 | for branch-target = (car branch-target-cell) | 1973 | for branch-target = (car branch-target-cell) |
| 1964 | for assume-target = (comp-add-cond-cstrs-target-block b branch-target) | 1974 | for assume-target = (comp-add-cond-cstrs-target-block b branch-target) |
| @@ -1970,6 +1980,57 @@ TARGET-BB-SYM is the symbol name of the target block." | |||
| 1970 | do (comp-emit-assume target-mvar2 op1 assume-target negated) | 1980 | do (comp-emit-assume target-mvar2 op1 assume-target negated) |
| 1971 | finally (cl-return-from in-the-basic-block))))))) | 1981 | finally (cl-return-from in-the-basic-block))))))) |
| 1972 | 1982 | ||
| 1983 | (defun comp-emit-call-cstr (mvar call-cell cstr) | ||
| 1984 | "Emit a constraint CSTR for MVAR after CALL-CELL." | ||
| 1985 | (let ((next-cell (cdr call-cell)) | ||
| 1986 | (new-cell `((assume ,(make-comp-mvar :slot (comp-mvar-slot mvar)) | ||
| 1987 | (and ,mvar ,cstr))))) | ||
| 1988 | (setf (cdr call-cell) new-cell | ||
| 1989 | (cdr new-cell) next-cell | ||
| 1990 | (comp-func-ssa-status comp-func) 'dirty))) | ||
| 1991 | |||
| 1992 | (defun comp-lambda-list-gen (lambda-list) | ||
| 1993 | "Return a generator to iterate over LAMBDA-LIST." | ||
| 1994 | (lambda () | ||
| 1995 | (cl-case (car lambda-list) | ||
| 1996 | (&optional | ||
| 1997 | (setf lambda-list (cdr lambda-list)) | ||
| 1998 | (prog1 | ||
| 1999 | (car lambda-list) | ||
| 2000 | (setf lambda-list (cdr lambda-list)))) | ||
| 2001 | (&rest | ||
| 2002 | (cadr lambda-list)) | ||
| 2003 | (t | ||
| 2004 | (prog1 | ||
| 2005 | (car lambda-list) | ||
| 2006 | (setf lambda-list (cdr lambda-list))))))) | ||
| 2007 | |||
| 2008 | (defun comp-add-call-cstr () | ||
| 2009 | "Add args assumptions for each function of which the type specifier is known." | ||
| 2010 | (cl-loop | ||
| 2011 | for bb being each hash-value of (comp-func-blocks comp-func) | ||
| 2012 | do | ||
| 2013 | (comp-loop-insn-in-block bb | ||
| 2014 | (when-let ((match | ||
| 2015 | (pcase insn | ||
| 2016 | (`(set ,lhs (,(pred comp-call-op-p) ,f . ,args)) | ||
| 2017 | (when-let ((cstr-f (gethash f comp-known-func-cstr-h))) | ||
| 2018 | (cl-values cstr-f lhs args))) | ||
| 2019 | (`(,(pred comp-call-op-p) ,f . ,args) | ||
| 2020 | (when-let ((cstr-f (gethash f comp-known-func-cstr-h))) | ||
| 2021 | (cl-values cstr-f nil args)))))) | ||
| 2022 | (cl-multiple-value-bind (cstr-f lhs args) match | ||
| 2023 | (cl-loop | ||
| 2024 | for arg in args | ||
| 2025 | for gen = (comp-lambda-list-gen (comp-cstr-f-args cstr-f)) | ||
| 2026 | for cstr = (funcall gen) | ||
| 2027 | for target = (comp-cond-cstrs-target-mvar arg insn bb) | ||
| 2028 | when (and target | ||
| 2029 | (or (null lhs) | ||
| 2030 | (not (eql (comp-mvar-slot lhs) | ||
| 2031 | (comp-mvar-slot target))))) | ||
| 2032 | do (comp-emit-call-cstr target insn-cell cstr))))))) | ||
| 2033 | |||
| 1973 | (defun comp-add-cstrs (_) | 2034 | (defun comp-add-cstrs (_) |
| 1974 | "Rewrite conditional branches adding appropriate 'assume' insns. | 2035 | "Rewrite conditional branches adding appropriate 'assume' insns. |
| 1975 | This is introducing and placing 'assume' insns in use by fwprop | 2036 | This is introducing and placing 'assume' insns in use by fwprop |
| @@ -1984,6 +2045,7 @@ blocks." | |||
| 1984 | (not (comp-func-has-non-local f))) | 2045 | (not (comp-func-has-non-local f))) |
| 1985 | (let ((comp-func f)) | 2046 | (let ((comp-func f)) |
| 1986 | (comp-add-cond-cstrs) | 2047 | (comp-add-cond-cstrs) |
| 2048 | (comp-add-call-cstr) | ||
| 1987 | (comp-log-func comp-func 3)))) | 2049 | (comp-log-func comp-func 3)))) |
| 1988 | (comp-ctxt-funcs-h comp-ctxt))) | 2050 | (comp-ctxt-funcs-h comp-ctxt))) |
| 1989 | 2051 | ||
diff --git a/test/src/comp-tests.el b/test/src/comp-tests.el index 4ea8dbbadb3..a3e887bde95 100644 --- a/test/src/comp-tests.el +++ b/test/src/comp-tests.el | |||
| @@ -872,14 +872,14 @@ Return a list of results." | |||
| 872 | (if (= x 3) | 872 | (if (= x 3) |
| 873 | 'foo | 873 | 'foo |
| 874 | x)) | 874 | x)) |
| 875 | (or (member foo) (integer * 2) (integer 4 *))) | 875 | (or (member foo) marker number)) |
| 876 | 876 | ||
| 877 | ;; 13 | 877 | ;; 13 |
| 878 | ((defun comp-tests-ret-type-spec-8-4-f (x y) | 878 | ((defun comp-tests-ret-type-spec-8-4-f (x y) |
| 879 | (if (= x y) | 879 | (if (= x y) |
| 880 | x | 880 | x |
| 881 | 'foo)) | 881 | 'foo)) |
| 882 | t) | 882 | (or (member foo) marker number)) |
| 883 | 883 | ||
| 884 | ;; 14 | 884 | ;; 14 |
| 885 | ((defun comp-tests-ret-type-spec-9-1-f (x) | 885 | ((defun comp-tests-ret-type-spec-9-1-f (x) |