-
Notifications
You must be signed in to change notification settings - Fork 777
OptimizeInstructions does not optimize divide by zero #7471
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
Comments
This isn't miscompiled, since it traps in all cases, before optimizations, The difference between 2 and 3 reduces to the difference between these: (module
(type $0 (func))
(import "External" "external_function" (func $external_function))
(export "_start" (func $_start))
(func $_start
(local $x i32)
(if
(i32.div_u
(i32.const 0)
(local.get $x)
)
(then
(call $external_function)
)
)
)
) and (module
(type $0 (func))
(import "External" "external_function" (func $external_function))
(export "_start" (func $_start))
(func $_start
;; the local vanished
(if
(i32.div_u
(i32.const 0)
(i32.const 0) ;; this changed
)
(then
(call $external_function)
)
)
)
)
|
Yes, both of the two optimized results trap. But I am still confused that why O2 could eliminate the branch, because there must be an assumption here: wasm-opt knows the semantics of "i32.eqz (undefined)" is. As you can see in O2 result, it reduces the i32.eqz (undefined) to be true. Is this reasonable? Or maybe I still misunderstand what you mean, thus can you explain it more clearly? |
|
( |
I agree with you. In your provided two cases, the second case should be handled, since the condition is a trap. But I didn't seem to see any rule for handling this. Does there lack a rule for it? |
Yes, this looks like a missing optimization. |
Since there is no rule for this case, would it be proper to add the fix like below in } else if (binary->op == DivUInt32) {
if (Match::matches(binary,
Match::binary(Abstract::DivU,
Match::constant(0),
Match::constant(0)))) {
// Optimize later branch while still preserving trap
return getDroppedChildrenAndAppend(
binary, LiteralUtils::makeZero(Type::i32, *getModule()));
}
} It fixes, however, I'm afraid it might be a bit awkward. Is there any better way? |
I don't think we need to add a new rule for |
Thanks for guidance. The directly issues lies in the following rule for checking whether binary operator emitting zero bits: binaryen/src/passes/OptimizeInstructions.cpp Lines 317 to 323 in e6f1c53
It treats In details, the Lines 194 to 201 in e6f1c53
Is that a missing consideration for |
Yes, that looks like the bug, good find. On line 198, the Would you like to open a PR with that? |
Yes, the result of division cannot have more bits than the dividend ( I've opened a PR as you suggested (with the first solution). |
Given the following code:
The
-O2
producesThe
-O3
produceswasm-opt version: d0d970c
According to the spec, the result of
i32.div_u(num, 0)
is undefined, in this issue, the O2 deduces the result ofi32.eqz (undefined)
to be true thus eliminates the branch, which happens in theinlining-optimizing
.Since division always traps, is there any miscompliation in this O2 optimizing pipeline?
The text was updated successfully, but these errors were encountered: