Skip to content
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

Use unchecked mul to compute slice sizes #98078

Merged
merged 1 commit into from
Jun 15, 2022

Conversation

erikdesjardins
Copy link
Contributor

This allows LLVM to realize that slice.len() > 0 iff slice.len() * size_of::<T>() > 0, allowing a branch on the latter to be folded into the former when dropping vecs and boxed slices, in some cases.

Fixes (partially) #96497

@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jun 14, 2022
@rust-highfive
Copy link
Collaborator

r? @petrochenkov

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jun 14, 2022
@rust-log-analyzer

This comment has been minimized.

@@ -39,7 +39,8 @@ pub fn size_and_align_of_dst<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
// The info in this case is the length of the str, so the size is that
// times the unit size.
(
bx.mul(info.unwrap(), bx.const_usize(unit.size.bytes())),
// All slice sizes must fit into `isize`, so this multiplication cannot (signed) wrap.
bx.unchecked_smul(info.unwrap(), bx.const_usize(unit.size.bytes())),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any specific reason to use signed multiplication here?
Both length and element size are unsigned.

Copy link
Contributor Author

@erikdesjardins erikdesjardins Jun 14, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because mul/unchecked_smul/unchecked_umul are all "half width" multiplies (the result is the same number of bits as the input), there is no behavior difference between signed and unsigned multiplication--for the same bitpattern in the inputs, they return the same result. This is why the previous code was just bx.mul, and not bx.smul or bx.umul (which don't exist).

The difference between unchecked_umul/unchecked_smul, then, is that unchecked_umul tells the backend that the multiplication can't wrap around the unsigned boundary (0/usize::MAX), and unchecked_smul tells the backend that it can't wrap around the signed boundary (isize::MIN/isize::MAX). Ideally, we would have both (resulting in mul nsw nuw in LLVM IR), since we know both inputs are non-negative. But there's no existing unchecked_nsw_nuw_mul, and it's not necessary for this use case, so I don't think it's worth adding.

Because both unchecked_umul and unchecked_smul are correct here, the choice is arbitrary. I picked unchecked_smul here because the upper bound on the result is lower (isize::MAX instead of usize::MAX), though I have no particular reason to prefer that over a tighter lower bound. The added test case passes with either.

Added a comment.

@petrochenkov
Copy link
Contributor

r=me after answering #98078 (comment) and squashing commits.
@rustbot author

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 14, 2022
...since slice sizes can't signed wrap

see https://doc.rust-lang.org/std/slice/fn.from_raw_parts.html

> The total size len * mem::size_of::<T>() of the slice must be no larger than isize::MAX.
@erikdesjardins
Copy link
Contributor Author

@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Jun 14, 2022
@petrochenkov
Copy link
Contributor

Thanks!
@bors r+

@bors
Copy link
Contributor

bors commented Jun 14, 2022

📌 Commit 50f6a9e has been approved by petrochenkov

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 14, 2022
JohnTitor added a commit to JohnTitor/rust that referenced this pull request Jun 14, 2022
…rochenkov

Use unchecked mul to compute slice sizes

This allows LLVM to realize that `slice.len() > 0` iff `slice.len() * size_of::<T>() > 0`, allowing a branch on the latter to be folded into the former when dropping vecs and boxed slices, in some cases.

Fixes (partially) rust-lang#96497
bors added a commit to rust-lang-ci/rust that referenced this pull request Jun 15, 2022
Rollup of 7 pull requests

Successful merges:

 - rust-lang#97822 (Filter out intrinsics if we have other import candidates to suggest)
 - rust-lang#98026 (Move some tests to more reasonable directories)
 - rust-lang#98067 (compiler: remove unused deps)
 - rust-lang#98078 (Use unchecked mul to compute slice sizes)
 - rust-lang#98083 (Rename rustc_serialize::opaque::Encoder as MemEncoder.)
 - rust-lang#98087 (Suggest adding a `#[macro_export]` to a private macro)
 - rust-lang#98113 (Fix misspelling of "constraint" as "contraint")

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 2722c2a into rust-lang:master Jun 15, 2022
@rustbot rustbot added this to the 1.63.0 milestone Jun 15, 2022
@erikdesjardins erikdesjardins deleted the uncheckedsize branch June 15, 2022 14:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants