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

From: Dimitris Vyzovitis (vyzo at media.mit.edu)
Date: Sat Apr 7 21:21:10 EDT 2007

On Sun, 8 Apr 2007, Matthew Flatt wrote:

> At Sat, 7 Apr 2007 20:30:35 -0400 (EDT), Dimitris Vyzovitis wrote:
> > 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.

It seems to me that some of these issues would disappear if the optimizer
was doing multiple passes -- preferably recursively until a fixpoint is
reached in the generated code.

>  (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

Here, a constant propagation pass after the dead code elimination would do
the trick.

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

Ok, letrec is trickier. With standard expansion to
(let ((f #<undefined>))
  (set! f (lambda () 10))
  ...)

it may be possible to get rid of it with multiple passes, but it requires
safe mutation removal of sorts (the computation of the value in the
assingment has no direct side effects)

>
>  (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'

ditto for multiple passess

-- vyzo



Posted on the users mailing list.