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

Cranelift: avoid integer-shift optimization with invalid reduces on vector types. #10413

Conversation

cfallin
Copy link
Member

@cfallin cfallin commented Mar 17, 2025

An optimization rule in our mid-end implemented the following equivalence:

    (x << N) >> N == x as T1 as T2

where T1 is a smaller integer type and T2 is a larger integer type, and N is the difference in bitwidths between them. In other words, when a left-then-right-shift clears the upper bits (or sign-extends them), we can implement that by reducing to a smaller type then extending back to the original type.

Unfortunately, ireduce is not valid on vector-of-integer types. A fuzzbug reported in #10409 shows that this pattern results in invalid CLIF when optimizing this pattern with an i64x2 as input.

This PR tightens the rule's LHS to only apply to integer types.

Note that there is another optimization rule that can also implement this behavior with a bitwise AND with a mask. Previously the two resulting expressions had the same cost in the egraph, and whatever perturbation occurred in the ISLE compilation of the rule (which is a multi-constructor because this is the mid-end, so is returning multiple results) caused that rule's result to be picked instead during extraction. I've also tweaked the costs to make reduces/extends cheaper than ordinary arithmetic as a result, to keep the same optimizer outputs after extraction. One x64 test in particular showed why this is correct: the mask-with-AND resulted in two instructions (move, AND-with-immediate) while a uextend can be done with one (zero-extending move, movzbl), and aarch64 has similar builtin extends in many cases.

Fixes #10409.

…ector types.

An optimization rule in our mid-end implemented the following
equivalence:

```
    (x << N) >> N == x as T1 as T2
```

where `T1` is a smaller integer type and `T2` is a larger integer
type, and `N` is the difference in bitwidths between them. In other
words, when a left-then-right-shift clears the upper bits (or
sign-extends them), we can implement that by reducing to a smaller
type then extending back to the original type.

Unfortunately, `ireduce` is not valid on vector-of-integer types. A
fuzzbug reported in bytecodealliance#10409 shows that this pattern results in invalid
CLIF when optimizing this pattern with an `i64x2` as input.

This PR tightens the rule's LHS to only apply to integer types.

Note that there is another optimization rule that can also implement
this behavior with a bitwise AND with a mask. Previously the two
resulting expressions had the same cost in the egraph, and whatever
perturbation occurred in the ISLE compilation of the rule (which is a
multi-constructor because this is the mid-end, so is returning
multiple results) caused that rule's result to be picked instead
during extraction. I've also tweaked the costs to make reduces/extends
cheaper than ordinary arithmetic as a result, to keep the same
optimizer outputs after extraction. One x64 test in particular showed
why this is correct: the mask-with-AND resulted in two
instructions (move, AND-with-immediate) while a uextend can be done
with one (zero-extending move, `movzbl`), and aarch64 has similar
builtin extends in many cases.
@cfallin cfallin requested a review from fitzgen March 17, 2025 19:30
@cfallin cfallin requested a review from a team as a code owner March 17, 2025 19:30
Copy link
Member

@fitzgen fitzgen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@fitzgen fitzgen enabled auto-merge March 17, 2025 19:43
@fitzgen fitzgen added this pull request to the merge queue Mar 17, 2025
Merged via the queue into bytecodealliance:main with commit 1104a83 Mar 17, 2025
40 checks passed
@cfallin cfallin deleted the now-shift-to-the-left-now-shift-to-the-right-everybody-do-the-ireduce branch March 17, 2025 20:34
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

Successfully merging this pull request may close these issues.

cranelift fuzzgen: fuzz failure involving ishl of an i64x2 value and invalid operand constraints
2 participants