bongjunj opened PR #11994 from bongjunj:mul_ne_eqv_ne_div to bytecodealliance:main:
<!--
Please make sure you include the following information:
If this work has been discussed elsewhere, please include a link to that
conversation. If it was discussed in an issue, just mention "issue #...".Explain why this change is needed. If the details are in an issue already,
this can be brief.Our development process is documented in the Wasmtime book:
https://docs.wasmtime.dev/contributing-development-process.htmlPlease ensure all communication follows the code of conduct:
https://github.com/bytecodealliance/wasmtime/blob/main/CODE_OF_CONDUCT.md
-->This add the optimization of
(x * y) (==/!=) z --> x (==/!=) (y / z).
ymust be odd and divideszfor the rule to be correct.
bongjunj requested wasmtime-compiler-reviewers for a review on PR #11994.
bongjunj requested cfallin for a review on PR #11994.
cfallin submitted PR review.
cfallin created PR review comment:
Could you add "and y and z are constant" to the description here? Otherwise this reads as a fairly odd optimization that is replacing a multiply with a divide, which would ordinarily reduce performance.
Also: why is it necessary that
yis odd? Is that because we need it to be mutually prime with the ring's modulus (2^n) so the product doesn't collapse to zero?
bongjunj updated PR #11994.
bongjunj submitted PR review.
bongjunj created PR review comment:
I've changed the description so that one can read that the division happens in compile time.
Also, the solution X for X * C = D is not unique when C is even in 2^n module arithmetic.
bongjunj edited PR review comment.
github-actions[bot] commented on PR #11994:
Subscribe to Label Action
cc @cfallin, @fitzgen
<details>
This issue or pull request has been labeled: "cranelift", "isle"Thus the following users have been cc'd because of the following labels:
- cfallin: isle
- fitzgen: isle
To subscribe or unsubscribe from this label, edit the <code>.github/subscribe-to-label.json</code> configuration file.
Learn more.
</details>
bongjunj commented on PR #11994:
Could you add "and y and z are constant" to the description here? Otherwise this reads as a fairly odd optimization that is replacing a multiply with a divide, which would ordinarily reduce performance.
Also: why is it necessary that
yis odd? Is that because we need it to be mutually prime with the ring's modulus (2^n) so the product doesn't collapse to zero?To clarify, this is the counterexample obtained by Crocus, when
yis relaxed to be any bitvector.
Here,yis even.Verification failed for <unnamed rule>, width 8 (simplify (ne [cty|8] (imul [ty|32] [x|#x80000002] (iconst_u [ty|32] [y|#x0000000000448102])) (iconst_u [ty|32] [z|#x0000000000890204]))) (if-let ((0) (u64_rem [z|#x0000000000890204] [y|#x0000000000448102]))((true) (u64_ne [y|#x0000000000448102] (0))))=> (ne [cty|8] [x|#x80000002] (iconst [ty|32] (imm64 (u64_div [z|#x0000000000890204] [y|#x0000000000448102]))))Furthermore, there is a similar optimization in LLVM
When
yis odd:define i1 @src(i32 %x) { #0: %mul = mul i32 %x, 7 %eq = icmp eq i32 %mul, 42 ret i1 %eq } => define i1 @src(i32 %x) nofree willreturn memory(none) { #0: %eq = icmp eq i32 %x, 6 ret i1 %eq } Transformation seems to be correct!When
yis even:---------------------------------------- define i1 @src(i32 %x) { #0: %mul = mul i32 %x, 6 %eq = icmp eq i32 %mul, 42 ret i1 %eq } => define i1 @tgt(i32 %x) { #0: %eq = icmp eq i32 %x, 7 ret i1 %eq } Transformation doesn't verify! ERROR: Value mismatch NOTE: The counterexample is unique. Example: i32 %x = #x80000007 (2147483655, -2147483641) Source: i32 %mul = #x0000002a (42) i1 %eq = #x1 (1) Target: i1 %eq = #x0 (0) Source value: #x1 (1) Target value: #x0 (0)This shows that the optimization violates the semantic equivalence (or refinement) when
yis even.
bongjunj edited a comment on PR #11994:
Could you add "and y and z are constant" to the description here? Otherwise this reads as a fairly odd optimization that is replacing a multiply with a divide, which would ordinarily reduce performance.
Also: why is it necessary that
yis odd? Is that because we need it to be mutually prime with the ring's modulus (2^n) so the product doesn't collapse to zero?To clarify, this is the counterexample obtained by Crocus, when
yis relaxed to be any bitvector.
Here,yis even.Verification failed for <unnamed rule>, width 8 (simplify (ne [cty|8] (imul [ty|32] [x|#x80000002] (iconst_u [ty|32] [y|#x0000000000448102])) (iconst_u [ty|32] [z|#x0000000000890204]))) (if-let ((0) (u64_rem [z|#x0000000000890204] [y|#x0000000000448102]))((true) (u64_ne [y|#x0000000000448102] (0))))=> (ne [cty|8] [x|#x80000002] (iconst [ty|32] (imm64 (u64_div [z|#x0000000000890204] [y|#x0000000000448102]))))Furthermore, there is a similar optimization in LLVM
When
yis odd:define i1 @src(i32 %x) { #0: %mul = mul i32 %x, 7 %eq = icmp eq i32 %mul, 42 ret i1 %eq } => define i1 @src(i32 %x) nofree willreturn memory(none) { #0: %eq = icmp eq i32 %x, 6 ret i1 %eq } Transformation seems to be correct!When
yis even:---------------------------------------- define i1 @src(i32 %x) { #0: %mul = mul i32 %x, 6 %eq = icmp eq i32 %mul, 42 ret i1 %eq } => define i1 @tgt(i32 %x) { #0: %eq = icmp eq i32 %x, 7 ret i1 %eq } Transformation doesn't verify! ERROR: Value mismatch NOTE: The counterexample is unique. Example: i32 %x = #x80000007 (2147483655, -2147483641) Source: i32 %mul = #x0000002a (42) i1 %eq = #x1 (1) Target: i1 %eq = #x0 (0) Source value: #x1 (1) Target value: #x0 (0)This shows that the optimization violates the semantic equivalence (or refinement) when
yis even.Reference implementation in LLVM: https://github.com/llvm/llvm-project/blob/a257a063c6fdcbc1db897d360c3791d8c4f4e48d/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp#L2209-L2230
bongjunj edited a comment on PR #11994:
Could you add "and y and z are constant" to the description here? Otherwise this reads as a fairly odd optimization that is replacing a multiply with a divide, which would ordinarily reduce performance.
Also: why is it necessary that
yis odd? Is that because we need it to be mutually prime with the ring's modulus (2^n) so the product doesn't collapse to zero?To clarify, this is the counterexample obtained by Crocus, when
yis relaxed to be any bitvector.
Here,yis even.Verification failed for <unnamed rule>, width 8 (simplify (ne [cty|8] (imul [ty|32] [x|#x80000002] (iconst_u [ty|32] [y|#x0000000000448102])) (iconst_u [ty|32] [z|#x0000000000890204]))) (if-let ((0) (u64_rem [z|#x0000000000890204] [y|#x0000000000448102]))((true) (u64_ne [y|#x0000000000448102] (0))))=> (ne [cty|8] [x|#x80000002] (iconst [ty|32] (imm64 (u64_div [z|#x0000000000890204] [y|#x0000000000448102]))))Furthermore, there is a similar optimization in LLVM, and the optimization requires
yto be odd as well.When
yis odd:define i1 @src(i32 %x) { #0: %mul = mul i32 %x, 7 %eq = icmp eq i32 %mul, 42 ret i1 %eq } => define i1 @src(i32 %x) nofree willreturn memory(none) { #0: %eq = icmp eq i32 %x, 6 ret i1 %eq } Transformation seems to be correct!When
yis even:---------------------------------------- define i1 @src(i32 %x) { #0: %mul = mul i32 %x, 6 %eq = icmp eq i32 %mul, 42 ret i1 %eq } => define i1 @tgt(i32 %x) { #0: %eq = icmp eq i32 %x, 7 ret i1 %eq } Transformation doesn't verify! ERROR: Value mismatch NOTE: The counterexample is unique. Example: i32 %x = #x80000007 (2147483655, -2147483641) Source: i32 %mul = #x0000002a (42) i1 %eq = #x1 (1) Target: i1 %eq = #x0 (0) Source value: #x1 (1) Target value: #x0 (0)This shows that the optimization violates the semantic equivalence (or refinement) when
yis even.Reference implementation in LLVM: https://github.com/llvm/llvm-project/blob/a257a063c6fdcbc1db897d360c3791d8c4f4e48d/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp#L2209-L2230
cfallin submitted PR review:
Yep, that makes sense -- just wanted to get it written down why. Thanks! Happy to merge once the merge conflicts are resolved.
bongjunj updated PR #11994.
bongjunj updated PR #11994.
cfallin submitted PR review.
cfallin created PR review comment:
One more request, sorry -- could you add the commutative versions (const * x) for both rules as well?
bongjunj updated PR #11994.
bongjunj updated PR #11994.
bongjunj submitted PR review.
bongjunj created PR review comment:
Thanks!
bongjunj updated PR #11994.
cfallin merged PR #11994.
Last updated: Dec 06 2025 at 06:05 UTC