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.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchCategory: An issue highlighting optimization opportunities or PRs implementing suchE-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.Call for participation: An issue has been fixed and does not reproduce, but no test has been added.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.S-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueStatus: A Minimal Complete and Verifiable Example has been found for this issueT-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
When creating a structure which has a variant type, and that this type is wrapped as an Option<T>, the unwrap branch cannot be removed by LLVM, even after proving that the only path reachable is the Some(…) case and never the None case.
I tried this code:
Calling the previous function as:
assert!(self.top != 0);
let v = self.pop().unwrap();
This hint LLVM that the self.top == 0 branch does not need to be generated. However, the unwrap condition remains as the None value is folded within the variant and that LLVM does not know about it.
I think the Rust compiler should give range analysis information that the None value would never be part of the variant, and as such let LLVM remove the unwrapping condition from the generated code.
Meta
Tested with both rustc --version --verbose:
rustc 1.42.0 (b8cedc004 2020-03-09)
binary: rustc
commit-hash: b8cedc00407a4c56a3bda1ed605c6fc166655447
commit-date: 2020-03-09
host: x86_64-unknown-linux-gnu
release: 1.42.0
LLVM version: 9.0
and
rustc 1.44.0-nightly (7f3df5772 2020-04-16)
binary: rustc
commit-hash: 7f3df5772439eee1c512ed2eb540beef1124d236
commit-date: 2020-04-16
host: x86_64-unknown-linux-gnu
release: 1.44.0-nightly
LLVM version: 9.0
Reacted by MSxDOS, vultix, PSeitz, Lu, Wangshan, Aurelia Molzer, Jakub Beránek, Ricardo Silva Veloso and Timo
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.C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchCategory: An issue highlighting optimization opportunities or PRs implementing suchE-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.Call for participation: An issue has been fixed and does not reproduce, but no test has been added.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.S-has-mcveStatus: A Minimal Complete and Verifiable Example has been found for this issueStatus: A Minimal Complete and Verifiable Example has been found for this issueT-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
Mark-Simulacrum commentedon Apr 17, 2020
In the trivial case, https://rust.godbolt.org/z/3TaPU2, this doesn't seem to reproduce, so I'm going to go ahead and mark as E-needs-mcve. I suspect that this might be a case of insufficient inlining or something like that.
nbp commentedon Apr 18, 2020
I can reproduce it with the following test case: ( https://rust.godbolt.org/z/t_9kCR )
In the generated code we see the branch for the assertion, which remove the None case from
pop. However, the unwrap condition is still present, because theNonecase is mixed with the discriminant type ofFoo, which lead the generated code to load the the discriminant, and compare it against theNonevalue (= 2), instead of removing the branch.nbp commentedon Apr 18, 2020
I will also note that without the assertion, the case which generate the
Nonebranch is folded with the unwrap case and panic. However, theSomebranch still has the extra unwrap test, despite the fact that it would never fail.jrmuizel commentedon Jun 10, 2020
Clang gets this right with the
-fstrict-enumsoption which attaches range metadata to the enum load from the the Vec.e.g.
with
-O2compiles to something similar to the Rust code:but with
-O2 -fstrict-enumscompiles to the desired:It seems like it would be reasonable for Rust to always act like
-fstrict-enumshanna-kruppe commentedon Jun 11, 2020
rustc already adds range metadata to the load of the discriminant. It seems it gets lost at some point during optimizations.
jrmuizel commentedon Jun 11, 2020
Hmm so it does. It seems like LLVM is pretty fragile here.
produces the following with
-fstrict-enumsInterestingly enough the
jebecomesjgewithout-fstrict-enumsso LLVM has some idea what's going on.jrmuizel commentedon Jun 11, 2020
I filed an LLVM bug:
https://bugs.llvm.org/show_bug.cgi?id=46279
jrmuizel commentedon Jun 11, 2020
So it turns out that https://bugs.llvm.org/show_bug.cgi?id=46279 was me making an incorrect assumption about enums in C++. I looked more closely at the rust issue and filed #73258 which probably needs to be fixed before making progress on this one.
alex commentedon Dec 29, 2024
This appears to be fixed: https://rust.godbolt.org/z/38bsj4onG
moxian commentedon Mar 25, 2025
Fixed in #109035 . Might be worth adding an extra test to ensure this does not regress?
But if not, and the checks in the PR are sufficient, then we can just close this.
@rustbot label: -E-needs-mcve +S-has-mcve +E-needs-test +C-optimization
Rollup merge of rust-lang#145380 - okaneco:add-codegen-tests, r=Mark-…
Rollup merge of rust-lang#145380 - okaneco:add-codegen-tests, r=Mark-…
Unrolled build for #145380
Rollup merge of #145380 - okaneco:add-codegen-tests, r=Mark-Simulacrum
Rollup merge of #145380 - okaneco:add-codegen-tests, r=Mark-Simulacrum