Previous Up Next

6.7  Inlining

To improve efficiency, calls to user-defined predicates can be preprocessed and transformed at compile time. The directive inline/2, e.g.
:- inline(mypred/1, mytranspred/2).
arranges for mytranspred/2 to be invoked at compile time for each call to the predicate mypred/1 before this call is being compiled.

The transformation predicate receives the original call to mypred/1 as its first argument, and is expected to return a replacement goal in its second argument. This replacement goal replaces the original call in the compiled code. Usually, the replacement goal would be semantically equivalent, but more efficient than the original goal. When the transformation predicate fails, the original goal is not replaced.

Typically, a predicate would be defined together with the corresponding inlining transformation predicate, e.g.
:- inline(double/2, trans_double/2).

double(X, Y) :-
        Y is 2*X.

trans_double(double(X, Y), Y=Result) :-
        not nonground(X),    % if X already known at compile time:
        Result is 2*X.       % do calculation at compile time!
All compiled calls to double/2 will now be preprocessed by being passed to trans_double/2. E.g. if we now compile the following predicate involving double/2
sample :-
        double(12,Y), ...,  double(Y,Z).
the first call to double will be replaced by Y=24 while the second one will be unaffected. The code that the compiler sees and compiles is therefore
sample :-
        Y=24, ...,  double(Y,Z).
Note that meta-calls (e.g. via call/1) are never preprocessed, they always go directly to the definition of double/2.

Transformation can be disabled for debugging purposes by adding
:- pragma(noexpand).
to the compiled file, or by setting the global flag
:- set_flag(goal_expansion, off).

Previous Up Next