Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect optimizer result with if parameter #5950

Closed
camilstaps opened this issue Sep 17, 2023 · 6 comments
Closed

Incorrect optimizer result with if parameter #5950

camilstaps opened this issue Sep 17, 2023 · 6 comments

Comments

@camilstaps
Copy link

camilstaps commented Sep 17, 2023

The following program:

(module
	(func $f (export "f") (param $x i32) (param $y i32) (result i32)
		local.get $x

		local.get $y
		if (param i32)
			return
		else
			drop
			local.get $y
			return
		end
		unreachable
	)
)

is optimized to:

(module
 (type $0 (func (param i32 i32) (result i32)))
 (export "f" (func $0))
 (func $0 (param $0 i32) (param $1 i32) (result i32)
  (drop
   (return
    (local.get $0)
   )
  )
  (if
   (local.get $1)
   (block
   )
   (block
   )
  )
  (unreachable)
 )
)

by

wat2wasm weird.wat && wasm-merge -S weird.wasm bug --output=-

and the function body becomes simply (local.get $0) with wasmopt -O.

I am surprised by the fact that the return and return_call are lifted out of the if block. This does not happen when the local.get $x is moved inside both if alternatives and the if does not take a parameter.

With the original module, the following tests pass, but they fail with the binaryen output, so I think this is a bug:

(assert_return (invoke "f" (i32.const 100) (i32.const 1)) (i32.const 100))
(assert_return (invoke "f" (i32.const 100) (i32.const 0)) (i32.const 0))

This is on the current main (16a5993).

@camilstaps camilstaps changed the title Unexpected optimizer result with if parameter Incorrect optimizer result with if parameter Sep 17, 2023
@kripken
Copy link
Member

kripken commented Sep 18, 2023

Looks like a binary parsing error, which I think is because of Binaryen's lack of support for multivalue input params to control flow structures.

We should probably error on any such control flow structures?

@camilstaps
Copy link
Author

@kripken Thanks. An error would have been helpful, yes.

When I add the --enable-multivalue flag to the wasm-merge call the result is the same, though. Is multi-value not fully implemented? wasm-merge --help says it enables "multivalue functions", should I interpret that as support for multi-valued return but not control flow structure parameters? If so, it may be useful to clarify that as well. I had read the readme and #663, but when I saw --enable-multivalue just assumed they were outdated.

Are there any plans for supporting control flow structure parameters? (I originally wanted to use LLVM's wasm-ld instead of wasm-merge for reasons like this, but came back to wasm-merge because wasm-ld doesn't fully support tables.)

@kripken
Copy link
Member

kripken commented Sep 19, 2023

Yes, I think "multivalue functions" is meant to indicate that the support is only present for function returns and calls of such functions (and the result of inlining such things). I agree that might not be clear enough. Really we should have an error in the binary parser for this. I'll try to look into that.

I think our plan is to support parsing of control flow inputs with the new wasm parser @tlively is working on? That should fix correctness at least, though optimization would take more work. Note that in general this is not a top priority for us as the benefits of such code are minor, 1-2% at best, so there are better things to focus on.

@tlively
Copy link
Member

tlively commented Sep 19, 2023

I wasn't planning on it before, but yes, the new wat parser and associated IRBuilder should make it much more feasible to support parsing multivalue control structures from binary and text. We'll be replacing the input parameters with locals, though, unless we decide to make larger changes to Binaryen IR.

kripken added a commit that referenced this issue Sep 20, 2023
Before in getType() we silently dropped the params of a signature type. Now we verify that
it is none, or we error.

Helps #5950
@camilstaps
Copy link
Author

Thanks both, and thanks for the new error! I’ll leave it up to you if you want to leave this issue open.

@tlively
Copy link
Member

tlively commented Apr 15, 2024

Closing this in favor of #6407.

@tlively tlively closed this as not planned Won't fix, can't repro, duplicate, stale Apr 15, 2024
radekdoulik pushed a commit to dotnet/binaryen that referenced this issue Jul 12, 2024
Before in getType() we silently dropped the params of a signature type. Now we verify that
it is none, or we error.

Helps WebAssembly#5950
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

No branches or pull requests

3 participants