Optimizer hints
Hints tell the optimizer what it cannot see in the code. A hint never changes what a program computes, only how fast it runs, so a wrong hint costs speed and nothing else.
- Which way a branch goes: write
[Likely]or[Unlikely]above theiformatcharm (see branch hints). - A function rarely called:
[Cold]above it (see cold functions). - Memory a loop will soon touch: the
hintmodule’s prefetches.
| Function | Tells the optimizer |
|---|---|
hint.prefetch_read(address) | address will be read soon: start loading its cache line now. |
hint.prefetch_write(address) | address will be written soon. |
A prefetch never faults, even for an address that is not mapped, and does nothing where the CPU has no prefetch instruction.
# Prefetching: start loading memory a loop will soon read.
import hint;
main(): int {
var text = "a long text that a loop will read";
hint.prefetch_read(text.c_str());
var spaces = 0;
for (var index in 0..text.length) {
if (text.byte_at(index) == ' ') {
spaces += 1;
}
}
assert(spaces == 7, "a hint changes nothing the program computes");
return 0;
}
The prefetches are LLVM’s llvm.prefetch intrinsic (see
LLVM intrinsics). They matter only with
optimization (-O2 and up, where the runtime’s functions inline into the
caller); at -O0 they cost a call and do nothing.
Cold functions
[Cold] above a function, method or constructor marks it rarely called:
the optimizer never inlines it and treats a call to it as the unlikely
side of a branch. Split the rare work out of a hot function into a [Cold]
one, so the hot function stays small enough to inline into its callers:
# A hot method with its rare work split out into a [Cold] one.
struct Counter {
var count: int;
var wraps: int;
construct() {
count = 0;
wraps = 0;
}
# Called on every event: small enough to inline.
add() {
if (count == 1000) {
_wrap();
}
count += 1;
}
# Called once per thousand events: kept out of line.
[Cold]
_wrap() {
count = 0;
wraps += 1;
}
}
main(): int {
var counter = Counter();
for (var index in 0..2500) {
counter.add();
}
assert(counter.wraps == 2 && counter.count == 500, "[Cold] changes nothing the program computes");
return 0;
}
[Cold] is LLVM’s cold and noinline function attributes. The runtime’s
allocator marks its slow paths this way.
Deprecated hints
hint.likely(condition) and hint.unlikely(condition) are deprecated:
each use warns and suggests the attribute.