Differently optimized code between `let else` and `if`
Open
Nobody has claimed this yet.
A-LLVM
C-optimization
- Dominant language
- Rust
- Stars
- 119k
- Forks
- 16.1k
- PR merge metrics
- PR metrics pending
Description
Hi,
Those two pieces of code do the same thing, but end up having different assembly 👀
#[inline(never)]
pub fn foo(x: i32) -> bool {
let (1 | 3 | 99) = x else { return false; };
true
}
#[inline(never)]
pub fn bar(x: i32) -> bool {
x == 1 || x == 3 || x == 99
}
playground::foo: # @playground::foo
# %bb.0:
cmpl $1, %edi
je .LBB0_4
# %bb.1:
cmpl $99, %edi
je .LBB0_4
# %bb.2:
cmpl $3, %edi
jne .LBB0_3
.LBB0_4:
movb $1, %al
# kill: def $al killed $al killed $eax
retq
.LBB0_3:
xorl %eax, %eax
# kill: def $al killed $al killed $eax
retq
# -- End function
playground::bar: # @playground::bar
# %bb.0:
movb $1, %al
cmpl $1, %edi
je .LBB1_4
# %bb.1:
cmpl $3, %edi
je .LBB1_4
# %bb.2:
cmpl $99, %edi
je .LBB1_4
# %bb.3:
xorl %eax, %eax
.LBB1_4:
# kill: def $al killed $al killed $eax
retq
# -- End function
Curiously, they do get optimized the same sometimes (e.g. for (1 | 3 | 5) or even (1 | 2 | 3 | 5..=10)).
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 with the playground reproduction and compare the generated assembly for foo and bar in release mode. Investigate why the let-else pattern and equivalent boolean expression receive different optimization, then verify whether the cases produce equivalent assembly after the fix.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100