Repository navigation
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-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchCategory: An issue highlighting optimization opportunities or PRs implementing suchI-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
See the following code:
pub struct ListNode {
next: Option<Box<ListNode>>
}
pub fn foo(mut head: Box<ListNode>) -> Box<ListNode> {
let mut cur = &mut head;
while let Some(next) = std::mem::replace(&mut cur.next, None) {
cur.next = Some(next);
cur = cur.next.as_mut().unwrap();
}
head
}Apparently the unwrap should never panic given the assignment in the previous line. However, based on the assembly output, that check isn't optimized away.
(The while let statement seems to be generating useless function calls for drop as well, btw.)
Reacted by LifeIsStrange, Dror Levin, Yari, ondj, scottmcm, Iago-lito, Bobby Reynolds, Andrea Catania, Kevin Darlington, Akshay Karthik and 3 more
Reacted by Ricardo Fernández Serrata
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-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchCategory: An issue highlighting optimization opportunities or PRs implementing suchI-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
RustyYato commentedon Jul 15, 2019
Minimal example
This no-op
generates
On playground for the latest nightly (2019-07-14 83e4eed)
upsuper commentedon Jul 16, 2019
That reminds me that this issue may be from the enum size optimization. When we don't have a separate field for the enum tag (in case like
Option<Box<_>>), compiler doesn't make use of non-null guarantee when optimizing it.To prove that, an even simpler testcase is:
which produces the following assembly:
Details
AndreaCatania commentedon Nov 24, 2019
Hope that this will be improved soon considering the broad use of
Optionand the related functionsunwrap,expect,...klensy commentedon Aug 8, 2023
Slapping
-Zmir-opt-level=3solves issue, at least now https://rust.godbolt.org/z/6d8hW1PqWWorks for String and NonZeroUsize examples, but not for first message (this is -Zmir-enable-passes=+DataflowConstProp)
saethlin commentedon Nov 9, 2024
The minimized examples have been fixed since 1.77. I'm not completely certain that we have codegen tests for these.
But the original example still has the missing optimizations as described.
lolbinarycat commentedon Mar 31, 2025
Here's a new MCVE:
scottmcm commentedon Apr 1, 2025
Hmm, the
as_mut()in the OP makes it much harder, because things like #138759 won't be able to help as it's forced through memory.@lolbinarycat Please include a godbolt or playground link with a repro. That works fine when I try it https://rust.godbolt.org/z/cnznoG4K4