Optimization Reference
This reference defines PGO configuration, candidate presets, and advanced compiler controls. Follow the PGO walkthrough for setup and a complete optimization session; use this page to adjust acceptance criteria or investigate a specific transformation.
Configuration
Settings belong under [targets.NAME.optimize] in exaloop.toml.
| Setting | Purpose |
|---|---|
train, tune, holdout | Required, separate lists of executable argument arrays |
inputs | Additional data, imports, verifier scripts, and native dependencies to fingerprint |
presets | Candidate policies; omitted means ["pgo"] |
samples | Paired timing samples; default 7 |
timeout | Per-process timeout in seconds; default 60 |
min_gain | Required lower confidence-bound gain; default 0.03 |
max_regression | Per-case regression limit; default 0.05 |
max_code_growth | Maximum native code-size ratio; default 1.25 |
max_memory_growth | Maximum peak-RSS ratio; default 1.2 |
min_coverage | Minimum profile-match coverage; default 0.95 |
verify | Optional verifier argument array replacing exact output comparison |
The default verifier requires identical stdout and stderr and successful exits.
A custom verifier receives the baseline and candidate stdout filenames appended
to its command. It must return zero only for equivalent results. Declare its
script and dependencies in inputs; see replay safety.
SDK and Session Selection
Use a registered ext SDK or choose an unregistered one with
optimize --sdk /path/to/sdk/ext or EXALOOP_OPTIMIZER_SDK.
doctor --optimization --optimizer-sdk /path/to/sdk/ext --json checks a specific
SDK without starting a target's optimization session.
--budget 10m bounds compilation and process execution for a session; the native
capability probe counts toward it. Fingerprinting and report writing are outside
the budget. --resume SESSION reuses valid artifacts but repeats measurements
and holdout checks. Global --dry-run prints the plan without running the probe;
global --no-open suppresses the dashboard.
Presets
| Build | PGO | Additional Exaloop passes |
|---|---|---|
| Default baseline | No | Normal default inlining and DFA settings |
pgo | Yes | Disabled to isolate LLVM PGO |
compact, balanced, aggressive | Yes | Experimental inlining and DFA policies |
Omitting presets evaluates only pgo. The default optimizer baseline is
retained unless the candidate passes the tuning and holdout gates. To study the
experimental combinations, request them explicitly:
presets = ["pgo", "compact", "balanced", "aggressive"]
Such runs are labeled experimental in the CLI and report. The Exaloop validation matrix established no incremental gain above 3% over PGO-only across its five workloads; preset search is not the default strategy. Profile-cold calls do not consume extra inline trials, and late reconsideration prioritizes hotter sites. Numerical semantics and legality rules are unchanged.
Older reports used a baseline with both extra passes disabled. They are not directly comparable with the current default-optimizer baseline; inspect each report's baseline label. Changed CLI fingerprints invalidate session reuse.
Additional Compiler Passes
You can use the compiler passes without a PGO session. Choose an SDK matching your compiler and LLVM build:
OPT_SDK=/path/to/sdk/ext
codon build -release -plugin "$OPT_SDK" -o program program.codon
./program
Context-sensitive inlining and DFA jump threading are enabled by default for release builds. Debug builds load the plugin without enabling these passes. There is no Codon module to import or optimizer runtime library to deploy.
Controls
| Control | Default / behavior |
|---|---|
CODON_EXT_INLINE | Unset = 1; contextual inlining and late reconsideration |
CODON_EXT_DFA | Unset = 1; late DFA jump threading |
-enable-dfa-jump-thread=false | Explicit LLVM disable takes precedence |
-enable-dfa-jump-thread=true | LLVM controls enablement; plugin avoids duplicate insertion |
CODON_EXT_INLINE_GROWTH | Added-instruction budget per caller: 512, maximum 16384 |
CODON_EXT_INLINE_TRIALS | Trial budget: 128, maximum 4096 |
CODON_EXT_INLINE_WORK | Estimated-work budget: 262144, maximum 16777216 |
Set environment controls when invoking the compiler, not the finished binary.
The two pass switches accept 0 or 1; other values are rejected in release
compilation. Explicit LLVM DFA flags take precedence over plugin defaults.
Compare a Build
Build the same source with a plain compiler, a disabled plugin, each individual pass, and the default combination. Check outputs before comparing timings:
codon build -release -o baseline program.codon
CODON_EXT_INLINE=0 CODON_EXT_DFA=0 \
codon build -release -plugin "$OPT_SDK" -o disabled program.codon
CODON_EXT_INLINE=1 CODON_EXT_DFA=0 \
codon build -release -plugin "$OPT_SDK" -o inline-only program.codon
CODON_EXT_INLINE=0 CODON_EXT_DFA=1 \
codon build -release -plugin "$OPT_SDK" -o dfa-only program.codon
codon build -release -plugin "$OPT_SDK" -o enabled program.codon
The disabled build isolates pipeline changes unrelated to the two passes. To
investigate an effect, emit LLVM IR with -llvm and compare calls, allocations,
switches, and loops. Fewer instructions do not establish a runtime gain; record
compilation time and native code size too. Use the
profiler to investigate the affected execution paths.
Context-Sensitive Inlining
LLVM's normal inliner estimates a call's benefit before changing it. This plugin adds a trial for selected calls above the normal cost threshold: clone the caller, inline, simplify, and compare instruction counts. Candidates include constant arguments and small call groups sharing a noncaptured stack allocation. Two cleanup rounds run scalar replacement, mem2reg, early CSE, SCCP, instruction combining, control-flow simplification, and dead-code elimination.
An inline is accepted when the cleaned caller does not grow, or when enough materialized instructions disappear within the growth budget. These are static heuristics, not a performance oracle. A late pass tries coroutine-frame elision and reconsiders calls in singleton call-graph components, which can simplify generator state machines.
| Fixed implementation limit | Value |
|---|---|
| Caller instructions | 1,500 |
| Callee instructions | 400 |
| Calls in a shared-allocation group | 4 |
The configurable budgets are listed above. The pass respects @noinline and LLVM
legality checks; it excludes direct recursion, presplit coroutine callees,
size-optimized callers, and protected JIT/kernel functions. It does not turn
indirect calls into direct calls. Remarks use codon-ext-inline / Trial.
DFA Jump Threading
DFA jump threading simplifies control flow when possible state transitions are known. The plugin runs LLVM's existing pass late in scalar optimization, after other simplifications can expose transitions. Some generator-derived loops benefit; not every switch can be eliminated. Late coroutine and DFA passes run at optimization levels intended for speed.
Low-Level PGO Controls
The CLI manages these for ordinary PGO sessions. They are exposed for tooling and compiler experiments:
| Control | Meaning |
|---|---|
CODON_EXT_PGO_GENERATE=1 | Instrument a release build; link the SDK profile runtime |
CODON_EXT_PGO_USE=FILE | Load an indexed profile; mutually exclusive with generation |
CODON_EXT_PGO_REPORT=FILE | Write function-profile match and execution coverage |
Generation/use occurs once at the first LLVM pipeline-start checkpoint. Codon's second O3 run preserves counter metadata and regenerates derived call-graph profile metadata. The LLVM matcher diagnoses function/hash mismatches; coverage distinguishes matched zero-count functions from executed functions. Available inline remarks and per-candidate coverage appear in the report.
The supplied SDK includes the matching profile runtime and exaloop-profdata
merger. exaloop doctor --optimization checks that these components work with
the active compiler before a tuning session begins.