New Compiler Switches in Allegro CL 8.2

The behavior of the compiler in Allegro CL is controlled in part by
compiler switches. These switches are described in the
section Declarations
and optimizations
in compiling.htm. They
are variables whose values are functions which takes as arguments the
values of the compiler optimization qualities safety, space, speed,
debug, and compilation-speed and return t or nil as the
switch should or should not affect the compilation. (The values of the
variables can also be t or nil, meaning the switch is always on or
always off.)

There are twenty-four switches. The
function explain-compiler-settings
displays the switch values for specified values of the optimization
qualities (defaulting to the current global values). Obviously using
five values to control 24 values may result in some switches not
having the value you want in order that others do have the desired
value, but you can change the variable values so you get what you want
easily enough, as described in
the documentation.

In this note, we discuss the four new switches in release 8.2. The new
switches are:

optimize-large-functions-switch

When this switch is true, the compiler will do its best to optimize
large functions. If this switch is nil, the compiler will detect
certain cases when optimizations are taking too long and stop further
optimization. The exact internal mechanics are complicated and
difficult to explain, so we will not try. The compiler notices that
internal structures are exceeding a certain size (and inferring that
compilation is taking too long). If you notice that compilation takes
much longer than expected, try setting this switch to nil and see if
that speeds things up. Note that when you produce production code, you
might want to take the time to do the fully optimized compilation in
order to deliver fully optimized code.

save-source-level-debug-info-switch

This switch is only relevant when compiling files. It causes the
compiler to annotate the fasl (compiled-lisp) file with information
useful for source-level debugging
(see The
source stepper
in debugging.htm)
and for coverage analysis
(see with-coverage). This
switch can in some cases greatly increase compilation time so you
might turn it off, at least for those files you do not think need
debugging, if compilation speed becomes an issue.

generate-accurate-x86-float-code-switch

This is an interesting issue. Certain 32-bit X86 processor chips have
two modes for certain floating-point calculations, doing 80
calculations or 32/64-bit calculations. Under certain circumstances,
unless certain flags are set, you can get different answers from run
to run, with the differences affecting the lowest bits.

Setting the flags so the calculations always produce the same results
causes a significant slowdown to the code. When this was first
noticed, we overloaded
the declared-fixnums-remain-fixnums-switch
so when that switch was true, we also would not set the flags so
floating-point calculations might differ from run to run as
well. However we recognized that was undesirable so now this new
switch controls setting the flags in floating-point calculations
and declared-fixnums-remain-fixnums-switch
controls fixnum arithmetic only.

People should keep in mind that floating-point calculations are
inherently inaccurate. The inaccuracy introduced by this problem is no
greater than that introduced normally. The amount is magnified by
unstable calculations (such as inverting a matrix whose determinant is
very close to zero) but such calculations are very inaccurate
anyway. (The point is that in such case, you may notice the difference
because it will no longer be only in the lowest bits.) However, it is
true that users are often disturbed when what are apparently the same
calculatiopns produce different answers. It is up to the programmer
whether to have faster programs but occasional slight differences in
results, or slower programs and the same results.

verify-type-declarations-switch

This switch, when true, causes code to be added which verifies
variable type declarations so whenever a variable is bound or set to a
value, that value is checked to be of the declared type. For example,
in the let form, if in the body the variable var is set to a
value which is not a fixnum, an error is signaled:

(let ((var 0))
(declare (fixnum var))
(<body>)
)

Note that this tests inititializations which are not explicit, such as:

The list passed to foo indeed contains fixnums only, so where
is i bound to nil? The specification
for dolist
says that the interation variable is set to nil when the loop is
complete and the return form (the optional third element of the loop
variable binding form) is evaluated, and that form defaults to the
form nil if unsupplied. Therefore, even if you do not specify a return
form, your iteration variable will be set to nil sometime unless the
loop is terminated (by return, for example) before it completes
and the ANS is clear that the scope of the declaration in
the dolist includes the return form, even if that form is not
supplied.

If you have such declarations (and thus find
yourself getting an error), you should either change the declaration,
perhaps to (or nil <previous type specification>), or be sure this
compiler switch is nil when the function containing the dolist
form is compiled. If you want the switch true in general, you can use
this undocumented (for now) utility to set the switch value locally: