prompt handlers are always inline
[bpt/guile.git] / module / language / tree-il / inline.scm
CommitLineData
dab0f9d5
AW
1;;; a simple inliner
2
282d128c 3;; Copyright (C) 2009, 2010 Free Software Foundation, Inc.
dab0f9d5 4
c21c89b1
AW
5;;;; This library is free software; you can redistribute it and/or
6;;;; modify it under the terms of the GNU Lesser General Public
7;;;; License as published by the Free Software Foundation; either
8;;;; version 3 of the License, or (at your option) any later version.
9;;;;
10;;;; This library is distributed in the hope that it will be useful,
11;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
12;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13;;;; Lesser General Public License for more details.
14;;;;
15;;;; You should have received a copy of the GNU Lesser General Public
16;;;; License along with this library; if not, write to the Free Software
17;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
dab0f9d5
AW
18
19(define-module (language tree-il inline)
8a4ca0ea 20 #:use-module (system base pmatch)
dab0f9d5
AW
21 #:use-module (system base syntax)
22 #:use-module (language tree-il)
23 #:export (inline!))
24
25;; Possible optimizations:
26;; * constant folding, propagation
27;; * procedure inlining
28;; * always when single call site
29;; * always for "trivial" procs
30;; * otherwise who knows
31;; * dead code elimination
32;; * degenerate case optimizations
33;; * "fixing letrec"
34
35;; This is a completely brain-dead optimization pass whose sole claim to
36;; fame is ((lambda () x)) => x.
37(define (inline! x)
8a4ca0ea
AW
38 (define (inline1 x)
39 (record-case x
40 ((<application> src proc args)
41 (record-case proc
42 ;; ((lambda (y ...) x) z ...) => (let ((y z) ...) x)
43 ((<lambda> body)
44 (let lp ((lcase body))
45 (and lcase
46 (record-case lcase
3a88cb3b 47 ((<lambda-case> req opt rest kw inits vars body alternate)
1e2a8edb 48 (if (and (= (length vars) (length req) (length args)))
8a4ca0ea
AW
49 (let ((x (make-let src req vars args body)))
50 (or (inline1 x) x))
3a88cb3b 51 (lp alternate)))))))
bca488f1 52
8a4ca0ea 53 ((<primitive-ref> name)
349d5c44
AW
54 (case name
55 ((@call-with-values)
56 (pmatch args
57 ;; (call-with-values (lambda () foo) (lambda (a b . c) bar))
58 ;; => (let-values (((a b . c) foo)) bar)
59 ;;
60 ;; Note that this is a singly-binding form of let-values.
61 ;; Also note that Scheme's let-values expands into
62 ;; call-with-values, then here we reduce it to tree-il's
63 ;; let-values.
64 ((,producer ,consumer)
65 (guard (lambda? consumer)
66 (lambda-case? (lambda-body consumer))
67 (not (lambda-case-opt (lambda-body consumer)))
68 (not (lambda-case-kw (lambda-body consumer)))
69 (not (lambda-case-alternate (lambda-body consumer))))
70 (make-let-values
71 src
72 (let ((x (make-application src producer '())))
73 (or (inline1 x) x))
74 (lambda-body consumer)))
75 (else #f)))
76
77 ((memq memv)
78 (pmatch args
79 ((,k ,l) (guard (const? l) (list? (const-exp l)))
492e7efe
AW
80 (if (null? (const-exp l))
81 (make-const #f #f)
82 (let lp ((elts (const-exp l)))
83 (let ((test (make-application
84 #f
85 (make-primitive-ref #f (case name
86 ((memq) 'eq?)
87 ((memv) 'eqv?)
88 (else (error "what"))))
89 (list k (make-const #f (car elts))))))
90 (if (null? (cdr elts))
91 test
92 (make-conditional
93 src
94 test
95 (make-const #f #t)
96 (lp (cdr elts))))))))
349d5c44
AW
97
98 (else #f)))
99
100 (else #f)))
bca488f1
AW
101
102 (else #f)))
80af1168 103
8a4ca0ea
AW
104 ((<let> vars body)
105 (if (null? vars) body x))
80af1168 106
8a4ca0ea
AW
107 ((<letrec> vars body)
108 (if (null? vars) body x))
80af1168 109
8a4ca0ea
AW
110 ((<fix> vars body)
111 (if (null? vars) body x))
80af1168 112
ea6b18e8
AW
113 ((<lambda-case> req opt rest kw vars body alternate)
114 (let ()
115 (define (args-compatible? args vars)
116 (let lp ((args args) (vars vars))
117 (cond
118 ((null? args) (null? vars))
119 ((null? vars) #f)
120 ((and (lexical-ref? (car args))
121 (eq? (lexical-ref-gensym (car args)) (car vars)))
122 (lp (cdr args) (cdr vars)))
123 (else #f))))
124
125 (and (not opt) (not kw) (not alternate)
126 (record-case body
127 ((<application> proc args)
128 ;; (lambda args (apply (lambda ...) args)) => (lambda ...)
129 (and (primitive-ref? proc)
130 (eq? (primitive-ref-name proc) '@apply)
131 (pair? args)
132 (lambda? (car args))
133 (args-compatible? (cdr args) vars)
134 (lambda-body (car args))))
135 (else #f)))))
136
8a4ca0ea
AW
137 (else #f)))
138 (post-order! inline1 x))