Repository navigation
Closed
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-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.llvm-fixed-upstreamIssue expected to be fixed by the next major LLVM upgrade, or backported fixesIssue expected to be fixed by the next major LLVM upgrade, or backported fixes
Description
I tried this code:
Say we define an AST type for expressions, each carrying a span to give its position in the original source code:
pub type ByteSpan = (u32, u32);
pub enum Expr<'core> {
Error(ByteSpan),
Int(ByteSpan, u64),
Array(ByteSpan, &'core [Self]),
Call(ByteSpan, &'core Self, &'core [Self]),
}
pub fn span(expr: &Expr) -> ByteSpan {
match expr {
Expr::Error(span, ..)
| Expr::Int(span, ..)
| Expr::Array(span, ..)
| Expr::Call(span, ..) => *span,
}
}I expected to see this happen:
The ByteSpan is placed at the same offset for every variant of the enum, so the final assembly for span should be:
example::span:
mov eax, dword ptr [rdi + 4]
mov edx, dword ptr [rdi + 8]
ret
Instead, this happened:
A jump table is generated, even though every entry in the jump table is identical (godbolt):
example::span:
mov eax, dword ptr [rdi]
lea rcx, [rip + .LJTI0_0]
movsxd rax, dword ptr [rcx + 4*rax]
add rax, rcx
jmp rax
.LBB0_1:
lea rcx, [rdi + 4]
mov eax, dword ptr [rdi + 4]
mov edx, dword ptr [rcx + 4]
ret
.LJTI0_0:
.long .LBB0_1-.LJTI0_0
.long .LBB0_1-.LJTI0_0
.long .LBB0_1-.LJTI0_0
.long .LBB0_1-.LJTI0_0
If the last 2 variants are removed, the optimal code is produced. If only the last variant is removed, the code is better, but still suboptimal:
example::span:
mov eax, dword ptr [rdi]
test rax, rax
je .LBB0_2
cmp eax, 1
.LBB0_2:
lea rcx, [rdi + 4]
mov eax, dword ptr [rdi + 4]
mov edx, dword ptr [rcx + 4]
ret
Meta
rustc --version --verbose:
rustc 1.74.0-nightly (1e746d774 2023-09-07)
binary: rustc
commit-hash: 1e746d7741d44551e9378daf13b8797322aa0b74
commit-date: 2023-09-07
host: x86_64-unknown-linux-gnu
release: 1.74.0-nightly
LLVM version: 17.0.0
Compiler returned: 0
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-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.llvm-fixed-upstreamIssue expected to be fixed by the next major LLVM upgrade, or backported fixesIssue expected to be fixed by the next major LLVM upgrade, or backported fixes
Activity
Kmeakin commentedon Sep 10, 2023
@rustbot label I-slow
dianqk commentedon Sep 11, 2023
Looking at the IR form https://godbolt.org/z/G79jaedqa, I believe this is a duplicate issue of #113506.
@rustbot claim
the8472 commentedon Sep 11, 2023
The ordering of the variant payloads is not guaranteed to be in source order for
repr(Rust)enumsKmeakin commentedon Sep 12, 2023
But in this case rustc did decide to put it at the same offset for each variant, so no jump table should be needed
nikic commentedon Feb 14, 2024
Not fixed by the LLVM 18 upgrade. Keeping the label though, as LLVM 19 should fix this thanks to getelementptr i8 canonicalization.
erikdesjardins commentedon Mar 5, 2024
Fixed in nightly by #121665: https://godbolt.org/z/rPhrxTq61
I don't think this needs a test, since
tests/codegen/issues/issue-121719-common-field-offset.rsadded in that PR is basically the same.dianqk commentedon Mar 6, 2024
Yes. InstCombine now do this transformation. It's different from #113506.
WaffleLapkin commentedon Mar 6, 2024
Closing as per #115742 (comment)