~ chicken-core (chicken-5) 0fcc20358eb98dd2e8f84ae0ce85e48cde8889ed
commit 0fcc20358eb98dd2e8f84ae0ce85e48cde8889ed Author: felix <felix@call-with-current-continuation.org> AuthorDate: Fri Aug 30 10:09:22 2019 +0200 Commit: Peter Bex <peter@more-magic.net> CommitDate: Sun Sep 15 11:42:24 2019 +0200 Add some optimizer simplification rules Certain combinations of conditionals and ##core#inline operations turns out to reduce the opportunity for collapsing continuation lambdas, specifically, constructs like (if ... (let ((<var> (##core#inline ...))) (<kvar> (##core#inline ... <var> ...))) (<kvar> ...)) could not be optimized into a simpler form (<kvar> ... (##core#cond ...) ...) and thus not be contracted. This patch rewrites the given form (and a variation using ##core#call) into a nested ##core#inline expression, making the contraction possible. diff --git a/optimizer.scm b/optimizer.scm index 8017ef19..5d80ad12 100644 --- a/optimizer.scm +++ b/optimizer.scm @@ -792,7 +792,79 @@ (make-node 'if d (list (make-node '##core#inline (list op) args) - x y) ) ) ) ) ) + x y) ) ) ) ) + + ;; (let ((<var1> (##core#inline <op1> ...))) + ;; (<var2> (##core#inline <op2> ... <var1> ...))) + ;; -> (<var2> (##core#inline <op2> ... (##core#inline <op2> ...) + ;; ...)) + ;; - <var1> is used only once. + `((let (var) (##core#inline (op1) . args1) + (##core#call p + (##core#variable (kvar)) + (##core#inline (op2) . args2))) + (var op1 args1 p kvar op2 args2) + ,(lambda (db may-rewrite var op1 args1 p kvar op2 args2) + (and may-rewrite ; give other optimizations a chance first + (not (eq? var kvar)) + (not (db-get db kvar 'contractable)) + (= 1 (length (db-get-list db var 'references))) + (let loop ((args args2) (nargs '()) (ok #f)) + (cond ((null? args) + (and ok + (make-node + '##core#call p + (list (varnode kvar) + (make-node + '##core#inline + (list op2) + (reverse nargs)))))) + ((and (eq? '##core#variable + (node-class (car args))) + (eq? var + (car (node-parameters (car args))))) + (loop (cdr args) + (cons (make-node + '##core#inline + (list op1) + args1) + nargs) + #t)) + (else (loop (cdr args) + (cons (car args) nargs) + ok))))))) + + ;; (let ((<var1> (##core#inline <op> ...))) + ;; (<var2> ... <var1> ...)) + ;; -> (<var2> ... (##core#inline <op> ...) ...) + ;; ...)) + ;; - <var1> is used only once. + `((let (var) (##core#inline (op) . args1) + (##core#call p . args2)) + (var op args1 p args2) + ,(lambda (db may-rewrite var op args1 p args2) + (and may-rewrite ; give other optimizations a chance first + (= 1 (length (db-get-list db var 'references))) + (let loop ((args args2) (nargs '()) (ok #f)) + (cond ((null? args) + (and ok + (make-node + '##core#call p + (reverse nargs)))) + ((and (eq? '##core#variable + (node-class (car args))) + (eq? var + (car (node-parameters (car args))))) + (loop (cdr args) + (cons (make-node + '##core#inline + (list op) + args1) + nargs) + #t)) + (else (loop (cdr args) + (cons (car args) nargs) + ok)))))))) (register-simplificationsTrap