-
Notifications
You must be signed in to change notification settings - Fork 13k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of #110837 - scottmcm:offset-for-add, r=compiler-errors
Use MIR's `Offset` for pointer `add` too ~~Status: draft while waiting for #110822 to land, since this is built atop that.~~ ~~r? `@ghost~~` Canonical Rust code has mostly moved to `add`/`sub` on pointers, which take `usize`, instead of `offset` which takes `isize`. (And, relatedly, when `sub_ptr` was added it turned out it replaced every single in-tree use of `offset_from`, because `usize` is just so much more useful than `isize` in Rust.) Unfortunately, `intrinsics::offset` could only accept `*const` and `isize`, so there's a *huge* amount of type conversions back and forth being done. They're identity conversions in the backend, but still end up producing quite a lot of unhelpful MIR. This PR changes `intrinsics::offset` to accept `*const` *and* `*mut` along with `isize` *and* `usize`. Conveniently, the backends and CTFE already handle this, since MIR's `BinOp::Offset` [already supports all four combinations](https://github.com/rust-lang/rust/blob/adaac6b166df57ea5a20d56e4cce503b55aca927/compiler/rustc_const_eval/src/transform/validate.rs#L523-L528). To demonstrate the difference, I added some `mir-opt/pre-codegen/` tests around slice indexing. Here's the difference to `[T]::get_mut`, since it uses `<*mut _>::add` internally: ```diff `@@` -79,30 +70,21 `@@` fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { StorageLive(_12); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL StorageLive(_9); // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL _9 = _8 as *mut u32 (PtrToPtr); // scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL - StorageLive(_13); // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL - _13 = _2 as isize (IntToInt); // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL - StorageLive(_14); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL - StorageLive(_15); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL - _15 = _9 as *const u32 (Pointer(MutToConstPointer)); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL - _14 = Offset(move _15, _13); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL - StorageDead(_15); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL - _7 = move _14 as *mut u32 (PtrToPtr); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL - StorageDead(_14); // scope 15 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL - StorageDead(_13); // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL + _7 = Offset(_9, _2); // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL StorageDead(_9); // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL StorageDead(_12); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL StorageDead(_11); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL ``` 1c1c8e4#diff-a841b6a4538657add3f39bc895744331453d0625e7aace128b1f604f0b63c8fdR80
- Loading branch information
Showing
14 changed files
with
401 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
// compile-flags: -O -C no-prepopulate-passes | ||
// min-llvm-version: 15.0 (because we're using opaque pointers) | ||
|
||
#![crate_type = "lib"] | ||
#![feature(core_intrinsics)] | ||
|
||
use std::intrinsics::offset; | ||
|
||
// CHECK-LABEL: ptr @offset_zst | ||
// CHECK-SAME: (ptr noundef %p, [[SIZE:i[0-9]+]] noundef %d) | ||
#[no_mangle] | ||
pub unsafe fn offset_zst(p: *const (), d: usize) -> *const () { | ||
// CHECK-NOT: getelementptr | ||
// CHECK: ret ptr %p | ||
offset(p, d) | ||
} | ||
|
||
// CHECK-LABEL: ptr @offset_isize | ||
// CHECK-SAME: (ptr noundef %p, [[SIZE]] noundef %d) | ||
#[no_mangle] | ||
pub unsafe fn offset_isize(p: *const u32, d: isize) -> *const u32 { | ||
// CHECK: %[[R:.*]] = getelementptr inbounds i32, ptr %p, [[SIZE]] %d | ||
// CHECK-NEXT: ret ptr %[[R]] | ||
offset(p, d) | ||
} | ||
|
||
// CHECK-LABEL: ptr @offset_usize | ||
// CHECK-SAME: (ptr noundef %p, [[SIZE]] noundef %d) | ||
#[no_mangle] | ||
pub unsafe fn offset_usize(p: *const u64, d: usize) -> *const u64 { | ||
// CHECK: %[[R:.*]] = getelementptr inbounds i64, ptr %p, [[SIZE]] %d | ||
// CHECK-NEXT: ret ptr %[[R]] | ||
offset(p, d) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
// compile-flags: -O -C debuginfo=0 -Zmir-opt-level=2 | ||
// only-64bit | ||
// ignore-debug | ||
|
||
#![crate_type = "lib"] | ||
|
||
use std::ops::Range; | ||
|
||
// EMIT_MIR slice_index.slice_index_usize.PreCodegen.after.mir | ||
pub fn slice_index_usize(slice: &[u32], index: usize) -> u32 { | ||
slice[index] | ||
} | ||
|
||
// EMIT_MIR slice_index.slice_get_mut_usize.PreCodegen.after.mir | ||
pub fn slice_get_mut_usize(slice: &mut [u32], index: usize) -> Option<&mut u32> { | ||
slice.get_mut(index) | ||
} | ||
|
||
// EMIT_MIR slice_index.slice_index_range.PreCodegen.after.mir | ||
pub fn slice_index_range(slice: &[u32], index: Range<usize>) -> &[u32] { | ||
&slice[index] | ||
} | ||
|
||
// EMIT_MIR slice_index.slice_get_unchecked_mut_range.PreCodegen.after.mir | ||
pub unsafe fn slice_get_unchecked_mut_range(slice: &mut [u32], index: Range<usize>) -> &mut [u32] { | ||
slice.get_unchecked_mut(index) | ||
} |
105 changes: 105 additions & 0 deletions
105
tests/mir-opt/pre-codegen/slice_index.slice_get_mut_usize.PreCodegen.after.mir
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
// MIR for `slice_get_mut_usize` after PreCodegen | ||
|
||
fn slice_get_mut_usize(_1: &mut [u32], _2: usize) -> Option<&mut u32> { | ||
debug slice => _1; // in scope 0 at $DIR/slice_index.rs:+0:28: +0:33 | ||
debug index => _2; // in scope 0 at $DIR/slice_index.rs:+0:47: +0:52 | ||
let mut _0: std::option::Option<&mut u32>; // return place in scope 0 at $DIR/slice_index.rs:+0:64: +0:80 | ||
scope 1 (inlined core::slice::<impl [u32]>::get_mut::<usize>) { // at $DIR/slice_index.rs:16:11: 16:25 | ||
debug self => _1; // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL | ||
debug index => _2; // in scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL | ||
scope 2 (inlined <usize as SliceIndex<[u32]>>::get_mut) { // at $SRC_DIR/core/src/slice/mod.rs:LL:COL | ||
debug self => _2; // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
debug slice => _1; // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
let mut _3: bool; // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
let mut _4: usize; // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
let mut _5: &[u32]; // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
let mut _6: &mut u32; // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
let mut _7: *mut u32; // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
let mut _8: *mut [u32]; // in scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
scope 3 { | ||
scope 4 (inlined <usize as SliceIndex<[u32]>>::get_unchecked_mut) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
debug self => _2; // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
debug slice => _8; // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
let mut _9: *mut u32; // in scope 4 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
let mut _10: usize; // in scope 4 at $SRC_DIR/core/src/intrinsics.rs:LL:COL | ||
let mut _11: *mut [u32]; // in scope 4 at $SRC_DIR/core/src/intrinsics.rs:LL:COL | ||
scope 5 { | ||
debug this => _2; // in scope 5 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
scope 6 { | ||
scope 7 (inlined <usize as SliceIndex<[T]>>::get_unchecked_mut::runtime::<u32>) { // at $SRC_DIR/core/src/intrinsics.rs:LL:COL | ||
debug this => _10; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL | ||
debug slice => _11; // in scope 7 at $SRC_DIR/core/src/intrinsics.rs:LL:COL | ||
scope 8 (inlined ptr::mut_ptr::<impl *mut [u32]>::len) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
debug self => _11; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL | ||
let mut _12: *const [u32]; // in scope 8 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL | ||
scope 9 (inlined std::ptr::metadata::<[u32]>) { // at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL | ||
debug ptr => _12; // in scope 9 at $SRC_DIR/core/src/ptr/metadata.rs:LL:COL | ||
scope 10 { | ||
} | ||
} | ||
} | ||
} | ||
scope 11 (inlined ptr::mut_ptr::<impl *mut [u32]>::as_mut_ptr) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
debug self => _8; // in scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL | ||
} | ||
scope 12 (inlined ptr::mut_ptr::<impl *mut u32>::add) { // at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
debug self => _9; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL | ||
debug count => _2; // in scope 12 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL | ||
scope 13 { | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
bb0: { | ||
StorageLive(_6); // scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL | ||
StorageLive(_3); // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
StorageLive(_4); // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
StorageLive(_5); // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
_5 = &(*_1); // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
_4 = Len((*_5)); // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
StorageDead(_5); // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
_3 = Lt(_2, move _4); // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
StorageDead(_4); // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
switchInt(move _3) -> [0: bb2, otherwise: bb1]; // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
} | ||
|
||
bb1: { | ||
StorageLive(_7); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
StorageLive(_8); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
_8 = &raw mut (*_1); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
StorageLive(_10); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
StorageLive(_11); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
StorageLive(_12); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
StorageLive(_9); // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
_9 = _8 as *mut u32 (PtrToPtr); // scope 11 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL | ||
_7 = Offset(_9, _2); // scope 13 at $SRC_DIR/core/src/ptr/mut_ptr.rs:LL:COL | ||
StorageDead(_9); // scope 6 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
StorageDead(_12); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
StorageDead(_11); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
StorageDead(_10); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
StorageDead(_8); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
_6 = &mut (*_7); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
_0 = Option::<&mut u32>::Some(_6); // scope 3 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
StorageDead(_7); // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
goto -> bb3; // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
} | ||
|
||
bb2: { | ||
_0 = const Option::<&mut u32>::None; // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
// mir::Constant | ||
// + span: no-location | ||
// + literal: Const { ty: Option<&mut u32>, val: Value(Scalar(0x0000000000000000)) } | ||
goto -> bb3; // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
} | ||
|
||
bb3: { | ||
StorageDead(_3); // scope 2 at $SRC_DIR/core/src/slice/index.rs:LL:COL | ||
StorageDead(_6); // scope 1 at $SRC_DIR/core/src/slice/mod.rs:LL:COL | ||
return; // scope 0 at $DIR/slice_index.rs:+2:2: +2:2 | ||
} | ||
} |
Oops, something went wrong.