Next: Generic Arithmetic, Previous: Non-Descriptor Representations, Up: Numbers [Contents][Index]
In order to use a non-descriptor representation for a variable or expression intermediate value, the compiler must be able to prove that the value is always of a particular type having a non-descriptor representation. Type inference (see type-inference) often needs some help from user-supplied declarations. The best kind of type declaration is a variable type declaration placed at the binding point:
(let ((x (car l))) (declare (single-float x)) ...)
Use of the
, or of variable declarations not at the binding form
is insufficient to allow non-descriptor representation of the
variable—with these declarations it is not certain that all
values of the variable are of the right type. It is sometimes useful
to introduce a gratuitous binding that allows the compiler to change
to a non-descriptor representation, like:
(etypecase x ((signed-byte 32) (let ((x x)) (declare (type (signed-byte 32) x)) ...)) ...)
The declaration on the inner x
is necessary here due to a phase
ordering problem. Although the compiler will eventually prove that
the outer x
is a (signed-byte 32)
within that
etypecase
branch, the inner x
would have been optimized
away by that time. Declaring the type makes let optimization more
cautious.
Note that storing a value into a global (or special
) variable
always forces a descriptor representation. Wherever possible, you
should operate only on local variables, binding any referenced globals
to local variables at the beginning of the function, and doing any
global assignments at the end.
Efficiency notes signal use of inefficient representations, so programmer’s needn’t continuously worry about the details of representation selection (see representation-eff-note.)
Next: Generic Arithmetic, Previous: Non-Descriptor Representations, Up: Numbers [Contents][Index]