optimizer
Talk-artifact Ruby optimizer. Companion to
docs/superpowers/specs/2026-04-19-optimizer.md.
Status
- Binary codec: round-trippable decoder/encoder for YARB binaries.
Modifications to
IR::Function#instructionsare re-encoded including length changes — passes can freely insert, delete, or replace instructions.IR::Functionalso carries decoded#catch_entries,#line_entries, and#arg_positionswhose references to instructions are by identity, so they survive instruction-list mutation; the encoder resolves identity to current positions at emit time. - IR:
IR::Function(one per iseq),IR::Instruction(one per YARV op),IR::BasicBlockandIR::CFGfor control-flow analysis. - Passes: base class (
Optimize::Pass), orchestrator (Optimize::Pipeline), hardcoded contract (Optimize::Contract), structured log (Optimize::Log). ANoopPassships as proof-of-life. Real passes come in subsequent plans. - Type env:
Optimize::RbsParserextracts inline@rbssignatures;Optimize::TypeEnvexposes#signature_for. - Harness:
Optimize::Harness::LoadIseqHookinstalls aload_iseqoverride that runs the pipeline on every loaded file. Opt out with# rbs-optimize: falseat the top of the file. Any failure falls back to MRI's built-in compilation.
Passes
Optimize::Passes::ArithReassocPass— arithmetic reassociation driven by theREASSOC_GROUPStable. Two groups today: the additive group (opt_plusidentity 0,opt_minuswith sign-, primaryopt_plus, kind:abelian) and the multiplicative group (opt_multidentity 1,opt_divsecondary, primaryopt_mult, kind:ordered). The:abelianalgorithm partitions non-literal operands by effective sign and injects literals through a single combiner. The:orderedalgorithm walks the chain left-to-right with a single literal accumulator, coalescing contiguous same-op literal runs (* L1 * L2or/ L1 / L2) but refusing to fold across a*//boundary — required because Ruby integer/is floor-division, so(a * L1) / L2 ≠ a * (L1 / L2)in general. Reaches shapes const-fold cannot:x + 1 + 2 + 3→x + 6,x + 1 - 2 + 3→x + 2,x * 2 * 3 * 4→x * 24,x + 1 - y + 2→x - y + 3,x / 2 / 3→x / 6,x * 2 * 3 / 4 / 5→x * 6 / 20. Non-Integer literals, chains with <2 integer literals, results that would exceed theObjectTable#internrange, additive chains where all non-literals have effective sign-, multiplicative chains with any≤0literal divisor, and multiplicative chains whose walk produces no fold are left alone (:mixed_literal_types,:chain_too_short,:would_exceed_intern_range,:no_positive_nonliteral,:unsafe_divisor,:no_change). An outer any-rewrite fixpoint wraps the per-group inner fixpoints so mult rewrites expose additive chains (e.g.,x + 2 * 3 - 4→x + 2).**and exact-divisibility folds (e.g.x * 6 / 2 → x * 3) are out of scope; see follow-up plans.Optimize::Passes::ConstFoldPass— tier 1 constant folding. Folds Integer literal arithmetic (+ - * / %) and Integer literal comparison (< <= > >= == !=) triples within a basic block, iterating until no more folds fire. Division/modulo by zero and non-Integer literal operands are left alone and logged (:would_raise,:non_integer_literal). The default pipeline runsConstFoldPassonly; inlining, arithmetic specialization, and higher tiers of const-fold are future plans.Optimize::Passes::IdentityElimPass— strips arithmetic identities the upstream passes leave behind:x * 1,1 * x,x + 0,0 + x,x - 0,x / 1. Driven by theIDENTITY_OPStable, which encodes each operator's identity element and which sides are eligible (:eitherfor commutative+/*,:rightonly for-//since0 - x = -xand1 / x ≠ x). Fires only when the non-literal side is inSAFE_PRODUCER_OPCODES(shared withArithReassocPass), so no potentially-side-effecting producer (asend,invokesuper, etc.) is ever elided. Integer-literal-only:x * 1.0is left alone (float identities have-0.0/NaNedge cases worth their own pass). The pass is sound in practice, not sound in principle: for a receiver whose class does not treat the operator as an identity (e.g."abc" + 0raisesTypeError;[1,2] * 1returns a copy), eliding the op changes observable behavior. We take the same bet CRuby'sopt_*fast paths take — numeric operands, specialized shape. Completes the three-pass collapse for2 * 3 / 6 * x→x.
Running tests
Tests run inside a Ruby 4.0.2 Docker container via the repo's MCP server
(see mcp-server/). From a Claude Code session, use the
mcp__ruby-bytecode__run_optimizer_tests tool.
Or, on a host with Ruby 4.0.2 and Docker:
cd optimizer
bundle install
bundle exec rake test
Layout
lib/optimize/codec/— YARB binary surgerylib/optimize/ir/—Function,Instruction,BasicBlock,CFGlib/optimize/pass.rb— Pass base class + NoopPasslib/optimize/pipeline.rb— pass orchestrationlib/optimize/contract.rb— the hardcoded ground ruleslib/optimize/log.rb— structured optimizer loglib/optimize/rbs_parser.rb— inline@rbsextractionlib/optimize/type_env.rb— typed-environment querieslib/optimize/harness.rb—load_iseqoverridetest/— minitest suites, fixtures undertest/harness_fixtures/
The round-trip contract
For any iseq produced by RubyVM::InstructionSequence#to_binary:
encode(decode(bin)) == bin (byte-identical)
Any input that doesn't round-trip is a codec bug. Modifications to the decoded IR are applied on re-encode via IR-driven serialization of the body record and data regions; length-changing edits cascade through the header and object-table offsets automatically.