binaryen icon indicating copy to clipboard operation
binaryen copied to clipboard

[NFC] DeadArgumentElimination: Update allCalls incrementally

Open kripken opened this issue 1 month ago • 1 comments

Rather than recompute the entire map of Call instructions to each target, keep it around between iterations, and just update the changed part. This requires us to track the origin of each call, so we know which data is old and stale.

This makes the pass 15% faster on some Dart and C++ testcases, and 9% faster on Kotlin and Java. On Dart this is also the slowest pass in -O3, making us overall 3% faster.

kripken avatar Dec 02 '25 23:12 kripken

Fuzzer found an issue, so converting to draft. It turns out that we Refinalize internally, and that can remove (unreachable) calls. That makes this hang on dae-optimizing:

(module
 (rec
  (type $0 (func))
  (type $1 (func (param (ref $2)) (result f32)))
  (type $2 (struct (field (mut externref))))
  (type $3 (func (result v128)))
 )
 (func $0 (type $3) (result v128)
  (drop
   (call_ref $1
    (struct.new $2
     (ref.as_non_null
      (ref.null noextern)
     )
    )
    (ref.func $1)
   )
  )
  (v128.const i32x4 0x00000000 0x00000000 0x00000000 0x00000000)
 )
 (func $1 (type $1) (param $0 (ref $2)) (result f32)
  (unreachable)
 )
 (func $2 (type $0)
  (drop
   (call $0)
  )
 )
)

We are not aware that Refinalize causes changes, so we miss the call going away, and end up confused.

Tracking Refinalize may be enough, perhaps in a separate PR.

kripken avatar Dec 03 '25 16:12 kripken