binaryen icon indicating copy to clipboard operation
binaryen copied to clipboard

Failure with optimize

Open tshort opened this issue 1 year ago • 8 comments

I'm generating some working WebAssembly code that fails if I try to run the default optimization passes. The code uses WASM GC, and there are no warnings or errors on validation.

What makes me think it might be a bug is that wasm-opt works fine on the un-optimized WASM file I write.

The error message is:

/workspace/srcdir/binaryen/src/passes/LocalCSE.cpp:305: 
void wasm::{anonymous}::Scanner::visitExpression(wasm::Expression*): Assertion `childOriginalRequests > 0' failed.

Any hints on how to debug this? I'm not sure how to produce a minimum working example. The code in question is shown in the examples here.

tshort avatar Oct 31 '23 02:10 tshort

If you have a wasm-opt command that hits that assertion, reducing it to a minimal testcase should be easy with wasm-reduce, https://github.com/WebAssembly/binaryen/wiki/Fuzzing#reducing

Basically, assuming wasm-opt -all -O2 hits that error, then

bin/wasm-reduce start.wasm "--command=bin/wasm-opt -all -O2 test.wasm" -t test.wasm -w work.wasm

kripken avatar Oct 31 '23 02:10 kripken

I haven't found a case where wasm-opt fails. It only fails when calling BinaryenModuleOptimize(mod) with the C API.

tshort avatar Oct 31 '23 10:10 tshort

Perhaps you can save the module before optimization and do a reduction on a small program that loads it and calls BinaryenModuleOptimize? wasm-reduce can be run on any program that reads a wasm file.

kripken avatar Oct 31 '23 15:10 kripken

I tried writing the small program to load a file and then run BinaryenModuleOptimize. I couldn't get that to fail. I can't reproduce the error after reading from a file. Not sure what to try next.

As a workaround, I can write and read the wasm file, optimize, then rewrite it. That's better than shelling out to wasm-opt. Also, BinaryenModuleOptimize doesn't fail if I set the following:

    BinaryenSetShrinkLevel(0)
    BinaryenSetOptimizeLevel(2)

tshort avatar Nov 01 '23 01:11 tshort

Another option for debugging here is to set BINARYEN_PASS_DEBUG=3 in the environment. That will write out a file after each pass. The last pass before that failure should then fail if you run wasm-opt THAT_FILE.wasm --local-cse, that is, running the next pass where you saw the error should continue from that step, and error.

If none of this works for you, if you can provide a reasonably small testcase in any form I can look into it.

kripken avatar Nov 01 '23 16:11 kripken

I didn't have luck with BINARYEN_PASS_DEBUG. I could not reproduce the crash with wasm-opt with any file saved.

I am still not able to get you a great reproducer. I found an interesting work-around. This crashes:

    BinaryenModuleValidate(ctx.mod)
    BinaryenSetShrinkLevel(1)
    BinaryenSetOptimizeLevel(3)
    BinaryenModuleOptimize(ctx.mod)

Using a two-step optimization, the following doesn't crash:

    BinaryenModuleValidate(ctx.mod)
    BinaryenSetShrinkLevel(0)
    BinaryenSetOptimizeLevel(2)
    BinaryenModuleOptimize(ctx.mod)
    BinaryenSetShrinkLevel(1)
    BinaryenSetOptimizeLevel(3)
    BinaryenModuleOptimize(ctx.mod)

I tried adding instrumentation for my code generation to produce more vanilla C-type Binaryen, but I failed at that. Any time I write anything out and read it back in or try wasm-opt, it doesn't crash.

local-cse crashes if I run it right away.

    BinaryenModuleValidate(ctx.mod)
    BinaryenModuleRunPasses(ctx.mod, ["local-cse"], 1)

It doesn't crash if I run other stuff first:

    BinaryenModuleValidate(ctx.mod)
    BinaryenSetShrinkLevel(0)
    BinaryenSetOptimizeLevel(2)
    BinaryenModuleOptimize(ctx.mod)
    BinaryenModuleRunPasses(ctx.mod, ["local-cse"], 1)

I don't know what to try next. Unless someone wants to try out Julia, I haven't come up with a good reproducer. In Julia, the code to reproduce is pretty small.

tshort avatar Nov 08 '23 01:11 tshort

Sounds like running local-cse is the simplest way to crash it. What happens if you print the module before that, then load that text in wasm-opt text.wat --local-cse? (if the issue is related to unreachable code, writing to binary would remove that code and hide the bug, but not text, so there's a chance this will help)

If that doesn't work, that text + a full stack trace (from gdb, that is, the full path to that visitExpression that crashes) might be enough for me to see something curious, if we're lucky (but it would be far better if the crash reproduces on the text).

kripken avatar Nov 08 '23 01:11 kripken

(I unfortunately don't know anything about Julia, so it would probably take much longer for me to try to get that set up to reproduce the problem that way, but if nothing else works out that's an option too... :smile: )

kripken avatar Nov 08 '23 01:11 kripken