diff options
| author | Andrea Corallo | 2020-10-27 19:40:55 +0000 |
|---|---|---|
| committer | Andrea Corallo | 2020-11-01 15:17:00 +0100 |
| commit | 42970cceb9b15212f1a2a28a4595efc8c960f929 (patch) | |
| tree | d56d387d21dc96e1a65e173c1f667161832ceca9 | |
| parent | 047fe3292d2f102c9aed4dc305de165b627bcddd (diff) | |
| download | emacs-42970cceb9b15212f1a2a28a4595efc8c960f929.tar.gz emacs-42970cceb9b15212f1a2a28a4595efc8c960f929.zip | |
Add new cond-rw pass to have forward propagation track cond branches
Add a new pass to rewrite conditional branches. This is introducing
and placing a new LIMPLE operator 'assume' in use by fwprop to
propagate conditional branch test informations on target basic blocks.
* lisp/emacs-lisp/comp.el (comp-passes): Add `comp-cond-rw'.
(comp-limple-assignments): Add `assume' operator.
(comp-emit-assume, comp-cond-rw-target-slot, comp-cond-rw-func)
(comp-cond-rw): Add new functions.
(comp-fwprop-insn): Update to pattern match `assume' insns.
* src/comp.c (emit_limple_insn): Add for `assume'.
(syms_of_comp): Define 'Qassume' symbol.
| -rw-r--r-- | lisp/emacs-lisp/comp.el | 83 | ||||
| -rw-r--r-- | src/comp.c | 5 |
2 files changed, 85 insertions, 3 deletions
diff --git a/lisp/emacs-lisp/comp.el b/lisp/emacs-lisp/comp.el index 15b8b3ab8da..9b26f6c4198 100644 --- a/lisp/emacs-lisp/comp.el +++ b/lisp/emacs-lisp/comp.el | |||
| @@ -171,6 +171,7 @@ Can be one of: 'd-default', 'd-impure' or 'd-ephemeral'. See `comp-ctxt'.") | |||
| 171 | comp-fwprop | 171 | comp-fwprop |
| 172 | comp-call-optim | 172 | comp-call-optim |
| 173 | comp-ipa-pure | 173 | comp-ipa-pure |
| 174 | comp-cond-rw | ||
| 174 | comp-fwprop | 175 | comp-fwprop |
| 175 | comp-dead-code | 176 | comp-dead-code |
| 176 | comp-tco | 177 | comp-tco |
| @@ -216,7 +217,8 @@ Useful to hook into pass checkers.") | |||
| 216 | set-rest-args-to-local) | 217 | set-rest-args-to-local) |
| 217 | "Limple set operators.") | 218 | "Limple set operators.") |
| 218 | 219 | ||
| 219 | (defconst comp-limple-assignments `(fetch-handler | 220 | (defconst comp-limple-assignments `(assume |
| 221 | fetch-handler | ||
| 220 | ,@comp-limple-sets) | 222 | ,@comp-limple-sets) |
| 221 | "Limple operators that clobbers the first m-var argument.") | 223 | "Limple operators that clobbers the first m-var argument.") |
| 222 | 224 | ||
| @@ -1677,6 +1679,73 @@ into the C code forwarding the compilation unit." | |||
| 1677 | (comp-add-func-to-ctxt (comp-limplify-top-level t)))) | 1679 | (comp-add-func-to-ctxt (comp-limplify-top-level t)))) |
| 1678 | 1680 | ||
| 1679 | 1681 | ||
| 1682 | ;;; conditional branches rewrite pass specific code. | ||
| 1683 | |||
| 1684 | (defun comp-emit-assume (target-slot rhs bb-name kind) | ||
| 1685 | "Emit an assume of kind KIND for TARGET-SLOT being RHS. | ||
| 1686 | The assume is emitted at the beginning of the block named | ||
| 1687 | BB-NAME." | ||
| 1688 | (push `(assume ,(make-comp-mvar :slot target-slot) ,rhs ,kind) | ||
| 1689 | (comp-block-insns (gethash bb-name (comp-func-blocks comp-func)))) | ||
| 1690 | (setf (comp-func-ssa-status comp-func) 'dirty)) | ||
| 1691 | |||
| 1692 | (defun comp-cond-rw-target-slot (slot-num exit-insn bb) | ||
| 1693 | "Search for the last assignment of SLOT-NUM in BB. | ||
| 1694 | Keep on searching till EXIT-INSN is encountered. | ||
| 1695 | Return the corresponding rhs slot number." | ||
| 1696 | (cl-flet ((targetp (x) | ||
| 1697 | ;; Ret t if x is an mvar and target the correct slot number. | ||
| 1698 | (and (comp-mvar-p x) | ||
| 1699 | (eql slot-num (comp-mvar-slot x))))) | ||
| 1700 | (cl-loop | ||
| 1701 | with res = nil | ||
| 1702 | for insn in (comp-block-insns bb) | ||
| 1703 | when (eq insn exit-insn) | ||
| 1704 | do (cl-return (and (comp-mvar-p res) (comp-mvar-slot res))) | ||
| 1705 | do (pcase insn | ||
| 1706 | (`(,(pred comp-assign-op-p) ,(pred targetp) ,rhs) | ||
| 1707 | (setf res rhs))) | ||
| 1708 | finally (cl-assert nil)))) | ||
| 1709 | |||
| 1710 | (defun comp-cond-rw-func () | ||
| 1711 | "`comp-cond-rw' worker function for each selected function." | ||
| 1712 | (cl-loop | ||
| 1713 | for b being each hash-value of (comp-func-blocks comp-func) | ||
| 1714 | do (cl-loop | ||
| 1715 | named in-the-basic-block | ||
| 1716 | for insns-seq on (comp-block-insns b) | ||
| 1717 | do (pcase insns-seq | ||
| 1718 | (`((set ,(and (pred comp-mvar-p) cond) | ||
| 1719 | (,(pred comp-call-op-p) | ||
| 1720 | ,(and (or 'eq 'eql '= 'equal) test-fn) ,op1 ,op2)) | ||
| 1721 | (comment ,_comment-str) | ||
| 1722 | (cond-jump ,cond ,(pred comp-mvar-p) ,bb-1 ,_bb-2)) | ||
| 1723 | (when-let ((target-slot1 (comp-cond-rw-target-slot | ||
| 1724 | (comp-mvar-slot op1) (car insns-seq) b))) | ||
| 1725 | (comp-emit-assume target-slot1 op2 bb-1 test-fn)) | ||
| 1726 | (when-let ((target-slot2 (comp-cond-rw-target-slot | ||
| 1727 | (comp-mvar-slot op2) (car insns-seq) b))) | ||
| 1728 | (comp-emit-assume target-slot2 op1 bb-1 test-fn)) | ||
| 1729 | (cl-return-from in-the-basic-block)))))) | ||
| 1730 | |||
| 1731 | (defun comp-cond-rw (_) | ||
| 1732 | "Rewrite conditional branches adding appropriate 'assume' insns. | ||
| 1733 | This is introducing and placing 'assume' insns in use by fwprop | ||
| 1734 | to propagate conditional branch test informations on target basic | ||
| 1735 | blocks." | ||
| 1736 | (maphash (lambda (_ f) | ||
| 1737 | (when (and (>= (comp-func-speed f) 1) | ||
| 1738 | ;; No point to run this on dynamic scope as | ||
| 1739 | ;; this pass is effecive only on local | ||
| 1740 | ;; variables. | ||
| 1741 | (comp-func-l-p f) | ||
| 1742 | (not (comp-func-has-non-local f))) | ||
| 1743 | (let ((comp-func f)) | ||
| 1744 | (comp-cond-rw-func) | ||
| 1745 | (comp-log-func comp-func 3)))) | ||
| 1746 | (comp-ctxt-funcs-h comp-ctxt))) | ||
| 1747 | |||
| 1748 | |||
| 1680 | ;;; pure-func pass specific code. | 1749 | ;;; pure-func pass specific code. |
| 1681 | 1750 | ||
| 1682 | ;; Simple IPA pass to infer function purity of functions not | 1751 | ;; Simple IPA pass to infer function purity of functions not |
| @@ -2158,6 +2227,18 @@ Forward propagate immediate involed in assignments." | |||
| 2158 | (comp-function-call-maybe-remove insn f args))) | 2227 | (comp-function-call-maybe-remove insn f args))) |
| 2159 | (_ | 2228 | (_ |
| 2160 | (comp-mvar-propagate lval rval)))) | 2229 | (comp-mvar-propagate lval rval)))) |
| 2230 | (`(assume ,lval ,rval ,kind) | ||
| 2231 | (pcase kind | ||
| 2232 | ('eq | ||
| 2233 | (comp-mvar-propagate lval rval)) | ||
| 2234 | ((or 'eql 'equal) | ||
| 2235 | (if (memq (comp-mvar-type rval) '(symbol fixnum)) | ||
| 2236 | (comp-mvar-propagate lval rval) | ||
| 2237 | (setf (comp-mvar-type lval) (comp-mvar-type rval)))) | ||
| 2238 | ('= | ||
| 2239 | (if (eq (comp-mvar-type rval) 'fixnum) | ||
| 2240 | (comp-mvar-propagate lval rval) | ||
| 2241 | (setf (comp-mvar-type lval) 'number))))) | ||
| 2161 | (`(setimm ,lval ,v) | 2242 | (`(setimm ,lval ,v) |
| 2162 | (setf (comp-mvar-const-vld lval) t | 2243 | (setf (comp-mvar-const-vld lval) t |
| 2163 | (comp-mvar-constant lval) v | 2244 | (comp-mvar-constant lval) v |
diff --git a/src/comp.c b/src/comp.c index 0c555578f81..48e4f1c8cde 100644 --- a/src/comp.c +++ b/src/comp.c | |||
| @@ -2131,9 +2131,9 @@ emit_limple_insn (Lisp_Object insn) | |||
| 2131 | n); | 2131 | n); |
| 2132 | emit_cond_jump (test, target2, target1); | 2132 | emit_cond_jump (test, target2, target1); |
| 2133 | } | 2133 | } |
| 2134 | else if (EQ (op, Qphi)) | 2134 | else if (EQ (op, Qphi) || EQ (op, Qassume)) |
| 2135 | { | 2135 | { |
| 2136 | /* Nothing to do for phis into the backend. */ | 2136 | /* Nothing to do for phis or assumes in the backend. */ |
| 2137 | } | 2137 | } |
| 2138 | else if (EQ (op, Qpush_handler)) | 2138 | else if (EQ (op, Qpush_handler)) |
| 2139 | { | 2139 | { |
| @@ -5134,6 +5134,7 @@ native compiled one. */); | |||
| 5134 | DEFSYM (Qcallref, "callref"); | 5134 | DEFSYM (Qcallref, "callref"); |
| 5135 | DEFSYM (Qdirect_call, "direct-call"); | 5135 | DEFSYM (Qdirect_call, "direct-call"); |
| 5136 | DEFSYM (Qdirect_callref, "direct-callref"); | 5136 | DEFSYM (Qdirect_callref, "direct-callref"); |
| 5137 | DEFSYM (Qassume, "assume"); | ||
| 5137 | DEFSYM (Qsetimm, "setimm"); | 5138 | DEFSYM (Qsetimm, "setimm"); |
| 5138 | DEFSYM (Qreturn, "return"); | 5139 | DEFSYM (Qreturn, "return"); |
| 5139 | DEFSYM (Qcomp_mvar, "comp-mvar"); | 5140 | DEFSYM (Qcomp_mvar, "comp-mvar"); |