next up previous contents index
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([]).
ordered([X]).
ordered([X,Y|Z]) :-
X @=< Y, ordered([Y|Z]). $ \longrightarrow$
ordered([]).
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 up previous contents index
Next: Compiler Directives Up: The Compiler Previous: Compiler Options   Contents   Index
Luis Fernando P. de Castro 2003-06-27