summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2021-01-26 19:01:25 -0800
committerKaz Kylheku <kaz@kylheku.com>2021-01-26 19:01:25 -0800
commitd3dccedf7d7ad9f7108bdc08df9901d607e5f25a (patch)
treead426da8c84857e0d66ee31373fb5e21768b50a1
parentdeae97f0dfdf0ea33bba2912f05bb6b350553b94 (diff)
downloadtxr-d3dccedf7d7ad9f7108bdc08df9901d607e5f25a.tar.gz
txr-d3dccedf7d7ad9f7108bdc08df9901d607e5f25a.tar.bz2
txr-d3dccedf7d7ad9f7108bdc08df9901d607e5f25a.zip
compiler: jump-threading optimization.
* share/txr/stdlib/compiler.tl: Load the new optimize module. (compiler optimize): New method. (compile-toplevel): Pass code through optimize method. * share/txr/stdlib/optimize.tl: New file.
-rw-r--r--share/txr/stdlib/compiler.tl10
-rw-r--r--share/txr/stdlib/optimize.tl88
2 files changed, 97 insertions, 1 deletions
diff --git a/share/txr/stdlib/compiler.tl b/share/txr/stdlib/compiler.tl
index ff769a0f..6d5dce38 100644
--- a/share/txr/stdlib/compiler.tl
+++ b/share/txr/stdlib/compiler.tl
@@ -25,6 +25,7 @@
;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
(load "vm-param")
+(load "optimize")
(compile-only
(load-for (struct sys:param-parser-base "param")))
@@ -1270,6 +1271,11 @@
(push lt-frag me.lt-frags)
(new (frag dreg nil))))))))
+(defmeth compiler optimize (me insns)
+ (let* ((bb (new (basic-blocks insns))))
+ bb.(thread-jumps)
+ bb.(get-insns)))
+
(defun maybe-mov (to-reg from-reg)
(if (nequal to-reg from-reg)
^((mov ,to-reg ,from-reg))))
@@ -1669,7 +1675,9 @@
(frag co.(compile oreg (new env co co) xexp)))
co.(free-treg oreg)
co.(check-treg-leak)
- as.(asm ^(,*(mappend .code (nreverse co.lt-frags)) ,*frag.code (end ,frag.oreg)))
+ as.(asm co.(optimize ^(,*(mappend .code (nreverse co.lt-frags))
+ ,*frag.code
+ (end ,frag.oreg))))
(vm-make-desc co.nlev (succ as.max-treg) as.buf co.(get-datavec) co.(get-symvec)))))
(defun compiler-emit-warnings ()
diff --git a/share/txr/stdlib/optimize.tl b/share/txr/stdlib/optimize.tl
new file mode 100644
index 00000000..5cd05095
--- /dev/null
+++ b/share/txr/stdlib/optimize.tl
@@ -0,0 +1,88 @@
+;; Copyright 2021
+;; Kaz Kylheku <kaz@kylheku.com>
+;; Vancouver, Canada
+;; All rights reserved.
+;;
+;; Redistribution and use in source and binary forms, with or without
+;; modification, are permitted provided that the following conditions are met:
+;;
+;; 1. Redistributions of source code must retain the above copyright notice, this
+;; list of conditions and the following disclaimer.
+;;
+;; 2. Redistributions in binary form must reproduce the above copyright notice,
+;; this list of conditions and the following disclaimer in the documentation
+;; and/or other materials provided with the distribution.
+;;
+;; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+;; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+;; DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+;; FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+;; DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+;; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+;; CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+;; OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+;; OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+(compile-only
+ (defstruct (basic-blocks insns) nil
+ insns
+ (hash (hash))
+ labels
+ list
+ (:static start (gensym "start-"))
+
+ (:postinit (bb)
+ (set bb.list (partition (dedup-labels (cons bb.start bb.insns))
+ (op where symbolp)))
+ (set bb.labels [mapcar car bb.list])
+ (mapdo (do set [bb.hash (car @1)] @1) bb.list))
+
+ (:method get-insns (bb)
+ [mappend bb.hash bb.labels])))
+
+(defmeth basic-blocks thread-jumps (bb)
+ (dohash (label code bb.hash)
+ (set [bb.hash label]
+ (rewrite (lambda (insns)
+ (match-case insns
+ (((jmp @jlabel) . @rest)
+ (let ((jinsns [bb.hash jlabel]))
+ (match-case jinsns
+ ((@(op eq jlabel) (jmp @(require @jjlabel (neq jjlabel jlabel))) . @nil)
+ ^((jmp ,jjlabel) ,*rest))
+ (@jelse insns))))
+ (((if @reg @jlabel) . @rest)
+ (let ((jinsns [bb.hash jlabel]))
+ (match-case jinsns
+ ((@(op eq jlabel) (if @(op eq reg) @(require @jjlabel (neq jjlabel jlabel))) . @nil)
+ ^((if ,reg ,jjlabel) ,*rest))
+ ((@(op eq jlabel) (jmp @(require @jjlabel (neq jjlabel jlabel))) . @nil)
+ ^((if ,reg ,jjlabel) ,*rest))
+ (@jelse insns))))
+ (@else insns)))
+ code))))
+
+(defun rewrite (fun list)
+ (build
+ (while* list
+ (let ((nlist [fun list]))
+ (if (eq list nlist)
+ (if list (add (pop list)))
+ (set list nlist))))))
+
+(defun subst (x y list)
+ (mapcar (lambda (item)
+ (if (equal item x) y item))
+ list))
+
+(defun dedup-labels (insns)
+ (rewrite (lambda (tail)
+ (match-case tail
+ ((@(symbolp label0) @(symbolp label1) . @rest)
+ (set insns (mapcar [iffi listp (op subst label1 label0)]
+ (remq label1 insns)))
+ (list* label0 rest))
+ (@else tail)))
+ insns)
+ insns)