1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-10 00:00:39 -08:00

add dead code removal pass

This commit is contained in:
Andrea Corallo 2019-09-22 18:49:11 +02:00
parent e3ed0208a8
commit d9670ef135
2 changed files with 96 additions and 10 deletions

View file

@ -58,6 +58,7 @@
comp-propagate comp-propagate
comp-call-optim comp-call-optim
comp-propagate comp-propagate
comp-dead-code
comp-final) comp-final)
"Passes to be executed in order.") "Passes to be executed in order.")
@ -72,14 +73,23 @@
(% . number)) (% . number))
"Alist used for type propagation.") "Alist used for type propagation.")
(defconst comp-limple-assignments '(set (defconst comp-limple-sets '(set
setimm setimm
set-par-to-local set-par-to-local
set-args-to-local set-args-to-local
set-rest-args-to-local set-rest-args-to-local)
push-handler) "Limple set operators.")
(defconst comp-limple-assignments `(push-handler
,@comp-limple-sets)
"Limple operators that clobbers the first mvar argument.") "Limple operators that clobbers the first mvar argument.")
(defconst comp-limple-calls '(call
callref
direct-call
direct-callref)
"Limple operators use to call subrs.")
(defconst comp-mostly-pure-funcs (defconst comp-mostly-pure-funcs
'(% * + - / /= 1+ 1- < <= = > >= cons list % concat logand logcount logior '(% * + - / /= 1+ 1- < <= = > >= cons list % concat logand logcount logior
lognot logxor regexp-opt regexp-quote string-to-char string-to-syntax lognot logxor regexp-opt regexp-quote string-to-char string-to-syntax
@ -234,10 +244,19 @@ structure.")
(defun comp-set-op-p (op)
"Assignment predicate for OP."
(cl-find op comp-limple-sets))
(defun comp-assign-op-p (op) (defun comp-assign-op-p (op)
"Assignment predicate for OP." "Assignment predicate for OP."
(cl-find op comp-limple-assignments)) (cl-find op comp-limple-assignments))
(defun comp-limple-insn-call-p (insn)
"Limple INSN call predicate."
(when (member (car-safe insn) comp-limple-calls)
t))
(defun comp-add-const-to-relocs (obj) (defun comp-add-const-to-relocs (obj)
"Keep track of OBJ into the ctxt relocations. "Keep track of OBJ into the ctxt relocations.
The corresponding index is returned." The corresponding index is returned."
@ -1384,12 +1403,75 @@ This can run just once."
(comp-call-optim-func))) (comp-call-optim-func)))
(comp-ctxt-funcs-h comp-ctxt)))) (comp-ctxt-funcs-h comp-ctxt))))
;;; Dead code elimination pass specific code.
;; This simple pass try to eliminate insns became useful after propagation.
;; Even if gcc would take care of this is good to perform this here
;; in the hope of removing memory references (remember that most lisp
;; objects are loaded from the reloc array).
;; This pass can be run as last optim.
(defun comp-collect-mvar-ids (insn)
"Collect the mvar unique identifiers into INSN."
(cl-loop for x in insn
if (consp x)
append (comp-collect-mvar-ids x)
else
when (comp-mvar-p x)
collect (comp-mvar-id x)))
(defun comp-dead-code-func ()
"Clean-up dead code into current function."
(let ((l-vals ())
(r-vals ()))
;; Collect used r and l values.
(cl-loop
for b being each hash-value of (comp-func-blocks comp-func)
do (cl-loop
for insn in (comp-block-insns b)
for (op arg0 . rest) = insn
if (comp-set-op-p op)
do (push (comp-mvar-id arg0) l-vals)
and
do (setf r-vals (nconc (comp-collect-mvar-ids rest) r-vals))
else
do (setf r-vals (nconc (comp-collect-mvar-ids insn) r-vals))))
;; Every l-value appearing that does not appear as r-value has no right to
;; exist and gets nuked.
(let ((nuke-list (cl-set-difference l-vals r-vals)))
(comp-log (format "Function %s\n" (comp-func-symbol-name comp-func)))
(comp-log (format "l-vals %s\n" l-vals))
(comp-log (format "r-vals %s\n" r-vals))
(comp-log (format "Nuking ids: %s\n" nuke-list))
(cl-loop
for b being each hash-value of (comp-func-blocks comp-func)
do (cl-loop
for insn-cell on (comp-block-insns b)
for insn = (car insn-cell)
for (op arg0 rest) = insn
when (and (comp-set-op-p op)
(member (comp-mvar-id arg0) nuke-list))
do (setcar insn-cell
(if (comp-limple-insn-call-p rest)
rest
`(comment ,(format "optimized out %s"
insn)))))))))
(defun comp-dead-code (_)
"Dead code elimination."
(when (>= comp-speed 2)
(maphash (lambda (_ f)
(let ((comp-func f))
(comp-dead-code-func)
(comp-log-func comp-func)))
(comp-ctxt-funcs-h comp-ctxt))))
;;; Final pass specific code. ;;; Final pass specific code.
(defun comp-compile-ctxt-to-file (name) (defun comp-compile-ctxt-to-file (name)
"Compile as native code the current context naming it NAME. "Compile as native code the current context naming it NAME.
Prepare every functions for final compilation and drive the C side." Prepare every function for final compilation and drive the C back-end."
(cl-assert (= (length (comp-ctxt-data-relocs-l comp-ctxt)) (cl-assert (= (length (comp-ctxt-data-relocs-l comp-ctxt))
(hash-table-count (comp-ctxt-data-relocs-idx comp-ctxt)))) (hash-table-count (comp-ctxt-data-relocs-idx comp-ctxt))))
(setf (comp-ctxt-exp-funcs comp-ctxt) (setf (comp-ctxt-exp-funcs comp-ctxt)

View file

@ -1295,10 +1295,14 @@ emit_limple_insn (Lisp_Object insn)
} }
else if (EQ (op, Qcall)) else if (EQ (op, Qcall))
{ {
gcc_jit_block_add_eval (comp.block, gcc_jit_block_add_eval (comp.block, NULL,
NULL,
emit_limple_call (args)); emit_limple_call (args));
} }
else if (EQ (op, Qcallref))
{
gcc_jit_block_add_eval (comp.block, NULL,
emit_limple_call_ref (args, false));
}
else if (EQ (op, Qset)) else if (EQ (op, Qset))
{ {
Lisp_Object arg1 = SECOND (args); Lisp_Object arg1 = SECOND (args);
@ -2721,7 +2725,7 @@ compile_function (Lisp_Object func)
- Enable gcc for better reordering (frame array is clobbered every time is - Enable gcc for better reordering (frame array is clobbered every time is
passed as parameter being invoved into an nargs function call). passed as parameter being invoved into an nargs function call).
- Allow gcc to trigger other optimizations that are prevented by memory - Allow gcc to trigger other optimizations that are prevented by memory
referencing (ex TCO). referencing.
*/ */
if (comp_speed >= 2) if (comp_speed >= 2)
{ {