-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Open
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.C-bugCategory: This is a bug.Category: This is a bug.I-heavyIssue: Problems and improvements with respect to binary size of generated code.Issue: Problems and improvements with respect to binary size of generated code.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.
Description
I tried this code (compiler explorer):
#[derive(Clone, Copy)]
pub enum Enum {
None,
Variant1,
Variant2,
}
impl Enum {
#[no_mangle]
pub fn as_str_1(self) -> &'static str {
// switch table for reference
match self {
Self::None => "",
Self::Variant1 => "1",
Self::Variant2 => "2",
}
}
#[no_mangle]
pub fn as_str_2(self) -> &'static str {
let len = (self as usize + 1) / 2;
let offs = self as usize / 2;
&"12"[offs..len + offs]
}
#[no_mangle]
pub fn as_str_3(self) -> &'static str {
let len = (self as usize + 1) / 2;
let offs = self as usize;
&" 12"[offs..len + offs]
}
}
and this code (compiler explorer):
#[derive(Clone, Copy)]
pub enum Enum {
None,
Variant1,
Variant2,
}
impl Enum {
#[no_mangle]
pub fn as_str_1(self) -> &'static str {
// switch table for reference
match self {
Self::None => "",
Self::Variant1 => "1",
Self::Variant2 => "2",
}
}
#[no_mangle]
pub fn as_str_2(self) -> &'static str {
let len = (self as usize + 1) / 2;
let offs = self as usize / 2;
&"12"[offs..len + offs]
}
}
(difference between the two is that as_str_3
only exists in the first example)
I expected to see this happen:
all as_str_
functions compile to roughly the same code (no memory accesses, just some pointer addition and getting the length right)
something like this (compiler explorer):
as_str_4:
movzx edx, dil
lea rax, [rip + .L__unnamed_3]
add rax, rdx
inc edx
shr edx
ret
.L__unnamed_3:
.ascii " 12"
Instead, this happened:
as_str_1
became a switch table, so i pointed the compiler in the right direction with as_str_2
, i tried a few other things, as_str_3
with an integer division less but a byte longer string and as_str_4
with unsafe code to get the desired output.
as_str_2
's panic branch only got removed when i commented as_str_3
out, as_str_3
always had one
Meta
rustc --version --verbose
:
rustc 1.77.0-nightly (62d7ed4a6 2024-01-11)
binary: rustc
commit-hash: 62d7ed4a6775c4490e493093ca98ef7c215b835b
commit-date: 2024-01-11
host: x86_64-unknown-linux-gnu
release: 1.77.0-nightly
LLVM version: 17.0.6
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.C-bugCategory: This is a bug.Category: This is a bug.I-heavyIssue: Problems and improvements with respect to binary size of generated code.Issue: Problems and improvements with respect to binary size of generated code.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.