[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

OPTIMIZE Declaration

At the meeting I volunteered to produce a new proposal for the OPTIMIZE
declaration.  Actually, I sent out such a proposal a couple of weeks
ago, but somehow it got lost before reaching SU-AI -- both that machine
and CMUC have been pretty flaky lately.  I did not realize that the rest
of you had not seen this proposal until a couple of days ago.
Naturally, this is the one thing I did not keep a copy of, so here is my
reconstruction.  I should say that this proposal is pretty ugly, but it
is the best that I've been able to come up with.  If anyone out there
can do better, feel free.

Guy originally proposed a format like (DECLARE (OPTIMIZE q1 q2 q3)),
where each of the q's is a quality from the set {SIZE, SPEED, SAFETY}.
(He later suggested to me that COMPILATION-SPEED would be a useful
fourth quality.)  The ordering of the qualities tells the system which
to optimize for.  The obvious problem is that you sometimes want to go
for, say, SPEED above all else, but usually you want some level of
compromise.  There is no way in this scheme to specify how strongly the
system should favor one quality over another.  We don't need a lot of
gradations for most compilers, but the simple ordering is not expressive

One possibility is to simply reserve the OPTIMIZE declaration for the
various implementations, but not to specify what is done with it.  Then
the implementor could specify in the red pages whatever declaration
scheme his compiler wants to follow.  Unfortunately, this means that
such declarations would be of no use when the code is ported to another
Common Lisp, and users would have no portable way to flag that some
function is an inner loop and should be super-fast, or whatever.  The
proposal below tries to provide a crude but adequate optimization
declaration for portable code, while still making it possible for users
to fine-tune the compiler's actions for particular implementations.

What I propose is (DECLARE (OPTIMIZE (qual1 value1) (qual2 value2) ...),
where the qualities are the four mentioned above and each is paired with
a value from 0 to 3 inclusive.  The ordering of the clauses doesn't
matter, and any quality not specified gets a default value of 1.  The
intent is that {1, 1, 1, 1} would be the compiler's normal default --
whatever set of compromises the implementor believes is appropriate for
his user community.  A setting of 0 for some value is an indication that
the associated quality is unimportant in this context and may be
discrimintaed against freely.  A setting of 2 indicates that the quality
should be favored more than normal, and a setting of 3 means to go all
out to favor that quality.  Only one quality should be raised above 1 at
any one time.

The above specification scheme is crude, but sufficiently expressive for
most needs in portable code.  A compiler implementor will have specific
decisions to make -- whether to suppress inline expansions, whether to
type-check the arguments to CAR and CDR, whether to check for overflow
on arithmetic declared to be FIXNUM, whether to run the peephole
optimizer, etc. -- and it is up to him to decide how to tie these
decisions to the above values so as to match the users expressed wishes.
These decision criteria should be spelled out in that implementation's red
pages.  For example, it might be the case that the peephole optimizer is
not run if COMPILER-SPEED > 1, that type checking for the argument to
CAR and CDR is suppressed if SPEED > SAFETY+1, etc.

A compiler may optionally provide for finer control in an
implementation-dependent way by allowing the user to set certain
compiler variables or switches via declarations.  The policies specified
by these variables would override any policies derived from the
optimization values described above.  The syntax would be as follows:

(DECLARE (COMPILER-VARIABLE implementation (var1 val1) (var2 val2) ...))

Each implementation would choose a distinct name, and the compiler would
ignore any COMPILER-VARIABLE declarations with a different
implementation name.  The red pages for an implementation would specify
what compiler variables are available and what they do.  Thus we might

(defun foo (x)
  (declare (compiler-variable vax (type-check-car/cdr nil))
           (compiler-variable s3600 (type-check-everything t)
	   (compiler-variable s1 (slow-down-so-the-rest-can-catch-up t)))

-- Scott