Repository navigation
Missed code elimination with std::mem::replace/std::mem::swap #44701
Description
Activity
- addedC-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.
on Sep 19, 2017 Haven't studied the ASM in detail, but with 1.19 and earlier the drop function contains a lot less assembly output. Maybe this is related to #40454 ?
Indeed, 1.19 doesn't use a temporary, and #40454 looks suspicious, so I've investigated a little: https://godbolt.org/g/Fo2bZ1 .
BufferOlduses the old version ofstd::swap, andBufferNew- the relevant part of the new version.With 1.20, beta and nightly,
BufferNew::dropcompiles as described above, butBufferOld::dropuses only a single on-stack temporary and doesn't waste time copying data around, so at first it looks like the problem is the newstd::swap. Yet with 1.19, bothBufferNew::dropandBufferOld::dropcompile to the same, more efficient code that doesn't use temporaries at all.So it looks like there has been a regression in the optimizer since 1.20, and the new
std::swap, while not the problem itself, suffers from it unproportionally.@aidanhs The label should probably be changed since the issue appears to be a recent regression.
- addedC-bugCategory: This is a bug.Category: This is a bug.and removedC-enhancementCategory: An issue proposing an enhancement or a PR with one.Category: An issue proposing an enhancement or a PR with one.
on Sep 21, 2017 - addedI-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.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.
on Jul 16, 2023 Yes, this looks almost identical to the
replace_stringcodegen test in that PR: https://github.com/rust-lang/rust/pull/112733/files#diff-aeacafb3161bf010bd64adaedc5709ad328f4e1f222cbbc3b3def7c6ac4e4385R49- linked a pull request that will close this issueAvoid `memcpy` in codegen for more types, notably `Vec` #112733
on Jul 20, 2023 Actually, if this is about
allocas duringmem::replace, then I think it's actually already fixed with https://github.com/rust-lang/rust/pull/111010/files#diff-24ed0a5d700ac2b1c9e1ef53e400e7f92ec49f8165fc5bf2647d1efb69e21c80R16
Edit: As pointed out by @oyvindln, the problem appears to be a regression introduced in 1.20.
Demonstration: https://godbolt.org/g/5uuzVL
Version: rustc 1.22.0-nightly (277476c 2017-09-16) , -C opt-level=3 -C target-cpu=native
Code:
Expected result: An optimal code would move
self.bufdirectly intoself.pooland then resetself.bufin-place. An acceptable code would moveself.bufinto a temporary on the stack, move the temporary intoself.pooland resetself.bufin-place.Observed result:
std::Vec<u8>(each 24 bytes) is allocated on the stack,-48(%rbp)(A) and-96(%rbp)(B).self.bufis copied to A.self.bufis reset in-place.self.pool.Steps 4 and 5 is a completely unnecessary copying of 48 bytes and could be safely removed. Replacing
std::mem::replacewith an equivalentstd::mem::swapcall produces a slightly different code with the same basic problem.Compiler output: