diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2021-03-03 08:37:48 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2021-03-03 08:37:48 -0800 |
commit | d6b6dfcf6b8adcb6c2fbc453c2c0fcbf3a27cbc3 (patch) | |
tree | 0338c87ec7a942b553741bcd196ae618b5411b54 | |
parent | 87ad7742d1fb7dd757f37dbf922eb30872e1b8ed (diff) | |
download | txr-d6b6dfcf6b8adcb6c2fbc453c2c0fcbf3a27cbc3.tar.gz txr-d6b6dfcf6b8adcb6c2fbc453c2c0fcbf3a27cbc3.tar.bz2 txr-d6b6dfcf6b8adcb6c2fbc453c2c0fcbf3a27cbc3.zip |
compiler: new late-peephole pass.
I noticed a lot of this in compiled code:
(if reg label1)
label2
(jmp label3)
label1
by inverting the test, this can be shortened to
(ifq reg (t 0) label2)
label1
We must keep label1 in case it is the target of other
branches. Also, we only perform this if label2 is unreachable:
the (jmp label3) instruction is reached only when the previous
if branch is not taken.
* share/txr/stdlib/optimize.tl (basic-blocks get-insns): Call
new late-peephole method.
(basic-blocks late-peephole): New method, incorporating the
above pattern.
-rw-r--r-- | share/txr/stdlib/optimize.tl | 17 |
1 files changed, 16 insertions, 1 deletions
diff --git a/share/txr/stdlib/optimize.tl b/share/txr/stdlib/optimize.tl index b4722f56..1541cd17 100644 --- a/share/txr/stdlib/optimize.tl +++ b/share/txr/stdlib/optimize.tl @@ -77,7 +77,7 @@ bb.(link-graph)) (:method get-insns (bb) - [mappend .insns bb.list]) + bb.(late-peephole [mappend .insns bb.list])) (:method cut-block (bb bl at insns) (let* ((nlabel (gensym "nl")) @@ -491,6 +491,21 @@ (set pbl.insns (append (ldiff code tail) (list sins)))))) (set bb.list (remove-if (lop memq dupes) bb.list)))))))) +(defmeth basic-blocks late-peephole (bb code) + (rewrite-case insns code + (((if @reg @lab1) + @lab2 + (jmp @lab3) + @lab1 + . @rest) + (let* ((bl [bb.hash lab2])) + (if (some bl.rlinks (op eq bb) .next) + insns + ^((ifq ,reg (t 0) ,lab3) + ,lab1 + ,*rest)))) + (@else else))) + (defun rewrite (fun list) (build (while* list |