-
Notifications
You must be signed in to change notification settings - Fork 14k
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.