Rust · no LLVM · no black box
Whetstone is a compiler optimizer in Rust built around a small, readable intermediate representation. Constant folding, constant propagation, algebraic simplification, and dead code elimination each transform the IR in the open, before and after, round by round to a fixed point.
dst = value op value or print reg. This is a direct port of the Rust parser and passes.
runs fully client-side, nothing leaves the page, a direct port of the same parser and passes as the Rust CLI
Fold, propagate, simplify, eliminate, repeat. A round that changes nothing ends the pipeline, capped hard so a strange input still always terminates.
A binary operation over two literals is replaced by the single computed constant. Division by zero is left unfolded on purpose.
A forward scan tracks which registers currently hold a known constant, and substitutes it at every later use.
Identities like x * 1, x + 0, and x * 0 collapse without needing either side to be a literal.
A backward liveness scan drops any assignment whose result is never read again and that has no side effect.
The optimizer is usually a pipeline of hundreds of passes buried in a much larger codebase, tuned for speed, not for a reader trying to understand one transform at a time.
A small IR, four passes, and a --show-passes flag that prints the before and after of every round. The same logic, ported line for line, runs in the demo above.
# before/after of every pass, round by round
whetstone opt prog.ir --show-passes
$ whetstone opt prog.ir t4 = x print t4 print 21 changes: constant folding: `t1 = 2 + 3` -> `t1 = 5` constant propagation: `t2 = t1 * 4` -> `t2 = 5 * 4` algebraic simplification: `t3 = t2 + 0` -> `t3 = t2` algebraic simplification: `t4 = x * 1` -> `t4 = x` algebraic simplification: `t5 = x * 0` -> `t5 = 0` dead code elimination: removed `t1 = 5` (result never used) dead code elimination: removed `t5 = 0` (result never used) constant folding: `t2 = 5 * 4` -> `t2 = 20` constant propagation: `t3 = t2` -> `t3 = 20` constant propagation: `t6 = t3 + 1` -> `t6 = 20 + 1` dead code elimination: removed `t2 = 20` (result never used) dead code elimination: removed `t3 = 20` (result never used) constant folding: `t6 = 20 + 1` -> `t6 = 21` constant propagation: `print t6` -> `print 21` dead code elimination: removed `t6 = 21` (result never used)
Text in, text out. The IR is one instruction per line, and every surface is the same parser and passes.
One instruction per line: dst = value, dst = value op value, or print value. Operators are + - * / and the comparisons. Blank lines and # comments are ignored, and bad input is a typed parse error with a line number, never a panic.
whetstone opt prog.ir prints the optimized program, then lists every fold, propagation, simplification, and removal in pipeline order on stderr.
whetstone opt prog.ir --show-passes prints the before and after of each pass that changed something, round by round, ending at the fixed point.
cargo build and cargo test. The browser demo above is a direct port of the same Rust parser and passes.