aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrea Corallo2024-03-26 11:14:08 +0100
committerAndrea Corallo2024-03-26 11:14:08 +0100
commit8cc67dbcec0753c5579e63bf82bfe247debe222c (patch)
tree1e35b49a8a150785138ccf4889888bc40252a0a0
parentb7b9a0a5c1afae07b8168e85dcf1fc37d29e98ef (diff)
downloademacs-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.el101
-rw-r--r--test/src/comp-tests.el9
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)) ()