Auto merge of #49297 - scottmcm:offset-from, r=dtolnay
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 https://github.com/rust-lang/rust/issues/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? https://github.com/rust-lang/rust/issues/41079#issuecomment-374426786 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 https://github.com/rust-lang/rust/pull/49297#discussion_r176697574
- [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 https://github.com/rust-lang/rust/issues/41079#issuecomment-375842235, so we might as well, and this existing to go with `offset` makes sense.
This commit is contained in:
commit
39ee3aaa13
8 changed files with 295 additions and 4 deletions
|
|
@ -344,6 +344,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn exactudiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
|
||||
self.count_insn("exactudiv");
|
||||
unsafe {
|
||||
llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn sdiv(&self, lhs: ValueRef, rhs: ValueRef) -> ValueRef {
|
||||
self.count_insn("sdiv");
|
||||
unsafe {
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>,
|
|||
"ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" |
|
||||
"bitreverse" | "add_with_overflow" | "sub_with_overflow" |
|
||||
"mul_with_overflow" | "overflowing_add" | "overflowing_sub" | "overflowing_mul" |
|
||||
"unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" => {
|
||||
"unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" | "exact_div" => {
|
||||
let ty = arg_tys[0];
|
||||
match int_type_width_signed(ty, cx) {
|
||||
Some((width, signed)) =>
|
||||
|
|
@ -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())
|
||||
} else {
|
||||
bx.exactudiv(args[0].immediate(), args[1].immediate())
|
||||
},
|
||||
"unchecked_div" =>
|
||||
if signed {
|
||||
bx.sdiv(args[0].immediate(), args[1].immediate())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue