Simpler Logic Produces More Complex Output Than Equivalent Expression
Open
Nobody has claimed this yet.
A-LLVM
C-optimization
I-slow
T-compiler
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
I tried these codes:
https://godbolt.org/z/sE73ocr4a
#![allow(unused_parens)]
#![allow(non_camel_case_types)]
enum colour {
red(isize, isize),
green,
}
impl PartialEq for colour {
#[no_mangle]
fn eq(&self, other: &colour) -> bool {
match *self {
colour::red(a0, b0) => match (*other) {
colour::red(a1, b1) => a0 == a1 && b0 == b1,
colour::green => false,
},
colour::green => match (*other) {
colour::red(..) => false,
colour::green => true,
},
}
}
}
and:
#![allow(unused_parens)]
#![allow(non_camel_case_types)]
enum colour {
red(isize, isize),
green,
}
impl PartialEq for colour {
#[no_mangle]
fn eq(&self, other: &colour) -> bool {
match *self {
colour::red(a0, b0) => match (*other) {
colour::red(a1, b1) => !(!(!(a0 != a1)) || !(!(b0 != b1))),
colour::green => false,
},
colour::green => match (*other) {
colour::red(..) => false,
colour::green => true,
},
}
}
}
I expected to see this happen:
Both expressions should produce identical assembly code:
eq:
movzx eax, byte ptr [rdi]
mov rcx, qword ptr [rsi]
mov edx, eax
or dl, cl
test dl, 1
je .LBB0_2
and al, cl
and al, 1
ret
.LBB0_2:
mov rax, qword ptr [rdi + 8]
xor rax, qword ptr [rsi + 8]
mov rcx, qword ptr [rsi + 16]
xor rcx, qword ptr [rdi + 16]
or rcx, rax
sete al
and al, 1
ret
Instead, this happened:
The first expression with simpler logic a0 == a1 && b0 == b1, generated more complex assembly code than expected:
eq:
cmp dword ptr [rdi], 1
jne .LBB0_2
movzx eax, byte ptr [rsi]
and al, 1
ret
.LBB0_2:
test byte ptr [rsi], 1
jne .LBB0_3
mov rax, qword ptr [rdi + 8]
cmp rax, qword ptr [rsi + 8]
jne .LBB0_3
mov rax, qword ptr [rdi + 16]
cmp rax, qword ptr [rsi + 16]
sete al
and al, 1
ret
.LBB0_3:
xor eax, eax
and al, 1
ret
Thank you!
Meta
rustc 1.85.0-nightly (d117b7f21 2024-12-31)
binary: rustc
commit-hash: d117b7f211835282b3b177dc64245fff0327c04c
commit-date: 2024-12-31
host: x86_64-unknown-linux-gnu
release: 1.85.0-nightly
LLVM version: 19.1.6
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 two examples from the Godbolt link with the reported rustc 1.85.0-nightly version and compare their generated assembly. Trace whether the difference comes from rustc or LLVM optimization, then confirm the simpler and equivalent expressions produce equivalent output.
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