Skip to content

Optimize instructions tee get relational 7672 - #9148

Open
ArkadySkv wants to merge 2 commits into
WebAssembly:mainfrom
ArkadySkv:optimize-instructions-tee-get-relational-7672
Open

ArkadySkv wants to merge 2 commits into
WebAssembly:mainfrom
ArkadySkv:optimize-instructions-tee-get-relational-7672

Conversation

@ArkadySkv

Copy link
Copy Markdown
Contributor

Problem: LocalCSE rewrites repeated subexpressions as a local.tee
followed by a local.get. When the two operands of a relational
comparison are exactly such a pair, OptimizeInstructions did not
recognize them as equal, so the comparison survived into the -O3
output and blocked dead-code elimination. The reproduction in #7672
is a module where (i32.gt_s (local.tee $0 X) (local.get $0))
should fold to a constant.

Fix: Add a fold at the top of optimizeRelational in
src/passes/OptimizeInstructions.cpp. The pass already has a helper
(areMatchingTeeAndGet) that recognizes the tee/get pattern; it was
consulted in the RefEq and Select handlers but not in the
relational path. The fold evaluates X once for its side effects,
drops it, and returns the constant result (gt/lt/ne -> 0,
ge/le/eq -> 1). It does not duplicate X, which matters when
X can trap — the reproduction is a chain of loads.

Verification:

  • New lit test test/lit/passes/optimize-instructions-tee-get-comparison.wast
    exercises the tee/get fold in isolation.
  • python3 check.py lit passes (1002 tests).
  • On the SimplifyLocals causes ineffective code #7672 reproducer, -O3 output contains zero local.tee and
    zero i32.gt_s (both greps return 0); before the fix, both returned 1.

Fixes #7672.

Fixes WebAssembly#7672.

`LocalCSE` rewrites repeated subexpressions as a `local.tee` followed
by a `local.get`, so two identical operands to a relational comparison
can reach `OptimizeInstructions` as
`(rel (local.tee $n X) (local.get $n))`. The pass has a helper for
exactly this shape (`areMatchingTeeAndGet`) but consults it only in
the `RefEq` and `Select` handlers, not in `optimizeRelational`. The
comparison survives into the `-O3` output and blocks subsequent
dead-code elimination.

Add the fold at the top of `optimizeRelational`. The result of a
self-comparison is a constant (`gt`/`lt`/`ne` -> 0, `ge`/`le`/`eq`
-> 1). X is evaluated once for its side effects and then dropped, so
the reproduction's load chain preserves its original trap behavior.

Refs WebAssembly#6719 -- the drop-before-unreachable fix that made the residual
`drop; unreachable` visible in the issue's output.
@ArkadySkv
ArkadySkv requested a review from a team as a code owner September 23, 2026 07:59
@ArkadySkv
ArkadySkv requested review from aheejin and removed request for a team September 23, 2026 07:59

This branch has not been deployed

No deployments
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.

SimplifyLocals causes ineffective code

1 participant