diff options
| author | Andrea Corallo | 2024-03-26 11:14:08 +0100 |
|---|---|---|
| committer | Andrea Corallo | 2024-03-26 11:14:08 +0100 |
| commit | 8cc67dbcec0753c5579e63bf82bfe247debe222c (patch) | |
| tree | 1e35b49a8a150785138ccf4889888bc40252a0a0 | |
| parent | b7b9a0a5c1afae07b8168e85dcf1fc37d29e98ef (diff) | |
| download | emacs-8cc67dbcec0753c5579e63bf82bfe247debe222c.tar.gz emacs-8cc67dbcec0753c5579e63bf82bfe247debe222c.zip | |
Fix native comp prediction on null functionp tested objects
* lisp/emacs-lisp/comp.el (comp-known-predicates)
(comp-known-predicates-h): Update.
(comp--pred-to-pos-cstr, comp--pred-to-neg-cstr): New functions.
(comp--add-cond-cstrs): Make use of them.
* test/src/comp-tests.el (comp-tests-type-spec-tests): Add a test.
| -rw-r--r-- | lisp/emacs-lisp/comp.el | 101 | ||||
| -rw-r--r-- | test/src/comp-tests.el | 9 |
2 files changed, 64 insertions, 46 deletions
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index 4ddf90349d1..9976a58f893 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el | |||
| @@ -193,49 +193,52 @@ Useful to hook into pass checkers.") | |||
| 193 | ;; cl-macs.el. We can't use `cl-deftype-satisfies' directly as the | 193 | ;; cl-macs.el. We can't use `cl-deftype-satisfies' directly as the |
| 194 | ;; relation type <-> predicate is not bijective (bug#45576). | 194 | ;; relation type <-> predicate is not bijective (bug#45576). |
| 195 | (defconst comp-known-predicates | 195 | (defconst comp-known-predicates |
| 196 | '((arrayp . array) | 196 | '((arrayp array) |
| 197 | (atom . atom) | 197 | (atom atom) |
| 198 | (bool-vector-p . bool-vector) | 198 | (bool-vector-p bool-vector) |
| 199 | (booleanp . boolean) | 199 | (booleanp boolean) |
| 200 | (bufferp . buffer) | 200 | (bufferp buffer) |
| 201 | (char-table-p . char-table) | 201 | (char-table-p char-table) |
| 202 | (characterp . fixnum) | 202 | (characterp fixnum) |
| 203 | (consp . cons) | 203 | (consp cons) |
| 204 | (floatp . float) | 204 | (floatp float) |
| 205 | (framep . frame) | 205 | (framep frame) |
| 206 | (functionp . (or function symbol cons)) | 206 | (functionp (or function symbol cons) (not function)) |
| 207 | (hash-table-p . hash-table) | 207 | (hash-table-p hash-table) |
| 208 | (integer-or-marker-p . integer-or-marker) | 208 | (integer-or-marker-p integer-or-marker) |
| 209 | (integerp . integer) | 209 | (integerp integer) |
| 210 | (keywordp . keyword) | 210 | (keywordp keyword) |
| 211 | (listp . list) | 211 | (listp list) |
| 212 | (markerp . marker) | 212 | (markerp marker) |
| 213 | (natnump . (integer 0 *)) | 213 | (natnump (integer 0 *)) |
| 214 | (null . null) | 214 | (null null) |
| 215 | (number-or-marker-p . number-or-marker) | 215 | (number-or-marker-p number-or-marker) |
| 216 | (numberp . number) | 216 | (numberp number) |
| 217 | (numberp . number) | 217 | (numberp number) |
| 218 | (obarrayp . obarray) | 218 | (obarrayp obarray) |
| 219 | (overlayp . overlay) | 219 | (overlayp overlay) |
| 220 | (processp . process) | 220 | (processp process) |
| 221 | (sequencep . sequence) | 221 | (sequencep sequence) |
| 222 | (stringp . string) | 222 | (stringp string) |
| 223 | (subrp . subr) | 223 | (subrp subr) |
| 224 | (symbol-with-pos-p . symbol-with-pos) | 224 | (symbol-with-pos-p symbol-with-pos) |
| 225 | (symbolp . symbol) | 225 | (symbolp symbol) |
| 226 | (vectorp . vector) | 226 | (vectorp vector) |
| 227 | (windowp . window)) | 227 | (windowp window)) |
| 228 | "Alist predicate -> matched type specifier.") | 228 | "(PREDICATE TYPE-IF-SATISFIED ?TYPE-IF-NOT-SATISFIED).") |
| 229 | 229 | ||
| 230 | (defconst comp-known-predicates-h | 230 | (defconst comp-known-predicates-h |
| 231 | (cl-loop | 231 | (cl-loop |
| 232 | with comp-ctxt = (make-comp-cstr-ctxt) | 232 | with comp-ctxt = (make-comp-cstr-ctxt) |
| 233 | with h = (make-hash-table :test #'eq) | 233 | with h = (make-hash-table :test #'eq) |
| 234 | for (pred . type-spec) in comp-known-predicates | 234 | for (pred . type-specs) in comp-known-predicates |
| 235 | for cstr = (comp-type-spec-to-cstr type-spec) | 235 | for pos-cstr = (comp-type-spec-to-cstr (car type-specs)) |
| 236 | do (puthash pred cstr h) | 236 | for neg-cstr = (if (length> type-specs 1) |
| 237 | (comp-type-spec-to-cstr (cl-second type-specs)) | ||
| 238 | (comp-cstr-negation-make pos-cstr)) | ||
| 239 | do (puthash pred (cons pos-cstr neg-cstr) h) | ||
| 237 | finally return h) | 240 | finally return h) |
| 238 | "Hash table function -> `comp-constraint'.") | 241 | "Hash table FUNCTION -> (POS-CSTR . NEG-CSTR).") |
| 239 | 242 | ||
| 240 | (defun comp--known-predicate-p (predicate) | 243 | (defun comp--known-predicate-p (predicate) |
| 241 | "Return t if PREDICATE is known." | 244 | "Return t if PREDICATE is known." |
| @@ -243,10 +246,14 @@ Useful to hook into pass checkers.") | |||
| 243 | (gethash predicate (comp-cstr-ctxt-pred-type-h comp-ctxt))) | 246 | (gethash predicate (comp-cstr-ctxt-pred-type-h comp-ctxt))) |
| 244 | t)) | 247 | t)) |
| 245 | 248 | ||
| 246 | (defun comp--pred-to-cstr (predicate) | 249 | (defun comp--pred-to-pos-cstr (predicate) |
| 247 | "Given PREDICATE, return the corresponding constraint." | 250 | "Given PREDICATE, return the corresponding positive constraint." |
| 248 | ;; FIXME: Unify those two hash tables? | 251 | (or (car-safe (gethash predicate comp-known-predicates-h)) |
| 249 | (or (gethash predicate comp-known-predicates-h) | 252 | (gethash predicate (comp-cstr-ctxt-pred-type-h comp-ctxt)))) |
| 253 | |||
| 254 | (defun comp--pred-to-neg-cstr (predicate) | ||
| 255 | "Given PREDICATE, return the corresponding negative constraint." | ||
| 256 | (or (cdr-safe (gethash predicate comp-known-predicates-h)) | ||
| 250 | (gethash predicate (comp-cstr-ctxt-pred-type-h comp-ctxt)))) | 257 | (gethash predicate (comp-cstr-ctxt-pred-type-h comp-ctxt)))) |
| 251 | 258 | ||
| 252 | (defconst comp-symbol-values-optimizable '(most-positive-fixnum | 259 | (defconst comp-symbol-values-optimizable '(most-positive-fixnum |
| @@ -2033,7 +2040,6 @@ TARGET-BB-SYM is the symbol name of the target block." | |||
| 2033 | (cond-jump ,cmp-res ,(pred comp-mvar-p) . ,blocks)) | 2040 | (cond-jump ,cmp-res ,(pred comp-mvar-p) . ,blocks)) |
| 2034 | (cl-loop | 2041 | (cl-loop |
| 2035 | with target-mvar = (comp--cond-cstrs-target-mvar op (car insns-seq) b) | 2042 | with target-mvar = (comp--cond-cstrs-target-mvar op (car insns-seq) b) |
| 2036 | with cstr = (comp--pred-to-cstr fun) | ||
| 2037 | for branch-target-cell on blocks | 2043 | for branch-target-cell on blocks |
| 2038 | for branch-target = (car branch-target-cell) | 2044 | for branch-target = (car branch-target-cell) |
| 2039 | for negated in '(t nil) | 2045 | for negated in '(t nil) |
| @@ -2041,7 +2047,10 @@ TARGET-BB-SYM is the symbol name of the target block." | |||
| 2041 | do | 2047 | do |
| 2042 | (let ((block-target (comp--add-cond-cstrs-target-block b branch-target))) | 2048 | (let ((block-target (comp--add-cond-cstrs-target-block b branch-target))) |
| 2043 | (setf (car branch-target-cell) (comp-block-name block-target)) | 2049 | (setf (car branch-target-cell) (comp-block-name block-target)) |
| 2044 | (comp--emit-assume 'and target-mvar cstr block-target negated)) | 2050 | (comp--emit-assume 'and target-mvar (if negated |
| 2051 | (comp--pred-to-neg-cstr fun) | ||
| 2052 | (comp--pred-to-pos-cstr fun)) | ||
| 2053 | block-target nil)) | ||
| 2045 | finally (cl-return-from in-the-basic-block))) | 2054 | finally (cl-return-from in-the-basic-block))) |
| 2046 | ;; Match predicate on the negated branch (unless). | 2055 | ;; Match predicate on the negated branch (unless). |
| 2047 | (`((set ,(and (pred comp-mvar-p) cmp-res) | 2056 | (`((set ,(and (pred comp-mvar-p) cmp-res) |
| @@ -2052,7 +2061,6 @@ TARGET-BB-SYM is the symbol name of the target block." | |||
| 2052 | (cond-jump ,neg-cmp-res ,(pred comp-mvar-p) . ,blocks)) | 2061 | (cond-jump ,neg-cmp-res ,(pred comp-mvar-p) . ,blocks)) |
| 2053 | (cl-loop | 2062 | (cl-loop |
| 2054 | with target-mvar = (comp--cond-cstrs-target-mvar op (car insns-seq) b) | 2063 | with target-mvar = (comp--cond-cstrs-target-mvar op (car insns-seq) b) |
| 2055 | with cstr = (comp--pred-to-cstr fun) | ||
| 2056 | for branch-target-cell on blocks | 2064 | for branch-target-cell on blocks |
| 2057 | for branch-target = (car branch-target-cell) | 2065 | for branch-target = (car branch-target-cell) |
| 2058 | for negated in '(nil t) | 2066 | for negated in '(nil t) |
| @@ -2060,7 +2068,10 @@ TARGET-BB-SYM is the symbol name of the target block." | |||
| 2060 | do | 2068 | do |
| 2061 | (let ((block-target (comp--add-cond-cstrs-target-block b branch-target))) | 2069 | (let ((block-target (comp--add-cond-cstrs-target-block b branch-target))) |
| 2062 | (setf (car branch-target-cell) (comp-block-name block-target)) | 2070 | (setf (car branch-target-cell) (comp-block-name block-target)) |
| 2063 | (comp--emit-assume 'and target-mvar cstr block-target negated)) | 2071 | (comp--emit-assume 'and target-mvar (if negated |
| 2072 | (comp--pred-to-neg-cstr fun) | ||
| 2073 | (comp--pred-to-pos-cstr fun)) | ||
| 2074 | block-target nil)) | ||
| 2064 | finally (cl-return-from in-the-basic-block)))) | 2075 | finally (cl-return-from in-the-basic-block)))) |
| 2065 | (setf prev-insns-seq insns-seq)))) | 2076 | (setf prev-insns-seq insns-seq)))) |
| 2066 | 2077 | ||
diff --git a/test/src/comp-tests.el b/test/src/comp-tests.el index fbcb6ca9560..b2fd2f68826 100644 --- a/test/src/comp-tests.el +++ b/test/src/comp-tests.el | |||
| @@ -1496,7 +1496,14 @@ Return a list of results." | |||
| 1496 | (if (comp-foo-p x) | 1496 | (if (comp-foo-p x) |
| 1497 | x | 1497 | x |
| 1498 | (error ""))) | 1498 | (error ""))) |
| 1499 | 'comp-foo))) | 1499 | 'comp-foo) |
| 1500 | |||
| 1501 | ;; 80 | ||
| 1502 | ((defun comp-tests-ret-type-spec-f (x) | ||
| 1503 | (if (functionp x) | ||
| 1504 | (error "") | ||
| 1505 | x)) | ||
| 1506 | '(not function)))) | ||
| 1500 | 1507 | ||
| 1501 | (defun comp-tests-define-type-spec-test (number x) | 1508 | (defun comp-tests-define-type-spec-test (number x) |
| 1502 | `(comp-deftest ,(intern (format "ret-type-spec-%d" number)) () | 1509 | `(comp-deftest ,(intern (format "ret-type-spec-%d" number)) () |