[plt-scheme] dead code elimination/closure optimization?

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Sat Apr 7 20:51:35 EDT 2007

At Sat, 7 Apr 2007 20:30:35 -0400 (EDT), Dimitris Vyzovitis wrote:
> Does the bytecode compiler or the jitter do dead code elimination for
> closures?

In easy cases.

> For example in
> (let ((foo (lambda () ...))) body ...)
> where foo is not referenced in the body (other than perhaps in in
> turn unreferenced macros), is the lambda closure construction and variable
> assignment code present in bytecode and ultimately in the
> code generated by the jit?

No, the procedure will be dropped. But if there are assignments in the
procedure, they will lead to worse code, anyway.

> What about
> (letrec ((foo (lambda () ... (set! foo ...) ...))) body ...) with
> similar body conditions for foo?

Not currently. The bytecode compiler does not currently detect dead
code bound by `letrec'. The `set!' would likely create trouble if
`letrec' wasn't already a problem.

Here's a way to get some idea of what the optimizer will do, as Eli
showed a few weeks ago:

 (define (comp=? c1 c2)
   (let ([s1 (open-output-bytes)]
         [s2 (open-output-bytes)])
     (write c1 s1)
     (write c2 s2)
     (let ([t1 (get-output-bytes s1)]
           [t2 (get-output-bytes s2)])
       (bytes=? t1 t2))))

 (comp=? (compile '(let ([f (lambda () 10)]) (display 2)))
         (compile '(display 2)))
 ; => #t

 (comp=? (compile '(let* ([x 8][f (lambda () x)]) (display x)))
         (compile '(display 8)))
 ; => #t

 (comp=? (compile '(let* ([x 8][f (lambda () (set! x 5))]) 
                     (display x)))
         (compile '(display 8)))
 ; => #f
 ;  because the `set!' prevents constant propagation `x', even though
 ;  the `set!' is eventually removed

 (comp=? (compile '(letrec ([f (lambda () 10)]) (display 2)))
         (compile '(display 2)))
 ; => #f
 ;  because the optimizer is currently conservative about `letrec'

 (comp=? (compile '(let* ([f (lambda () 10)][g (lambda () (f 6))]) (display 2)))
         (compile '(display 2)))
 ; => #f
 ;  because `g' is eliminated, but only after the decision is made to
 ; keep `f'

See also the middle part of "collects/tests/mzscheme/optimize.ss".


Posted on the users mailing list.