-
Notifications
You must be signed in to change notification settings - Fork 12.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Carefully remove bounds checks from some chunk iterator functions #86988
Conversation
r? @kennytm (rust-highfive has picked a reviewer for you, use r? to override) |
taking over reviews for this one r? @the8472 |
Ping from triage: |
Yes, but probably not until the weekend |
6fdbf2f
to
1f8fb58
Compare
Current status: The code works fine, and I've tried to remove the repetition from the safety comments, which is probably1 for the best. Anyway, I guess it can be reviewed now? I don't know that I can improve the safety comments further, but hopefully it's enough? That said, I'm willing to apply suggestions if they're suitably concrete2. Footnotes
|
The comment length looks manageable now and the contents are ok too. I looked over the existing tests and it appears that there are no explicit tests for |
Co-authored-by: the8472 <the8472@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JohnCSimon this should be waiting-on-author.
To make my previous comment more explicit, since this adds unsafe code it would be good to have test-coverage for it and the existing tests don't look like they cover it entirely.
Specifically Chunks::next_back
returning Some
doesn't appear to be covered, the None
case is covered by test_chunks_nth_back
.
Ah, right, I forgot about this. I'll get to it later this weekend. |
@thomcc ping, long weekend? 😄 |
😅 I'll try to get to it when I find some time. Busy lately, unfortunately. |
7a1a939
to
9c62455
Compare
Let's try.... @rustbot ready (Yay, it worked) |
@bors r+ rollup=never I'm not seeing much chunks use in the compiler itself but let's skip rollup just in case some lib uses it. |
📌 Commit 9c62455 has been approved by |
☀️ Test successful - checks-actions |
Finished benchmarking commit (547f2ba): comparison url. Summary: This benchmark run did not return any relevant results. If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf. @rustbot label: -perf-regression |
So, I was writing code that requires the equivalent of
rchunks(N).rev()
(which isn't the same as forwardchunks(N)
— in particular, if the buffer length is not a multiple ofN
, I must handle the "remainder" first).I happened to look at the codegen output of the function (I was actually interested in whether or not a nested loop was being unrolled — it was), and noticed that in the outer
rchunks(n).rev()
loop, LLVM seemed to be unable to remove the bounds checks from the iteration: https://rust.godbolt.org/z/Tnz4MYY8f (this panic was from the split_at inRChunks::next_back
).After doing some experimentation, it seems all of the
next_back
in the non-exact chunk iterators have the issue: (Chunks::next_back
,RChunks::next_back
,ChunksMut::next_back
, andRChunksMut::next_back
)...Even worse, the forward
rchunks
iterators sometimes have the issue as well (... but only sometimes). For example https://rust.godbolt.org/z/oGhbqv53r has bounds checks, but if I uncomment the loop body, it manages to remove the check (which is bizarre, since I'd expect the opposite...). I suspect it's highly dependent on the surrounding code, so I decided to remove the bounds checks from them anyway. Overall, this change includes:next_back
functions on the non-Exact
iterators (e.g.R?Chunks(Mut)?
).next
functions on the non-exact rchunks iterators (e.g.RChunks(Mut)?
).I wasn't able to catch any of the other chunk iterators failing to remove the bounds checks (I checked iterations over
r?chunks(_exact)?(_mut)?
with constant chunk sizes under-O3
,-Os
, and-Oz
), which makes sense, since these were the cases where it was harder to prove the bounds check correct to remove...In fact, it took quite a bit of thinking to convince myself that using unchecked_ here was valid — so I'm not really surprised that LLVM had trouble (although compilers are slightly better at this sort of reasoning than humans). A consequence of that is the fact that the
// SAFETY
comment for these are... kinda long...I didn't do this for, or even think about it for, any of the other iteration methods; just
next
andnext_back
(where it mattered). If this PR is accepted, I'll file a follow up for someone (possibly me) to look at the others later (in particular,nth
/nth_back
looked like they had similar logic), but I wanted to do this now, as IMOnext
/next_back
are the most important here, since they're what gets used by the iteration protocol.Note: While I don't expect this to impact performance directly, the panic is a side effect, which would otherwise not exist in these loops. That is, this could prevent the compiler from being able to move/remove/otherwise rework a loop over these iterators (as an example, it could not delete the code for a loop whose body computes a value which doesn't get used).
Also, some like to be able to have confidence this code has no panicking branches in the optimized code, and "no bounds checks" is kinda part of the selling point of Rust's iterators anyway.