mirror of
https://github.com/justinethier/cyclone.git
synced 2025-07-15 08:47:35 +02:00
Issue #201 - Inline if expressions
This commit is contained in:
parent
ce6b24cc10
commit
a6093601de
1 changed files with 62 additions and 47 deletions
|
@ -176,34 +176,6 @@
|
||||||
;; Determine if the given top-level function can be freed from CPS, due
|
;; Determine if the given top-level function can be freed from CPS, due
|
||||||
;; to it only containing calls to code that itself can be inlined.
|
;; to it only containing calls to code that itself can be inlined.
|
||||||
(define (inlinable-top-level-lambda? expr)
|
(define (inlinable-top-level-lambda? expr)
|
||||||
;; TODO: consolidate with same function in cps-optimizations module
|
|
||||||
(define (prim-creates-mutable-obj? prim)
|
|
||||||
(member
|
|
||||||
prim
|
|
||||||
'(
|
|
||||||
apply ;; ??
|
|
||||||
cons
|
|
||||||
make-vector
|
|
||||||
make-bytevector
|
|
||||||
bytevector
|
|
||||||
bytevector-append
|
|
||||||
bytevector-copy
|
|
||||||
string->utf8
|
|
||||||
number->string
|
|
||||||
symbol->string
|
|
||||||
list->string
|
|
||||||
utf8->string
|
|
||||||
read-line
|
|
||||||
string-append
|
|
||||||
string
|
|
||||||
substring
|
|
||||||
Cyc-installation-dir
|
|
||||||
Cyc-compilation-environment
|
|
||||||
Cyc-bytevector-copy
|
|
||||||
Cyc-utf8->string
|
|
||||||
Cyc-string->utf8
|
|
||||||
list->vector
|
|
||||||
)))
|
|
||||||
(define (scan expr fail)
|
(define (scan expr fail)
|
||||||
(cond
|
(cond
|
||||||
((string? expr) (fail))
|
((string? expr) (fail))
|
||||||
|
@ -269,6 +241,48 @@
|
||||||
(k #t))))))) ;; Scanned fine, return #t
|
(k #t))))))) ;; Scanned fine, return #t
|
||||||
(else #f)))
|
(else #f)))
|
||||||
|
|
||||||
|
;; Scan given if expression to determine if an inline is safe.
|
||||||
|
;; Returns #f if not, the new if expression otherwise.
|
||||||
|
(define (inline-if:scan-and-replace expr kont)
|
||||||
|
(define (scan expr fail)
|
||||||
|
;(trace:error `(inline-if:scan-and-replace:scan ,expr))
|
||||||
|
(cond
|
||||||
|
((ast:lambda? expr) (fail))
|
||||||
|
((string? expr) (fail))
|
||||||
|
((bytevector? expr) (fail))
|
||||||
|
((const? expr) expr) ;; Good enough? what about large vectors or anything requiring alloca (strings, bytevectors, what else?)
|
||||||
|
((ref? expr) expr)
|
||||||
|
((if? expr)
|
||||||
|
`(Cyc-if ,(scan (if->condition expr) fail)
|
||||||
|
,(scan (if->then expr) fail)
|
||||||
|
,(scan (if->else expr) fail)))
|
||||||
|
((app? expr)
|
||||||
|
(let ((fnc (car expr)))
|
||||||
|
;; If function needs CPS, fail right away
|
||||||
|
(cond
|
||||||
|
((equal? (car expr) kont)
|
||||||
|
;; Get rid of the continuation
|
||||||
|
(scan (cadr expr) fail))
|
||||||
|
((or (not (prim? fnc))
|
||||||
|
(prim:cont? fnc)
|
||||||
|
(prim:mutates? fnc)
|
||||||
|
(prim-creates-mutable-obj? fnc)
|
||||||
|
)
|
||||||
|
(fail))
|
||||||
|
(else
|
||||||
|
;; Otherwise, check for valid args
|
||||||
|
(cons
|
||||||
|
(car expr)
|
||||||
|
(map
|
||||||
|
(lambda (e)
|
||||||
|
(scan e fail))
|
||||||
|
(cdr expr)))))))
|
||||||
|
;; Reject everything else - define, set, lambda
|
||||||
|
(else (fail))))
|
||||||
|
(call/cc
|
||||||
|
(lambda (return)
|
||||||
|
(scan expr (lambda () (return #f))))))
|
||||||
|
|
||||||
(define (analyze-find-lambdas exp lid)
|
(define (analyze-find-lambdas exp lid)
|
||||||
(cond
|
(cond
|
||||||
((ast:lambda? exp)
|
((ast:lambda? exp)
|
||||||
|
@ -850,8 +864,9 @@
|
||||||
(and
|
(and
|
||||||
(app? (if->then if-exp))
|
(app? (if->then if-exp))
|
||||||
(app? (if->else if-exp))
|
(app? (if->else if-exp))
|
||||||
(equal? kont (car (if->then if-exp)))
|
;(equal? kont (car (if->then if-exp)))
|
||||||
(equal? kont (car (if->else if-exp)))))
|
;(equal? kont (car (if->else if-exp)))
|
||||||
|
))
|
||||||
;;
|
;;
|
||||||
(not
|
(not
|
||||||
(with-fnc (ast:lambda-id (car exp)) (lambda (fnc)
|
(with-fnc (ast:lambda-id (car exp)) (lambda (fnc)
|
||||||
|
@ -860,15 +875,18 @@
|
||||||
;(trace:error `(DEBUG2 ,exp))
|
;(trace:error `(DEBUG2 ,exp))
|
||||||
(let* ((new-exp (car (ast:lambda-body (cadr exp))))
|
(let* ((new-exp (car (ast:lambda-body (cadr exp))))
|
||||||
(old-if (car (ast:lambda-body (car exp))))
|
(old-if (car (ast:lambda-body (car exp))))
|
||||||
; TODO: what about nested if's? may need another pass above to make sure
|
|
||||||
;; the if is simple enough to inline
|
|
||||||
TODO: can logic from inlinable-top-level-lambda? be repurposed to
|
|
||||||
scan old-if to make sure everything is inlinable???
|
|
||||||
(new-if `(Cyc-if ,(if->condition old-if)
|
|
||||||
,(cadr (if->then old-if))
|
|
||||||
,(cadr (if->else old-if))))
|
|
||||||
(old-k (car (ast:lambda-formals->list (car exp))))
|
(old-k (car (ast:lambda-formals->list (car exp))))
|
||||||
(old-arg (car (ast:lambda-formals->list (cadr exp))))
|
(old-arg (car (ast:lambda-formals->list (cadr exp))))
|
||||||
|
; TODO: what about nested if's? may need another pass above to make sure
|
||||||
|
;; the if is simple enough to inline
|
||||||
|
;TODO: can logic from inlinable-top-level-lambda? be repurposed to
|
||||||
|
;scan old-if to make sure everything is inlinable???
|
||||||
|
(new-if
|
||||||
|
(inline-if:scan-and-replace
|
||||||
|
`(Cyc-if ,(if->condition old-if)
|
||||||
|
,(if->then old-if)
|
||||||
|
,(if->else old-if))
|
||||||
|
old-k))
|
||||||
)
|
)
|
||||||
#;(trace:error `(DEBUG if inline candidate
|
#;(trace:error `(DEBUG if inline candidate
|
||||||
,exp
|
,exp
|
||||||
|
@ -882,16 +900,13 @@ scan old-if to make sure everything is inlinable???
|
||||||
,new-exp
|
,new-exp
|
||||||
))
|
))
|
||||||
|
|
||||||
(hash-table-set! refs old-k 'values) ;; TODO: only a temporary solution, requires (scheme base) which is not guaranteed to be imported
|
(cond
|
||||||
(hash-table-set! refs old-arg new-if)
|
(new-if
|
||||||
;; TODO: behavior would be:
|
(hash-table-set! refs old-arg new-if)
|
||||||
;; - simplify calling lambda's if to remove cont
|
(opt:inline-prims new-exp refs))
|
||||||
;; - replace arg to other lambda with simplified expression
|
(else
|
||||||
;; - replace exp with body of other lambda,
|
;; Could not inline
|
||||||
;; - and call opt:inline-prims on it
|
(map (lambda (e) (opt:inline-prims e refs)) exp)))
|
||||||
(opt:inline-prims new-exp refs)
|
|
||||||
;; Same behavior for now, just seeing if this is possible first
|
|
||||||
;(map (lambda (e) (opt:inline-prims e refs)) exp)
|
|
||||||
)) ;;
|
)) ;;
|
||||||
(else
|
(else
|
||||||
(map (lambda (e) (opt:inline-prims e refs)) exp))))
|
(map (lambda (e) (opt:inline-prims e refs)) exp))))
|
||||||
|
|
Loading…
Add table
Reference in a new issue