Bad codegen for comparing struct of two 16bit ints
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
I tried this code:
#[derive(Clone, Copy, PartialEq)]
pub struct Foo {
pub x: u16,
pub y: u16,
}
#[no_mangle]
fn eq(a: &Foo, b: &Foo) -> bool {
a == b
}
I expected to see this happen: a and b are loaded into a single register each and then the registers are compared against each other.
Instead, this happened: https://rust.godbolt.org/z/8zaxKG8vx
For -Copt-level=2:
eq:
movzx eax, word ptr [rdi]
movzx ecx, word ptr [rdi + 2]
xor ax, word ptr [rsi]
movzx edx, word ptr [rsi + 2]
xor edx, ecx
or dx, ax
sete al
ret
For -Copt-level=3:
eq:
movd xmm0, dword ptr [rdi]
movd xmm1, dword ptr [rsi]
pcmpeqw xmm1, xmm0
pshuflw xmm0, xmm1, 80
pshufd xmm0, xmm0, 80
movmskpd eax, xmm0
cmp eax, 3
sete al
ret
Meta
rustc --version --verbose:
Both 1.86 and nightly.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the Rust snippet with rustc 1.86 and nightly, using the provided Godbolt link to compare assembly at opt-level 2 and 3. Read the open pull request linked from this issue before beginning, then use the generated code as the regression target. Done means the comparison produces the expected more efficient codegen without breaking correctness.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers, performance
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100