Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

on optimizing assigned-only bindings in LET forms

43 views
Skip to first unread message

Marco Maggi

unread,
Nov 4, 2012, 6:53:12 AM11/4/12
to
Ciao,

I am reviewing the source code optimizer in Vicare Scheme;
I am not really a compiler guy. The optimizer does a single
pass; when it finds a LET form like:

(let ((a (do-this))
(b 123))
(do-that b))

in which A is never referenced, it transforms the code into:

(begin
(do-this)
(let ((b 123))
(do-that b)))

and it is fine; when it finds a LET form like:

(let ((a (do-this)))
(set! a (do-that))
456)

where A is never referenced but it is assigned, it
transforms the code into:

(begin
(do-this)
(let ((a #<unspecified>))
(set! a (do-that))
456))

I cannot imagine why this is desirable beyond this reason:
with the optimizer doing a single pass, it is impossible to
go back to the assignment places and transform the
assignment into an RHS evaluation for side effects; that is,
it would occur another pass to transform the code into:

(begin
(do-this)
(let ()
(do-that)
456))

Am I missing something?

TIA
--
Marco Maggi

Nils M Holm

unread,
Nov 4, 2012, 11:40:47 AM11/4/12
to
Marco Maggi <ma...@maggi.invalid> wrote:
> and it is fine; when it finds a LET form like:
>
> (let ((a (do-this)))
> (set! a (do-that))
> 456)
>
> where A is never referenced but it is assigned, it
> transforms the code into:
>
> (begin
> (do-this)
> (let ((a #<unspecified>))
> (set! a (do-that))
> 456))
>
> I cannot imagine why this is desirable beyond this reason:
> with the optimizer doing a single pass, it is impossible to
> go back to the assignment places and transform the
> assignment into an RHS evaluation for side effects; that is,
> it would occur another pass to transform the code into:
>
> (begin
> (do-this)
> (let ()
> (do-that)
> 456))

As far as I can tell, that optimization would be perfectly fine.

Given the fact that A is never referenced in the original form

(let ((a (do-this)))
(set! a (do-that))
456)

and there is no way that A is being referenced or closed-over in
a procedure DO-THAT, I would probably even be comfortable with
transforming it to

(begin (do-this)
(do-that)
456)

Even if DO-THAT would be a macro that closes over A, its value
is never used, because the expression does not return it. So I
would consider your supposed transformation legitimate.

If there was any way in which DO-THAT could use A, BTW, even the
first transformation indicated at the top would be invalid.

--
Nils M Holm < n m h @ t 3 x . o r g > www.t3x.org

Marco Maggi

unread,
Nov 4, 2012, 2:52:53 PM11/4/12
to
Nils M Holm wrote:
> As far as I can tell, that optimization would be perfectly
> fine.

Thanks.

> If there was any way in which DO-THAT could use A, BTW,
> even the first transformation indicated at the top would
> be invalid.

All of this happens on fully expanded code. The real thing
(as I understand it so far) is this: after full expansion
the code in the core language is:

(letrec ((a (display "ciao"))
(b (lambda (x) a (list x))))
(set! a 123)
123)

in which A is referenced and assigned, so an internal
structure reports that it is "referenced before
optimization"; the LETREC optimizer transforms the code into
(not quite but close enough):

(let ((a (display '"ciao")))
(let ((b (lambda (x)
(begin
a
(list x)))))
(begin
(set! a '123)
'123)))

and now comes the source optimizer:

* First it processes the inner body, and since A is marked
as referenced before optimization, it does not remove the
assignment; rather it marks A as "still assigned after
optimization".

* Then it processes the inner LET, recognising the function
B as not referenced; so it removes it:

(let ((a (display '"ciao")))
(begin
(set! a '123)
'123))

A is left marked as "not referenced after optimization".

* Finally it processes the outer LET, now A is actually no
more referenced, but still assigned after optimization and
so the final transformation is:

(begin
(display '"ciao")
(let ((a #<unspecified>))
(begin
(set! a '123)
'123)))

because it is too late to remove the assignment.

An additional pass would clean up things, but it is not
performed by Vicare (whose logic is the same as the Ikarus
Scheme one). Maybe because such suboptimization is rare.
--
Marco Maggi
0 new messages