Whetstone logo

Rust · no LLVM · no black box

Watch the optimizer
think, one pass at a time.

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.

Try it in your browser View on GitHub
How to use this playground
Paste a small three-address IR into the box, or pick a sample chip, then press Optimize. Whetstone runs its four passes (constant folding, constant propagation, algebraic simplification, dead code elimination) over and over to a fixed point, and shows the Original next to the Optimized program. Below them, every fold, propagation, simplification, and removal is listed in pipeline order, so you can see exactly what each pass did and how one pass exposed work for the next. One instruction per line: dst = value op value or print reg. This is a direct port of the Rust parser and passes.
Paste IR, or use a sample

Original

Optimized

runs fully client-side, nothing leaves the page, a direct port of the same parser and passes as the Rust CLI

Four passes, run to a fixed point.

Fold, propagate, simplify, eliminate, repeat. A round that changes nothing ends the pipeline, capped hard so a strange input still always terminates.

1

Constant folding

A binary operation over two literals is replaced by the single computed constant. Division by zero is left unfolded on purpose.

2

Constant propagation

A forward scan tracks which registers currently hold a known constant, and substitutes it at every later use.

3

Algebraic simplification

Identities like x * 1, x + 0, and x * 0 collapse without needing either side to be a literal.

4

Dead code elimination

A backward liveness scan drops any assignment whose result is never read again and that has no side effect.

Built to be read, not just run.

Inside a real compiler

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.

Whetstone

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)

Read it, run it, test it.

Text in, text out. The IR is one instruction per line, and every surface is the same parser and passes.

The IR

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.

Optimize

whetstone opt prog.ir prints the optimized program, then lists every fold, propagation, simplification, and removal in pipeline order on stderr.

Show every pass

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.

Build and test

cargo build and cargo test. The browser demo above is a direct port of the same Rust parser and passes.