From: Bruno Haible
Subject: querying the optimization settings
Date: 
Message-ID: <6hg2fi$9a1$1@nz12.rz.uni-karlsruhe.de>
In Common Lisp, there is no portable way to have macroexpansions depend on
the optimization settings (speed, safety, etc.), i.e. in large programs,
the effect of these settings is limited to system code and low-level
issues like the function calls. For example, there is no way to have
a user-defined ASSERT-like macro which would expand to nothing if safety=0.

Using EVAL-WHEN (COMPILE) or DEFINE-COMPILER-MACRO does not help because
there is no portable way to access the current speed, safety etc. settings.

I propose to add a macro OPTIMIZECASE such that you could write things like

  (optimizecase ((> safety 0) (do-some-checking)))

  (defun my-fixnum-add (x y)
    (optimizecase
      ((> speed safety) (the fixnum (+ (the fixnum x) (the fixnum y))))
      ((= speed safety) (+ (the fixnum x) (the fixnum y)))
      (t                (+ (the integer x) (the integer y)))
  ) )

Formal proposal:

Add a macro OPTIMIZECASE.

  (OPTIMIZECASE clause*)
  clause ::= (test-form form*)

  This macro evaluates, in the macroexpansion environment, each test-form
  in turn. The test-form may reference the symbols naming optimize
  qualities as lexical variables, i.e. it is as if each test-form were
  enclosed in a
    (lambda (compilation-speed debug safety space speed ...) test-form).
  The values of the optimize qualities are the current values in the
  macroexpansion environment. In the interpreter, these values are
     compilation-speed  2
     debug              3
     safety             3
     space              0
     speed              0
  When a test-form returns a non-nil value, the macroexpansion of the
  OPTIMIZECASE form becomes the implicit progn containing the forms of
  the same clause, (PROGN form*), and remaining test-forms are not
  evaluated any more.

  If all of the test-forms evaluate to nil, an error is signalled.

Examples:

  See above.

Current Practice:

  ILOG Talk (not a Common Lisp) has a similar macro called `case-level'.

Cost to Implementors:

  Minor.

Cost to Users:

  Must be aware that macro expansions may depend on optimize qualities,
  even if DEFINE-COMPILER-MACRO is not used.

Cost of non-adoption:

  Portable programs cannot enquire the optimize qualities.

Performance impact:

  None.

Benefits:

  The cost of non-adoption is avoided.

Esthetics:

  If you think DEFINE-COMPILER-MACRO is elegant, then this is elegant too.


Bruno <······@clisp.cons.org>                    http://clisp.cons.org/~haible/

From: Barry Margolin
Subject: Re: querying the optimization settings
Date: 
Message-ID: <dKM_.13$344.325274@cam-news-reader1.bbnplanet.com>
In article <············@nz12.rz.uni-karlsruhe.de>,
Bruno Haible <······@clisp.cons.org> wrote:
>In Common Lisp, there is no portable way to have macroexpansions depend on
>the optimization settings (speed, safety, etc.), i.e. in large programs,
>the effect of these settings is limited to system code and low-level
>issues like the function calls. For example, there is no way to have
>a user-defined ASSERT-like macro which would expand to nothing if safety=0.

This was part of the environment-introspection mechanism that's described
in the Macros chapter of CLtL2; you could get optimization settings with
(declaration-information 'optimize <env>).  However, this stuff was all
pulled out before ANSI CL was completed, because there were problems with
the proposals and we didn't have time to work them out; we felt that it
would be better to allow implementors to work on these features, and
expected that a de facto standard would emerge by the time of the next ANSI
CL revision.

>Add a macro OPTIMIZECASE.
>
>  (OPTIMIZECASE clause*)
>  clause ::= (test-form form*)

You need an optional way to specify an environment.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: Bruno Haible
Subject: Re: querying the optimization settings
Date: 
Message-ID: <6hid52$jf3$1@nz12.rz.uni-karlsruhe.de>
> You need an optional way to specify an environment.

Can you please explain why? The fact that no environment occurs in my
proposal is actually a strength, because there is no need to worry about
functions to access this environment, and it doesn't constrain implementations
unnecessarily: An implementation has to provide the right values for the
lexical variables `speed', `safety' etc, that's all.

                             Bruno
From: Barry Margolin
Subject: Re: querying the optimization settings
Date: 
Message-ID: <vT4%.15$Qh4.274802@cam-news-reader1.bbnplanet.com>
In article <············@nz12.rz.uni-karlsruhe.de>,
Bruno Haible <······@clisp.cons.org> wrote:
>> You need an optional way to specify an environment.
>
>Can you please explain why? The fact that no environment occurs in my
>proposal is actually a strength, because there is no need to worry about
>functions to access this environment, and it doesn't constrain implementations
>unnecessarily: An implementation has to provide the right values for the
>lexical variables `speed', `safety' etc, that's all.

That will only work if a macro expands into an OPTIMIZECASE form, so that
these variable are lexically apparent to it.  If it wants to use the
optimization settings at expansion time to generate different code, it
needs to be able to query the environment at that time.

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: Harley Davis
Subject: Re: querying the optimization settings
Date: 
Message-ID: <6hjh3s$bsj$1@news1-alterdial.uu.net>
Barry Margolin wrote in message ...
>In article <············@nz12.rz.uni-karlsruhe.de>,
>Bruno Haible <······@clisp.cons.org> wrote:
>>> You need an optional way to specify an environment.
>>
>>Can you please explain why? The fact that no environment occurs in my
>>proposal is actually a strength, because there is no need to worry about
>>functions to access this environment, and it doesn't constrain
implementations
>>unnecessarily: An implementation has to provide the right values for the
>>lexical variables `speed', `safety' etc, that's all.
>
>That will only work if a macro expands into an OPTIMIZECASE form, so that
>these variable are lexically apparent to it.  If it wants to use the
>optimization settings at expansion time to generate different code, it
>needs to be able to query the environment at that time.


The intended idea is that the macro expands into an OPTIMIZECASE form; the
only actual expansion used by the language processor is the one
corresponding to the current environment settings.

-- Harley
From: Joao Cachopo
Subject: Re: querying the optimization settings
Date: 
Message-ID: <wx7m4igq23.fsf@haiti.gia.ist.utl.pt>
In a followup to Bruno Haible proposal for OPTIMIZE-CASE,

>>>>> "Barry" == Barry Margolin <······@bbnplanet.com> writes:

 Barry> This was part of the environment-introspection mechanism
 Barry> that's described in the Macros chapter of CLtL2; you could get
 Barry> optimization settings with (declaration-information 'optimize
 Barry> <env>).  However, this stuff was all pulled out before ANSI CL
 Barry> was completed, because there were problems with the proposals
 Barry> and we didn't have time to work them out; we felt that it
 Barry> would be better to allow implementors to work on these
 Barry> features, and expected that a de facto standard would emerge
 Barry> by the time of the next ANSI CL revision.

I've been reading in CLHS some of the issues relating to this, namely,
the SYNTACTIC-ENVIRONMENT-ACCESS issue.  (That proposal provides,
IMHO, a much better solution than OPTIMIZE-CASE to the problem
described.)

Actually, I agree with Kent Pitman that the values of optimize
settings actually used do have different meaning in different systems,
and I would even dare to say that, probably, they are not used
coherently within the same system.

What drove me to the SYNTACTIC-ENVIRONMENT-ACCESS issue was the need
to get another kind of information from the environment.  Namely, type
declarations.  These have a precise meaning, and a macro writer could
use them to include good declarations in a macro expansion.

Consider, for example, the macro DOTIMES.  
The variable it bounds is an integer that ranges from 0 to ...  

Therefore, we can include in the expansion of (dotimes (i 10) ..)
something like (declare (type (integer 0) i)).
(Actually, can we really do this?  What if "I" is setf'ed to something
else in the body?)

As a matter of fact, if the "count-form" is a literal we can do better
than this, and use (declare (type (integer 0 10) i)).

However, if the macro call does not use a literal but a variable, for
instance, we are hopeless.  If we could get any kind of type
information from the environment regarding the variable, maybe we
could do a better job in the expansion, in cases such as the
following:

   (defun foo (n)
     (declare (fixnum n))
     (dotimes (i n)
       'bla))

We could expand the dotimes into something with the following
declaration: (declare (type (and (integer 0) fixnum) i)).
(Blindly building type specifiers with will not work, though, because
N could be declared as being (integer 10 20), for instance.)

However, after some thoughts about this and some related issues, I
wondered whether this would be a reasonable approach to the problem.
It seems that it will give a lot of work to macro writers.  Or, in the
case of dotimes, which is part of ANSI CL, to implementors.  Somehow,
I feel that a better alternative is needed...

But I digress (sorry)...

The underlying reason that made me wrote this message is this: when
trying to get good performance from a Lisp program, after profiling
the code and doing all the restructuring needed, we have to resort to
"micro-optimization" things like type declarations and optimization
settings.  However, it is not always obvious where to put the
declarations and how much of them, because different Lisp compilers
have different type inferencers, for instance.

Now, my question is: wouldn't be better to build a program (in
portable Lisp, of course) that reads the program to optimize and
writes a version of it with declarations added?  I'm not saying it
would be easy (it needs a code walker, for a start), but it would take
the burden of some optimizations from the implementors.  Besides, if
properly done, it would provide to programmers a clear model of what
to expect from their declarations.

This is just a sketchy idea, but I would like to know if something
like this has been attempted before.  Of course, if an implementor has
such a thing already (which they must have, though probably not in
portable CL), it would like to keep it secret :-)

I hope that this message didn't bore you too much :-/,
-- 
Joao Cachopo   *   Homepage: http://www.gia.ist.utl.pt/~jcachopo

                 *** Murphy was an optimist ***
From: Kent M Pitman
Subject: Re: querying the optimization settings
Date: 
Message-ID: <sfwhg3o89w3.fsf@world.std.com>
······@clisp.cons.org (Bruno Haible) writes:

> In Common Lisp, there is no portable way to have macroexpansions depend on
> the optimization settings (speed, safety, etc.), i.e. in large programs,

To make a serious proposal on this one, you need a survey of current
practice.  In some implementations, relative values of settings are what
matters, in some absolute values matter, and some are mixed.  The problem
is that knowing the values of the settings doesn't help unless you
ALSO establish some coherent theory for why people would have set certain
values in the first place.  Otherwise, you might end up in a situation
where person A writes a macro library where (FOO X)
expands into (DECLARE (SPEED 1) (SAFETY 0)) thinking speed>safety
will make things speedy, while person B will write something with
 (DECLARE (SPEED 1))
thinking speeds way less than 3 will be "speed doesn't matter" and then
the two macros will be used in the same environment, one thinking it
means "speed doesn't matter" and another thinking it means "speed matters"
and then your macro package will comme along and try to attach some third
purpose.  It's a BIG problem and the only way to get a handle on it is
to FIRST get systems to agree on how various standard system-y things are
specified.  Then, once that is roped in, you can worry about user extension.

See also Barry's remarks, which are largely orthogonal.