myunbin opened PR #14896 from myunbin:add-rules-261021 to bytecodealliance:main:
Add mid-end optimization rules:
(~x | y) ^ x --> ~(x & y)(~x OP y) ^ (~y OP x) --> x ^ y, whereOP = {&, |}(~x | y) & (~y | x) --> ~(x ^ y)max(x, y) OP min(x, y) --> x OP y, whereOP = {&, |, ^}max(~x, ~y) --> ~min(x, y)min(~x, ~y) --> ~max(x, y)~max(~x, y) --> min(x, ~y)~min(~x, y) --> max(x, ~y)-(x & y) + x --> x & ~y(~x & y) + (~y & x) --> x ^ y(-x) - (~x) --> 1~x + C --> (C - 1) - x(x + C) ^ -1 --> (-(C + 1)) - x(x | C) - C --> x & ~C(x | C) ^ (y | C) --> (x ^ y) & ~C(x | C) ^ (y ^ C) --> (x & ~C) ^ y(x << 1) * C --> x * (2 * C)~rotl(~x, k) --> rotl(x, k)~rotr(~x, k) --> rotr(x, k)(x << 1) == x --> x == 0(x >>u 1) == x --> x == 0(~x & y) == y --> (x & y) == 0~x == (~x | y) --> (x & y) == 0umax(x, y) OP 0 --> (x | y) OP 0, whereOP = {==, !=}umax(x, y) OP umin(x, y) --> x OP y, whereOP = {==, !=}(x >=s y) & (y >=s x) --> x == y(x >=u y) & (y >=u x) --> x == yselect(c, x, y) == select(c, y, x) --> x == yselect(x == 0, -x, x) --> x, and correspondingx != 0select(x == 0, 0, x OP y) --> x OP y, whereOP = {&, *}, and correspondingx != 0~select(c, C1, C2) --> select(c, ~C1, ~C2)-select(c, C1, C2) --> select(c, -C1, -C2)Thanks!
myunbin removed the review request for wasmtime-compiler-reviewers from PR #14896.
myunbin requested cfallin for a review on PR #14896.
myunbin requested wasmtime-compiler-reviewers for a review on PR #14896.
github-actions[bot] added the label cranelift on PR #14896.
github-actions[bot] added the label isle on PR #14896.
github-actions[bot] commented on PR #14896:
Subscribe to Label Action
cc @avanhatt, @cfallin, @fitzgen, @mmcloughlin
<details>
This issue or pull request has been labeled: "cranelift", "isle"Thus the following users have been cc'd because of the following labels:
- avanhatt: isle
- cfallin: isle
- fitzgen: isle
- mmcloughlin: isle
To subscribe or unsubscribe from this label, edit the <code>.github/subscribe-to-label.json</code> configuration file.
Learn more.
</details>
:thumbs_up: cfallin submitted PR review:
Thanks! The new rules look good generally. Just one question below about a possible pessimization.
:speech_balloon: cfallin created PR review comment:
This seems like a regression -- we won't use the native negation instruction anymore but instead will load a zero-constant and do a subtract. Could you look into what's going on here (cost function discrepancies or something else)?
:memo: myunbin submitted PR review.
:speech_balloon: myunbin created PR review comment:
@cfallin
I believe it's because of the rule
~x + C → (C - 1) - x.When
C=1, both rules match:
~x + 1 → (1 - 1) - x → 0 - x(added rule in this pr)~x + 1 → -x(existing one)The cost model assigns both candidates as 4:
ineg(4)andiconst(1) - isub(3), therefore tie.
Maybe the tie breaker chooses0 - xafterward.
:speech_balloon: myunbin edited PR review comment.
:speech_balloon: myunbin edited PR review comment.
:speech_balloon: myunbin edited PR review comment.
:memo: cfallin submitted PR review.
:speech_balloon: cfallin created PR review comment:
Interesting. Probably we should adjust the cost of
ineg: on all CPUs I'm aware of, a unary integer negation operator has the same cost as other ALU ops (1 cycle) so it should win against a const materialization plus an ALU op. Can you bundle that change in here and see if it fixes this regression?
myunbin updated PR #14896.
:memo: myunbin submitted PR review.
:speech_balloon: myunbin created PR review comment:
I adjusted
inegto have same cost with other ALU ops. I guess all affected test cases now produceineg.
:speech_balloon: myunbin edited PR review comment.
cfallin commented on PR #14896:
@myunbin it looks like there is a verifier failure now -- could you take a look?
myunbin commented on PR #14896:
@cfallin I found two issues while investigating this failure.
iconst_uspec seems to treat the result as a single integer rather than a splat. For example, the verifier reports:iconst_u({bits: 32, lanes: 4}, 1) -> [1, 0, 0, 0]. A splat would produce[1, 1, 1, 1]. The spec seems to be missing the per-lane semantics for supported vector types. I can investigate more and open a separate PR.<details>
<summary>log</summary>isub({bits: 32, lanes: 4}, [#x00 #x00 #x00 #x00], [#xff #xff #xff #xff]) -> [#x01 #x01 #x01 #x01] ineg({bits: 32, lanes: 4}, [#x00 #x00 #x00 #x00]) -> [#x00 #x00 #x00 #x00] bnot({bits: 32, lanes: 4}, [#x00 #x00 #x00 #x00]) -> [#xff #xff #xff #xff] iconst_u({bits: 32, lanes: 4}, #x0000000000000001) -> [#x01 #x00 #x00 #x00] simplify([#x01 #x01 #x01 #x01]) -> [#x01 #x00 #x00 #x00] violated: cranelift/codegen/src/spec/opt.isle line 71: e123 violated: cranelift/codegen/src/spec/opt.isle line 20: e167</details>
- I guess rule
(rule (simplify (isub ty (ineg ty x) (bnot ty x))) (iconst_u ty 1))crashes. Currentlyiconst_uonly supports scalar and vec128, but this rule can also match other vector widths, causing a panic. I'll restrict the rule to the supported types for now. Is there a reason the helper's vector support is limited to 128 bits?
myunbin edited a comment on PR #14896:
@cfallin I found two issues.
iconst_uspec seems to treat the result as a single integer rather than a splat. For example, the verifier reports:iconst_u({bits: 32, lanes: 4}, 1) -> [1, 0, 0, 0]. A splat would produce[1, 1, 1, 1]. The spec seems to be missing the per-lane semantics for supported vector types. I can investigate more and open a separate PR.<details>
<summary>log</summary>isub({bits: 32, lanes: 4}, [#x00 #x00 #x00 #x00], [#xff #xff #xff #xff]) -> [#x01 #x01 #x01 #x01] ineg({bits: 32, lanes: 4}, [#x00 #x00 #x00 #x00]) -> [#x00 #x00 #x00 #x00] bnot({bits: 32, lanes: 4}, [#x00 #x00 #x00 #x00]) -> [#xff #xff #xff #xff] iconst_u({bits: 32, lanes: 4}, #x0000000000000001) -> [#x01 #x00 #x00 #x00] simplify([#x01 #x01 #x01 #x01]) -> [#x01 #x00 #x00 #x00] violated: cranelift/codegen/src/spec/opt.isle line 71: e123 violated: cranelift/codegen/src/spec/opt.isle line 20: e167</details>
- I guess rule
(rule (simplify (isub ty (ineg ty x) (bnot ty x))) (iconst_u ty 1))crashes. Currentlyiconst_uonly supports scalar and vec128, but this rule can also match other vector widths, causing a panic. I'll restrict the rule to the supported types for now. Is there a reason the helper's vector support is limited to 128 bits?
myunbin edited a comment on PR #14896:
@cfallin I found two issues.
iconst_uspec seems to treat the result as a single integer rather than a splat. For example, the verifier reports:iconst_u({bits: 32, lanes: 4}, 1) -> [1, 0, 0, 0]. A splat would produce[1, 1, 1, 1]. The spec seems to be missing the per-lane semantics for supported vector types. I can investigate more and open a separate PR.<details>
<summary>log</summary>isub({bits: 32, lanes: 4}, [#x00 #x00 #x00 #x00], [#xff #xff #xff #xff]) -> [#x01 #x01 #x01 #x01] ineg({bits: 32, lanes: 4}, [#x00 #x00 #x00 #x00]) -> [#x00 #x00 #x00 #x00] bnot({bits: 32, lanes: 4}, [#x00 #x00 #x00 #x00]) -> [#xff #xff #xff #xff] iconst_u({bits: 32, lanes: 4}, #x0000000000000001) -> [#x01 #x00 #x00 #x00] simplify([#x01 #x01 #x01 #x01]) -> [#x01 #x00 #x00 #x00] violated: cranelift/codegen/src/spec/opt.isle line 71: e123 violated: cranelift/codegen/src/spec/opt.isle line 20: e167</details>
- I guess rule
(rule (simplify (isub ty (ineg ty x) (bnot ty x))) (iconst_u ty 1))crashes. Currentlyiconst_uonly supports scalar and vec128, but this rule can also match other vector widths, causing a panic. I'll restrict the rule to the supported types for now. Is there a reason the helper's vector support is limited to 128 bits?
myunbin edited a comment on PR #14896:
@cfallin I found two issues.
iconst_uspec seems to treat the result as a single integer rather than a splat. For example, the verifier reports:iconst_u({bits: 32, lanes: 4}, 1) -> [1, 0, 0, 0]. A splat would produce[1, 1, 1, 1]. The spec seems to be missing the per-lane semantics for supported vector types. I can investigate more and open a separate PR.<details>
<summary>log</summary>isub({bits: 32, lanes: 4}, [#x00 #x00 #x00 #x00], [#xff #xff #xff #xff]) -> [#x01 #x01 #x01 #x01] ineg({bits: 32, lanes: 4}, [#x00 #x00 #x00 #x00]) -> [#x00 #x00 #x00 #x00] bnot({bits: 32, lanes: 4}, [#x00 #x00 #x00 #x00]) -> [#xff #xff #xff #xff] iconst_u({bits: 32, lanes: 4}, #x0000000000000001) -> [#x01 #x00 #x00 #x00] simplify([#x01 #x01 #x01 #x01]) -> [#x01 #x00 #x00 #x00] violated: cranelift/codegen/src/spec/opt.isle line 71: e123 violated: cranelift/codegen/src/spec/opt.isle line 20: e167</details>
(rule (simplify (isub ty (ineg ty x) (bnot ty x))) (iconst_u ty 1))crashes. Currentlyiconst_uonly supports scalar and vec128, but this rule can also match other vector widths, causing a panic. I'll restrict the rule to the supported types for now. Is there a reason the helper's vector support is limited to 128 bits?
myunbin updated PR #14896.
myunbin updated PR #14896.
Last updated: Oct 31 2026 at 23:03 UTC