Next: Compiler Directives
Up: The Compiler
Previous: Compiler Options
  Contents
  Index
Specialization
From Version 1.4.0 on, the XSB compiler automatically performs
specialization of partially instantiated calls. Specialization can be
thought as a source-level program transformation of a program to a
residual program in which partially instantiated calls to predicates
in the original program are replaced with calls to specialized versions
of these predicates. The expectation from this process is that the
calls in the residual program can be executed more efficiently that
their non-specialized counterparts. This expectation is justified
mainly because of the following two basic properties of the
specialization algorithm:
- Compile-time Clause Selection
- The specialized calls of the
residual program directly select (at compile time) a subset
containing only the clauses that the corresponding calls of the
original program would otherwise have to examine during their
execution (at run time). By doing so, laying down unnecessary
choice points is at least partly avoided, and so is the need to
select clauses through some sort of indexing.
- Factoring of Common Subterms
- Non-variable subterms of partially
instantiated calls that are common with subterms in the heads
of the selected clauses are factored out from these terms
during the specialization process. As a result, some head
unification (get_* or unify_*) and some argument
register (put_*) WAM instructions of the original
program become unnecessary. These instructions are eliminated
from both the specialized calls as well as from the specialized
versions of the predicates.
Though these properties are sufficient to get the idea behind
specialization, the actual specialization performed by the XSB
compiler can be better understood by the following example. The
example shows the specialization of a predicate that checks if a list
of HiLog terms is ordered:
| | |
ordered([X]). | | |
ordered([X,Y|Z]) :- | | |
X @=< Y, ordered([Y|Z]).
|
|
|
ordered([X]). | | |
ordered([X,Y|Z]) :- | | |
X @=< Y, _$ordered(Y, Z). | | |
| | |
:- index _$ordered/2-2. | | |
_$ordered(X, []). | | |
_$ordered(X, [Y|Z]) :- | | |
X @=< Y, _$ordered(Y, Z).
| | |
The transformation (driven by the partially instantiated call
ordered([Y|Z])) effectively allows predicate ordered/2
to be completely deterministic (when used with a proper list as its
argument), and to not use any unnecessary heap-space for its
execution. We note that appropriate :- index directives are
automatically generated by the XSB compiler for all specialized
versions of predicates.
The default specialization of partially instantiated calls is without
any folding of the clauses that the calls select. Using the spec_repr compiler option (see Section 3.8.2)
specialization with replacement of the selected clauses with the
representative of these clauses is performed. Using this compiler
option, predicate ordered/2 above would be specialized as follows:
ordered([]).
ordered([X|Y]) :- _$ordered(X, Y).
:- index _$ordered/2-2.
_$ordered(X, []).
_$ordered(X, [Y|Z]) :- X @=< Y, _$ordered(Y, Z).
|
We note that in the presense of cuts or side-effects, the code
replacement operation is not always sound, i.e. there are cases when
the original and the residual program are not computationally equivalent
(with respect to the answer substitution semantics). The compiler
checks for sufficient (but not necessary) conditions that guarantee
computational equivalence, and if these conditions are not met,
specialization is not performed for the violating calls.
The XSB compiler prints out messages whenever it specialises
calls to some predicate. For example, while compiling a file
containing predicate ordered/1 above, the compiler would print
out the following message:
% Specialising partially instantiated calls to ordered/1
The user may examine the result of the specialization transformation
by using the spec_dump compiler option
(see Section 3.8.2).
Finally, we have to mention that for technical reasons beyond the scope of
this document, specialization cannot be transparent to the user; predicates
created by the transformation do appear during tracing.
Next: Compiler Directives
Up: The Compiler
Previous: Compiler Options
  Contents
  Index
Luis Fernando P. de Castro
2003-06-27