Next: , Previous: , Up: Optimizer Idiom Language   [Index]


C.5 OIL Replacements

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: , Previous: , Up: Optimizer Idiom Language   [Index]