summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-03-03 08:37:48 -0800
committerKaz Kylheku <kaz@kylheku.com>2021-03-03 08:37:48 -0800
commitd6b6dfcf6b8adcb6c2fbc453c2c0fcbf3a27cbc3 (patch)
tree0338c87ec7a942b553741bcd196ae618b5411b54
parent87ad7742d1fb7dd757f37dbf922eb30872e1b8ed (diff)
downloadtxr-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.tl17
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