1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-09 21:40:33 +02:00

Better codegen for $values terms that don't shuffle

* module/language/cps/compile-bytecode.scm (compute-forwarding-labels):
  Analyze forwarding labels before emitting code.  This lets us elide
  conts that cause no shuffles, allowing more fallthrough.
This commit is contained in:
Andy Wingo 2015-07-27 14:53:59 +02:00
parent 3b60e79879
commit 90c11483e6

View file

@ -55,9 +55,42 @@
set set
empty-intmap))) empty-intmap)))
;; Any $values expression that continues to a $kargs and causes no
;; shuffles is a forwarding label.
(define (compute-forwarding-labels cps allocation)
(fixpoint
(lambda (forwarding-map)
(intmap-fold (lambda (label target forwarding-map)
(let ((new-target (intmap-ref forwarding-map target
(lambda (target) target))))
(if (eqv? target new-target)
forwarding-map
(intmap-replace forwarding-map label new-target))))
forwarding-map forwarding-map))
(intmap-fold (lambda (label cont forwarding-labels)
(match cont
(($ $kargs _ _ ($ $continue k _ ($ $values)))
(match (lookup-parallel-moves label allocation)
(()
(match (intmap-ref cps k)
(($ $ktail) forwarding-labels)
(_ (intmap-add forwarding-labels label k))))
(_ forwarding-labels)))
(_ forwarding-labels)))
cps empty-intmap)))
(define (compile-function cps asm) (define (compile-function cps asm)
(let ((allocation (allocate-slots cps)) (let* ((allocation (allocate-slots cps))
(frame-size #f)) (forwarding-labels (compute-forwarding-labels cps allocation))
(frame-size #f))
(define (forward-label k)
(intmap-ref forwarding-labels k (lambda (k) k)))
(define (elide-cont? label)
(match (intmap-ref forwarding-labels label (lambda (_) #f))
(#f #f)
(target (not (eqv? label target)))))
(define (maybe-slot sym) (define (maybe-slot sym)
(lookup-maybe-slot sym allocation)) (lookup-maybe-slot sym allocation))
@ -242,18 +275,6 @@
(($ $primcall 'unwind ()) (($ $primcall 'unwind ())
(emit-unwind asm)))) (emit-unwind asm))))
(define (forward-label label seen)
(if (memv label seen)
label
(match (intmap-ref cps label)
(($ $kargs _ _ ($ $continue k _ ($ $values)))
(match (lookup-parallel-moves label allocation)
(() (match (intmap-ref cps k)
(($ $ktail) label)
(_ (forward-label k (cons label seen)))))
(_ label)))
(cont label))))
(define (compile-values label exp syms) (define (compile-values label exp syms)
(match exp (match exp
(($ $values args) (($ $values args)
@ -262,62 +283,60 @@
(lookup-parallel-moves label allocation))))) (lookup-parallel-moves label allocation)))))
(define (compile-test label exp kt kf next-label) (define (compile-test label exp kt kf next-label)
(let* ((kt (forward-label kt '())) (define (prefer-true?)
(kf (forward-label kf '()))) (if (< (max kt kf) label)
(define (prefer-true?) ;; Two backwards branches. Prefer
(if (< (max kt kf) label) ;; the nearest.
;; Two backwards branches. Prefer (> kt kf)
;; the nearest. ;; Otherwise prefer a backwards
(> kt kf) ;; branch or a near jump.
;; Otherwise prefer a backwards (< kt kf)))
;; branch or a near jump. (define (unary op sym)
(< kt kf))) (cond
(define (unary op sym) ((eq? kt next-label)
(cond (op asm (slot sym) #t kf))
((eq? kt next-label) ((eq? kf next-label)
(op asm (slot sym) #t kf)) (op asm (slot sym) #f kt))
((eq? kf next-label) (else
(op asm (slot sym) #f kt)) (let ((invert? (not (prefer-true?))))
(else (op asm (slot sym) invert? (if invert? kf kt))
(let ((invert? (not (prefer-true?)))) (emit-br asm (if invert? kt kf))))))
(op asm (slot sym) invert? (if invert? kf kt)) (define (binary op a b)
(emit-br asm (if invert? kt kf)))))) (cond
(define (binary op a b) ((eq? kt next-label)
(cond (op asm (slot a) (slot b) #t kf))
((eq? kt next-label) ((eq? kf next-label)
(op asm (slot a) (slot b) #t kf)) (op asm (slot a) (slot b) #f kt))
((eq? kf next-label) (else
(op asm (slot a) (slot b) #f kt)) (let ((invert? (not (prefer-true?))))
(else (op asm (slot a) (slot b) invert? (if invert? kf kt))
(let ((invert? (not (prefer-true?)))) (emit-br asm (if invert? kt kf))))))
(op asm (slot a) (slot b) invert? (if invert? kf kt)) (match exp
(emit-br asm (if invert? kt kf)))))) (($ $values (sym)) (unary emit-br-if-true sym))
(match exp (($ $primcall 'null? (a)) (unary emit-br-if-null a))
(($ $values (sym)) (unary emit-br-if-true sym)) (($ $primcall 'nil? (a)) (unary emit-br-if-nil a))
(($ $primcall 'null? (a)) (unary emit-br-if-null a)) (($ $primcall 'pair? (a)) (unary emit-br-if-pair a))
(($ $primcall 'nil? (a)) (unary emit-br-if-nil a)) (($ $primcall 'struct? (a)) (unary emit-br-if-struct a))
(($ $primcall 'pair? (a)) (unary emit-br-if-pair a)) (($ $primcall 'char? (a)) (unary emit-br-if-char a))
(($ $primcall 'struct? (a)) (unary emit-br-if-struct a)) (($ $primcall 'symbol? (a)) (unary emit-br-if-symbol a))
(($ $primcall 'char? (a)) (unary emit-br-if-char a)) (($ $primcall 'variable? (a)) (unary emit-br-if-variable a))
(($ $primcall 'symbol? (a)) (unary emit-br-if-symbol a)) (($ $primcall 'vector? (a)) (unary emit-br-if-vector a))
(($ $primcall 'variable? (a)) (unary emit-br-if-variable a)) (($ $primcall 'string? (a)) (unary emit-br-if-string a))
(($ $primcall 'vector? (a)) (unary emit-br-if-vector a)) (($ $primcall 'bytevector? (a)) (unary emit-br-if-bytevector a))
(($ $primcall 'string? (a)) (unary emit-br-if-string a)) (($ $primcall 'bitvector? (a)) (unary emit-br-if-bitvector a))
(($ $primcall 'bytevector? (a)) (unary emit-br-if-bytevector a)) (($ $primcall 'keyword? (a)) (unary emit-br-if-keyword a))
(($ $primcall 'bitvector? (a)) (unary emit-br-if-bitvector a)) ;; Add more TC7 tests here. Keep in sync with
(($ $primcall 'keyword? (a)) (unary emit-br-if-keyword a)) ;; *branching-primcall-arities* in (language cps primitives) and
;; Add more TC7 tests here. Keep in sync with ;; the set of macro-instructions in assembly.scm.
;; *branching-primcall-arities* in (language cps primitives) and (($ $primcall 'eq? (a b)) (binary emit-br-if-eq a b))
;; the set of macro-instructions in assembly.scm. (($ $primcall 'eqv? (a b)) (binary emit-br-if-eqv a b))
(($ $primcall 'eq? (a b)) (binary emit-br-if-eq a b)) (($ $primcall 'equal? (a b)) (binary emit-br-if-equal a b))
(($ $primcall 'eqv? (a b)) (binary emit-br-if-eqv a b)) (($ $primcall '< (a b)) (binary emit-br-if-< a b))
(($ $primcall 'equal? (a b)) (binary emit-br-if-equal a b)) (($ $primcall '<= (a b)) (binary emit-br-if-<= a b))
(($ $primcall '< (a b)) (binary emit-br-if-< a b)) (($ $primcall '= (a b)) (binary emit-br-if-= a b))
(($ $primcall '<= (a b)) (binary emit-br-if-<= a b)) (($ $primcall '>= (a b)) (binary emit-br-if-<= b a))
(($ $primcall '= (a b)) (binary emit-br-if-= a b)) (($ $primcall '> (a b)) (binary emit-br-if-< b a))
(($ $primcall '>= (a b)) (binary emit-br-if-<= b a)) (($ $primcall 'logtest (a b)) (binary emit-br-if-logtest a b))))
(($ $primcall '> (a b)) (binary emit-br-if-< b a))
(($ $primcall 'logtest (a b)) (binary emit-br-if-logtest a b)))))
(define (compile-trunc label k exp nreq rest-var) (define (compile-trunc label k exp nreq rest-var)
(define (do-call proc args emit-call) (define (do-call proc args emit-call)
@ -359,13 +378,17 @@
(lambda (asm proc-slot nargs) (lambda (asm proc-slot nargs)
(emit-call-label asm proc-slot nargs k)))))) (emit-call-label asm proc-slot nargs k))))))
(define (skip-elided-conts label)
(if (elide-cont? label)
(skip-elided-conts (1+ label))
label))
(define (compile-expression label k exp) (define (compile-expression label k exp)
(let* ((fallthrough? (= k (1+ label)))) (let* ((forwarded-k (forward-label k))
(fallthrough? (= forwarded-k (skip-elided-conts (1+ label)))))
(define (maybe-emit-jump) (define (maybe-emit-jump)
(unless (or fallthrough? (unless fallthrough?
(= (forward-label k '()) (emit-br asm forwarded-k)))
(forward-label (1+ label) '())))
(emit-br asm k)))
(match (intmap-ref cps k) (match (intmap-ref cps k)
(($ $ktail) (($ $ktail)
(compile-tail label exp)) (compile-tail label exp))
@ -377,7 +400,8 @@
(($ $kargs () ()) (($ $kargs () ())
(match exp (match exp
(($ $branch kt exp) (($ $branch kt exp)
(compile-test label exp kt k (1+ label))) (compile-test label exp (forward-label kt) forwarded-k
(skip-elided-conts (1+ label))))
(_ (_
(compile-effect label exp k) (compile-effect label exp k)
(maybe-emit-jump)))) (maybe-emit-jump))))
@ -389,8 +413,11 @@
(and rest (and rest
(match (intmap-ref cps kargs) (match (intmap-ref cps kargs)
(($ $kargs names (_ ... rest)) rest)))) (($ $kargs names (_ ... rest)) rest))))
(unless (and fallthrough? (= kargs (1+ k))) (let* ((kargs (forward-label kargs))
(emit-br asm kargs)))))) (fallthrough? (and fallthrough?
(= kargs (skip-elided-conts (1+ k))))))
(unless fallthrough?
(emit-br asm kargs)))))))
(define (compile-cont label cont) (define (compile-cont label cont)
(match cont (match cont
@ -421,7 +448,8 @@
names vars) names vars)
(when src (when src
(emit-source asm src)) (emit-source asm src))
(compile-expression label k exp)) (unless (elide-cont? label)
(compile-expression label k exp)))
(($ $kreceive arity kargs) (($ $kreceive arity kargs)
(emit-label asm label)) (emit-label asm label))
(($ $ktail) (($ $ktail)