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-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.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
The following:
pub enum All {
None,
Foo,
Bar,
}
pub fn f(a: &mut All, q: i32) -> i32 {
*a = if (q == 5) {
All::Foo
} else {
All::Bar
};
match *a {
All::None => unreachable!(),
All::Foo => 1,
All::Bar => 2,
}
}compiles to:
example::f:
cmp esi, 5
sete al
mov cl, 2
sub cl, al
mov byte ptr [rdi], cl
mov eax, 1
cmp cl, 1
je .LBB6_3
cmp cl, 2
jne .LBB6_4
mov eax, 2
.LBB6_3:
ret
.LBB6_4:
push rax
call std::panicking::begin_panic
ud2The unreachable! and should be eliminated
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-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.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.
Activity
erikdesjardins commentedon Jun 8, 2020
This optimizes well with
u8instead of an enum:u8
With an enum, the important part of the optimized LLVM IR looks like this:
And with
u8:So it seems that LLVM doesn't propagate value ranges though
zext(or something, I don't know LLVM internals). And sure enough, if I addas u64to theu8code, it generates a panic branch:u8 as u64
With an enum, various things that make the size of the discriminant the same as the size of the enum in memory (hence avoiding the
zext) allow LLVM to remove the panic branch, e.g. a repr hint or an explicit discriminant that's different (?) from what the implicit discriminant would be:enums
I don't know why rustc does this. I assume it has something to do with the default discriminant type being
isize.Edit: it seems that LLVM is able to see through the zext in...some cases. I can't tell why, and it doesn't really seem to help us. See: https://godbolt.org/z/W8SeHC.
jrmuizel commentedon Jun 8, 2020
I've filed the upstream issue: https://bugs.llvm.org/show_bug.cgi?id=46244
@eddyb is it possible for us to avoid the
zextwhen generating code for this example?erikdesjardins commentedon Jul 14, 2020
@rustbot modify labels: +A-LLVM
erikdesjardins commentedon Dec 12, 2020
Like #77812 (comment), this will be fixed in LLVM 12: https://llvm.godbolt.org/z/jxjEbq
MSxDOS commentedon Mar 5, 2021
Seems to be fixed on the latest nightly by #81451
Rollup merge of rust-lang#82874 - erikdesjardins:cgtests, r=nagisa