Skip to content

compiler: emit i64.eqz for zero-equality comparisons in WAT codegen#113

Merged
yevbar merged 1 commit intomasterfrom
happy/eqz-peephole
Mar 1, 2026
Merged

compiler: emit i64.eqz for zero-equality comparisons in WAT codegen#113
yevbar merged 1 commit intomasterfrom
happy/eqz-peephole

Conversation

@yevbar
Copy link
Copy Markdown
Contributor

@yevbar yevbar commented Mar 1, 2026

Summary

Add a peephole optimization to the WAT code generator that emits the i64.eqz instruction when comparing an i64 expression against literal 0 for equality. This saves one instruction (i64.const 0) per zero-comparison in the generated WASM binary.

What changed

WAT code generator (lib/firebird/compiler/wat_gen.ex):

  • Added peephole patterns for {:binop, :eq, expr, {:literal, 0}} and {:binop, :eq, {:literal, 0}, expr} that emit i64.eqz instead of i64.const 0; i64.eq
  • Applied same optimization to case clause pattern matching against literal 0 (both normal and TCO paths)
  • Extracted generate_binop_expr/7 helper for peephole fallback

Before / After

;; Before (3 stack ops):
local.get $x
i64.const 0
i64.eq

;; After (2 stack ops):
local.get $x
i64.eqz

Impact

This pattern appears in:

  • Boolean/zero checks: if x == 0
  • Case dispatch: case x do 0 -> ... end
  • Guard conditions and parity tests (rem(n,2) == 0 after strength reduction becomes band(n,1) == 0)
  • Collatz-style algorithms, factorial base cases, etc.

Tests

  • 7 new tests in test/compiler/eqz_peephole_test.exs covering WAT output verification, commutative patterns, case expressions, optimized mode, and WASM binary validity
  • Updated existing wat_gen_edge_cases_test.exs to expect i64.eqz for pattern-0 cases
  • Full test suite passes (9379 tests, only pre-existing xmerl env failure)

…egen

Add a peephole optimization to the WAT code generator that emits the
i64.eqz instruction when comparing an i64 expression against literal 0
for equality. This saves one instruction (i64.const 0) in generated WASM.

The optimization applies in three code paths:
- General binop expressions: {:binop, :eq, expr, {:literal, 0}}
- Case clause pattern matching: {:literal_pat, 0}
- TCO case clause pattern matching: {:literal_pat, 0} in tail position

Before (3 stack operations):
  local.get $x
  i64.const 0
  i64.eq

After (2 stack operations):
  local.get $x
  i64.eqz

This pattern is extremely common in:
- Boolean/zero checks: if x == 0
- Case dispatch with literal 0 patterns
- Guard conditions and parity tests (rem(n,2) == 0 after strength reduction)

Also extracts generate_binop_expr/7 helper for peephole fallback paths.
@yevbar yevbar merged commit 16ab588 into master Mar 1, 2026
4 checks passed
@yevbar yevbar deleted the happy/eqz-peephole branch March 1, 2026 07:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant