Subject: access to declaration information?
From: Erik Naggum <clerik@naggum.no>
Date: 1998/03/13
Newsgroups: comp.lang.lisp
Message-ID: <3098779525464968@naggum.no>
when writing highly optimized code, it is important to bind a variable to
values of a single type so the compiler can optimize out the (redundant)
type dispatch or checks, but however useful this may be, it is not quite
sufficient for speed when macros use local variables that bound to the
values, yet cannot "inherit" the known type restrictions into their own
declarations.
e.g., DOTIMES can easily optimize the representation of the counter
variable if the upper bound is a constant fixnum, but if the upper bound
is an expression that ought to be a constant fixnum because the compiler
has already been informed of the relevant types and values involved, like
the length of a vector that has been declared with a size, it's out of
luck, and must use generic integer arithmetic. in traversing a vector, I
wouldn't want to use the stupid C-approach and use DEFCONSTANT to define
a symbol to hold the size and sprinkle that symbol around the code, I
want to use (LENGTH <vector>) and that should be a constant if <vector>
is in a scope with, say, (DECLARE (TYPE (VECTOR * 256) <vector>)), and
variables whose values are tall taken from the set of indexes into this
vector should be automatically declared (INTEGER 0 256). also, I want a
macro-expansion function to be able to make the appropriate declarations
by querying the environment for the declaration of the subexpressiosn
involved. relying on the compiler to optimize away multiple layers of
general macro-expansion code to divine the appropriate clauses that fit
the type is just too optimistic.
suppose I have a vector or some kind, and want to utilize SVREF when the
vector is a simple vector. if I could know that the vector is simple in
function calls that take this vector as argument, I could write a
compiler macro to differentiate between the simple-vector case and the
general case. if I knew some index arguments were declared to be less
than the length of the vector, I could skip both bignum tests and range
checks, but I would still want them if the function is called when I
don't know that.
I could use generic functions that specialize on all the argument types
and _hope_ the compiler does compile-time dispatch to methods when it
knows the types of all the arguments, but this, too, is removing some of
the control that you want when your code is going to be squeezed to the
last drop of performance. of course, you could write your own functions
that encode the types of the arguments like som manual C++ name-mangler
and write all optimized code with them, but that is _so_ disgusting.
this may sound (too) hairy for Lisp, but this is the kind of stuff that
strongly typed languages so readily exploit. if it were available for
Lisp, too, the programmer and the compiler could cooperate on the speed
of the code, instead of the programmer guessing and hoping he knows what
makes the compiler happy enough to produce optimal code.
am I out of luck?
(note: other languages with these properties are not interesting at this
time. Common Lisp doesn't get better by leaving it whenever you need
something that isn't readily available, and porting applications to
another language is not an option, anyway.)
#:Erik
--
God grant me serenity to accept the code I cannot change,
courage to change the code I can, and wisdom to know the difference.