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

Introduce unsafe offset_from on pointers #49297

Merged
merged 5 commits into from
Mar 26, 2018
Merged

Conversation

scottmcm
Copy link
Member

@scottmcm scottmcm commented Mar 23, 2018

Adds intrinsics::exact_div to take advantage of the unsafe, which reduces the implementation from

    sub rcx, rdx
    mov rax, rcx
    sar rax, 63
    shr rax, 62
    lea rax, [rax + rcx]
    sar rax, 2
    ret

down to

    sub rcx, rdx
    sar rcx, 2
    mov rax, rcx
    ret

(for *const i32)

See discussion on the offset_to tracking issue #41079

Some open questions

and todos

Adds intrinsics::exact_div to take advantage of the unsafe, which reduces the implementation from
```asm
    sub rcx, rdx
    mov rax, rcx
    sar rax, 63
    shr rax, 62
    lea rax, [rax + rcx]
    sar rax, 2
    ret
```
down to
```asm
    sub rcx, rdx
    sar rcx, 2
    mov rax, rcx
    ret
```
(for `*const i32`)
@scottmcm scottmcm added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Mar 23, 2018
@rust-highfive
Copy link
Collaborator

r? @dtolnay

(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 Mar 23, 2018
assert!(0 < pointee_size && pointee_size <= isize::max_value() as usize);

// FIXME: can this be nuw/nsw?
let d = isize::wrapping_sub(self as _, other as _);
Copy link
Member

Choose a reason for hiding this comment

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

It can't be nuw because the result might be a negative value.

It can't be nsw either because an allocation may straddle the boundary between ISIZE_MAX (0x7fffffff) and ISIZE_MIN (0x80000000).

Copy link
Member

Choose a reason for hiding this comment

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

I agree. nuw and nsw force both the result and the operands to have the same interpretation as each other. What you'd really want here is a way to say that the operands have an unsigned interpretation, while the result has a signed interpretation, however there's currently no way to express that in LLVM.

@@ -343,6 +343,12 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
"overflowing_add" => bx.add(args[0].immediate(), args[1].immediate()),
"overflowing_sub" => bx.sub(args[0].immediate(), args[1].immediate()),
"overflowing_mul" => bx.mul(args[0].immediate(), args[1].immediate()),
"exact_div" =>
if signed {
bx.exactsdiv(args[0].immediate(), args[1].immediate())
Copy link
Member

Choose a reason for hiding this comment

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

exactsdiv seems to be missing?

Copy link
Member Author

Choose a reason for hiding this comment

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

///
/// let a = [0; 5];
/// let ptr1: *const i32 = &a[1];
/// let ptr2: *const i32 = &a[3];
Copy link
Contributor

@strega-nil strega-nil Mar 23, 2018

Choose a reason for hiding this comment

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

This will panic at runtime. You do this a few other places as well. You should probably use get_unchecked? There's no actual mention of UB if you index out of bounds, so, I don't think it's an issue.

Copy link
Contributor

@hanna-kruppe hanna-kruppe Mar 23, 2018

Choose a reason for hiding this comment

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

Huh? a is an array of length 5, so a[3] is not out of bounds.

(But if it was, get_unchecked would be UB because it uses offset, not wrapping_offset.)

Copy link
Contributor

Choose a reason for hiding this comment

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

I, uh, may be too used to OCaml, sorry -.-

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, offset works with pointers which are one past the end.

Copy link
Contributor

@hanna-kruppe hanna-kruppe Mar 23, 2018

Choose a reason for hiding this comment

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

Oh yeah if a had length 2 then that would have been fine. Edit: Uh, yeah, see below

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, I'm just being stupid, array indexing is zero-based lol. Sorry, I should not comment when I'm tired :P

@scottmcm scottmcm changed the title [WIP] Introduce unsafe offset_from on pointers Introduce unsafe offset_from on pointers Mar 25, 2018
Copy link
Member

@dtolnay dtolnay left a comment

Choose a reason for hiding this comment

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

Looks good to me. Thanks!

I agree with the discussion in the tracking issue that the safe wrapping one seems suspicious, but I think it is fine to see how it gets used and revisit before stabilization.

@dtolnay
Copy link
Member

dtolnay commented Mar 25, 2018

@bors r+

@bors
Copy link
Contributor

bors commented Mar 25, 2018

📌 Commit 6264952 has been approved by dtolnay

@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 Mar 25, 2018
@bors
Copy link
Contributor

bors commented Mar 26, 2018

⌛ Testing commit 6264952 with merge 39ee3aa...

bors added a commit that referenced this pull request Mar 26, 2018
Introduce unsafe offset_from on pointers

Adds intrinsics::exact_div to take advantage of the unsafe, which reduces the implementation from
```asm
    sub rcx, rdx
    mov rax, rcx
    sar rax, 63
    shr rax, 62
    lea rax, [rax + rcx]
    sar rax, 2
    ret
```
down to
```asm
    sub rcx, rdx
    sar rcx, 2
    mov rax, rcx
    ret
```
(for `*const i32`)

See discussion on the `offset_to` tracking issue #41079

Some open questions
- Would you rather I split the intrinsic PR from the library PR?
- Do we even want the safe version of the API?  #41079 (comment)  I've added some text to its documentation that even if it's not UB, it's useless to use it between pointers into different objects.

and todos
- [x] ~~I need to make a codegen test~~ Done
- [x] ~~Can the subtraction use nsw/nuw?~~ No, it can't #49297 (comment)
- [x] ~~Should there be `usize` variants of this, like there are now `add` and `sub` that you almost always want over `offset`?  For example, I imagine `sub_ptr` that returns `usize` and where it's UB if the distance is negative.~~ Can wait for later; C gives a signed result #41079 (comment), so we might as well, and this existing to go with `offset` makes sense.
@bors
Copy link
Contributor

bors commented Mar 26, 2018

☀️ Test successful - status-appveyor, status-travis
Approved by: dtolnay
Pushing 39ee3aa to master...

@bors bors merged commit 6264952 into rust-lang:master Mar 26, 2018
@scottmcm scottmcm deleted the offset-from branch March 26, 2018 02:40
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. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants