-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Closed
Closed
Copy link
Labels
A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.
Description
I tried this code:
compiler explorer
pub enum Enum {
A(u32),
B(u32),
C(u32),
}
#[no_mangle]
pub fn f1(lhs: &Enum, rhs: &Enum) -> bool {
match (lhs, rhs) {
(Enum::A(lhs), Enum::A(rhs)) => lhs == rhs,
(Enum::B(lhs), Enum::B(rhs)) => lhs == rhs,
(Enum::C(lhs), Enum::C(rhs)) => lhs == rhs,
_ => false,
}
}
#[no_mangle]
pub fn f2(lhs: &Enum, rhs: &Enum) -> bool {
if std::mem::discriminant(lhs) != std::mem::discriminant(rhs) {
return false;
}
match (lhs, rhs) {
(Enum::A(lhs), Enum::A(rhs)) => lhs == rhs,
(Enum::B(lhs), Enum::B(rhs)) => lhs == rhs,
(Enum::C(lhs), Enum::C(rhs)) => lhs == rhs,
_ => false,
}
}
#[no_mangle]
pub fn f3(lhs: &Enum, rhs: &Enum) -> bool {
if std::mem::discriminant(lhs) != std::mem::discriminant(rhs) {
return false;
}
match (lhs, rhs) {
(Enum::A(lhs), Enum::A(rhs)) => lhs == rhs,
(Enum::B(lhs), Enum::B(rhs)) => lhs == rhs,
(Enum::C(lhs), Enum::C(rhs)) => lhs == rhs,
_ => unsafe { std::hint::unreachable_unchecked() },
}
}
Code like this is often used for implementations of PartialEq
or PartialOrd
on enums, so it is important that it be optimized well.
I expected to see this happen:
The functions f1
and f2
should produce equivalent machine code to f3
.
Instead, this happened:
f1
and f2
do not produce equivalent machine code.
f1
is missing the early return for when the discriminants do not match.
f2
unnecessarily examines the discriminant of lhs
twice!
LLVM should be able to transform f1
into f2
, and f2
into f3
Meta
rustc --version --verbose
:
rustc 1.76.0-nightly (a96d57bdb 2023-12-15)
binary: rustc
commit-hash: a96d57bdb6d2bb6d233d7d5aaefc2995ab99be01
commit-date: 2023-12-15
host: x86_64-unknown-linux-gnu
release: 1.76.0-nightly
LLVM version: 17.0.6
Backtrace
<backtrace>
Metadata
Metadata
Assignees
Labels
A-LLVMArea: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.Area: Code generation parts specific to LLVM. Both correctness bugs and optimization-related issues.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.