From: Andrew Reilly on
Hi there,

Much as enjoy lisp, I still spend quite a bit of my time worrying about
single-instruction details of generated C code (embedded DSP
applications). I was wondering, this morning, whether the state-of-lisp-
compiler-art ran to inlining of leaf functions, and all of the usual
subsequent optimization steps like CSE and constant propagation? That
would seem to require that function definitions hang around symbolically,
as well as having machine code generated. Not too hard I suppose.

Anyway, that was thought-1. The larger question in my mind was whether
this code generation and inlining process was ever invoked on runtime-
(nebulous concept, I know) -generated closures? That is, if the free
variables closed in a function that was subsequently called from a larger
function (defined after the closure was formed), could constant values of
closed free variables be part of the inlining and optimization process of
the new, larger function? I couldn't see any particular reason why that
couldn't happen, but I haven't heard it described.

Something along the lines of:

(defun a (offset) (lambda (x) (+ x offset))

(defvar a3)
(setf a3 (a 3))

(defun foo () t)
(defun bar (x) x)

(defun something-big (some args)
(cond
((foo)
(bar (funcall a3 4)))))

Would it be common for a contemporary lisp compiler to code the call to
a3 directly as (fx+ 4 3), (rather than always finding the "offset"
variable in some dynamic data structure), or even as 7, or even propagate
that 7 into an in-lining of bar?

I've just done a spot of googling, and found the results a bit
confusing. For example this one from 1986 seemed to suggest that all of
this was possible:
http://portal.acm.org/citation.cfm?
id=13323&dl=GUIDE&coll=GUIDE&CFID=80197817&CFTOKEN=62204720

but this one from 2009:
http://cl-www.msi.co.jp/solutions/knowledge/lisp-world/tutorial/compiler-
eval-e.pdf

suggested that it might not be in wide use today...

Entering that code into sbcl does seem to show it doing both inlining and
conversion of the closure into an inlined function, which is quite
cool... Not sure that I can detect constant propagation in the generated
assembly, though.

Sure, this sort of thing doesn't matter greatly, in the normal run of
coding, but there's an interesting question in my mind about the quality
with which a language supports the building and layering of abstractions.

Cheers,

--
Andrew
From: Thomas A. Russ on
Andrew Reilly <areilly---(a)bigpond.net.au> writes:

> Much as enjoy lisp, I still spend quite a bit of my time worrying about
> single-instruction details of generated C code (embedded DSP
> applications). I was wondering, this morning, whether the state-of-lisp-
> compiler-art ran to inlining of leaf functions, and all of the usual
> subsequent optimization steps like CSE and constant propagation? That
> would seem to require that function definitions hang around symbolically,
> as well as having machine code generated. Not too hard I suppose.

Well, this really depends a lot on the particular lisp implementation.
Certainly SBCL, CCL, CMUCL and the commercial lisps do a good job of
this.* The degree to which this is done depends on both the particular
lisp and also on the optimization settings when things get compiled.
There are also some additional things that can be done with block
compilation, through compiling files or using WITH-COMPILATION-UNIT.

> Anyway, that was thought-1. The larger question in my mind was whether
> this code generation and inlining process was ever invoked on runtime-
> (nebulous concept, I know) -generated closures?

Again, this can vary depending on the particular lisp implementation.
Sometimes it will happen automatically, and in other cases you have to
arrange to call the COMPILE function at run time in order to guarantee
that the generated code gets compiled at all.




*Omitted lisps don't necessarily not do it, I just have no knowledge one
way or the other.


--
Thomas A. Russ, USC/Information Sciences Institute