Next: OIL Loops, Previous: OIL Patterns, Up: Optimizer Idiom Language [Index]
Replacements have much the same syntax as patterns. The expressions are
parsed in much the same way; however, one peculiarity of replacements
is that bitwidths must be specified. INTERCAL has a
typecaster that figures out whether each expression is 16 bits or 32
bits wide, but it runs before the optimizer, and as the optimizer can
produce expressions whose bitwidths don’t obey
INTERCAL’s rules, this information needs to be
inserted somehow in a replacement. In C-INTERCAL, it
usually doesn’t matter what the bitwidth is, and in cases where
it doesn’t matter the normal operators ($
,
~
, and so on) can be used. (The bitwidth of the entire
replacement may be different from the bitwidth of the original, thus
leading to, say, a 32-bit unary logical operation applied to a
“16-bit” argument; but this is not a problem, as it just
means that there’s an implied typecast in there somewhere.) In
cases where it does matter (due to C-INTERCAL’s
lenient interpretation of bitwidth on mingle inputs, the only place it
matters is in the input to INTERCAL unary logical
operators), both the bitwidth of the operator and the argument on which
it operates must be explicitly given, and given as the same value; to
set the bitwidth of an operator’s result, simply write the
bitwidth (16 or 32 for onespot and twospot respectively) immediately
after the operator; for instance, !=32
will generate a
not-equals operation with a 32-bit bitwidth. If an operator’s
width is set to 16, and during the course of execution of the optimized
program, a value that doesn’t fit into 16 bits is encountered,
that’s undefined behaviour and anything might happen (most
likely, though, the program will just act as though its width had been
set to 32 bits instead); this error condition is not detected. Also
note that operators like &32
already have a bitwidth
specified, so specifying &3232
(or worse,
&3216
) is not allowed.
Replacement operands are simpler than pattern operands, because there are only a few forms they can take.
_NUMBER
.NUMBER
:NUMBER
This tells the optimiser to copy the operand or expression with
reference number NUMBER to this point in the replacement
used for the expression matched by the pattern. The three forms are
identical; the last two are provided for aesthetic reasons (it can
look better and be clearer to match .1
in the pattern
with .1
in the replacement, for instance). You cannot
use #NUMBER
here to copy in a constant from
the left-hand side, though, nor #{1}NUMBER
,
because the first means something else and the second is undefined
behaviour (that is, no behaviour for the second case has been
specifically implemented in the compiler and therefore its
behaviour is unpredictable and subject to change in future
versions); use _NUMBER
to copy over a
constant with an unknown at optimizer compile time (but known at
optimize time) value from the left hand side, as you can do with
any other operand being copied.
#NUMBER
Insert a constant with the literal value NUMBER here.
#{EXPRESSION}0
Calculate the value of EXPRESSION (a C expression, which can reference the same variables and functions as a C expression in a pattern can; see C functions in OIL) and insert a constant with the calculated value here. (That is, a value is calculated at optimise-time and the resulting value is therefore constant at runtime.)
As an example, here’s an idiom that moves C bitwise AND operations inside leftshifts. (This is useful because if the optimizer has generated a large sequence of mixed ANDs and bitshifts, moving all the ANDs to one end allows them to be clumped together and optimized down to one AND, whilst the shifts can all be combined into one large shift.)
((_1 << #{1}2) & #{1}3)->((_1 & #{x3>>x2}0) << _2)
Next: OIL Loops, Previous: OIL Patterns, Up: Optimizer Idiom Language [Index]