rename typed_swap → typed_swap_nonoverlapping
This commit is contained in:
parent
00dfa3ba2d
commit
7291b1eaf7
14 changed files with 43 additions and 26 deletions
|
@ -75,7 +75,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
// If we're swapping something that's *not* an `OperandValue::Ref`,
|
// If we're swapping something that's *not* an `OperandValue::Ref`,
|
||||||
// then we can do it directly and avoid the alloca.
|
// then we can do it directly and avoid the alloca.
|
||||||
// Otherwise, we'll let the fallback MIR body take care of it.
|
// Otherwise, we'll let the fallback MIR body take care of it.
|
||||||
if let sym::typed_swap = name {
|
if let sym::typed_swap_nonoverlapping = name {
|
||||||
let pointee_ty = fn_args.type_at(0);
|
let pointee_ty = fn_args.type_at(0);
|
||||||
let pointee_layout = bx.layout_of(pointee_ty);
|
let pointee_layout = bx.layout_of(pointee_ty);
|
||||||
if !bx.is_backend_ref(pointee_layout)
|
if !bx.is_backend_ref(pointee_layout)
|
||||||
|
|
|
@ -382,7 +382,7 @@ pub trait BuilderMethods<'a, 'tcx>:
|
||||||
/// Avoids `alloca`s for Immediates and ScalarPairs.
|
/// Avoids `alloca`s for Immediates and ScalarPairs.
|
||||||
///
|
///
|
||||||
/// FIXME: Maybe do something smarter for Ref types too?
|
/// FIXME: Maybe do something smarter for Ref types too?
|
||||||
/// For now, the `typed_swap` intrinsic just doesn't call this for those
|
/// For now, the `typed_swap_nonoverlapping` intrinsic just doesn't call this for those
|
||||||
/// cases (in non-debug), preferring the fallback body instead.
|
/// cases (in non-debug), preferring the fallback body instead.
|
||||||
fn typed_place_swap(
|
fn typed_place_swap(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
|
@ -424,7 +424,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
|
||||||
let result = self.raw_eq_intrinsic(&args[0], &args[1])?;
|
let result = self.raw_eq_intrinsic(&args[0], &args[1])?;
|
||||||
self.write_scalar(result, dest)?;
|
self.write_scalar(result, dest)?;
|
||||||
}
|
}
|
||||||
sym::typed_swap => {
|
sym::typed_swap_nonoverlapping => {
|
||||||
self.typed_swap_intrinsic(&args[0], &args[1])?;
|
self.typed_swap_intrinsic(&args[0], &args[1])?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -496,7 +496,9 @@ pub fn check_intrinsic_type(
|
||||||
(1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit)
|
(1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
sym::typed_swap => (1, 0, vec![Ty::new_mut_ptr(tcx, param(0)); 2], tcx.types.unit),
|
sym::typed_swap_nonoverlapping => {
|
||||||
|
(1, 0, vec![Ty::new_mut_ptr(tcx, param(0)); 2], tcx.types.unit)
|
||||||
|
}
|
||||||
|
|
||||||
sym::discriminant_value => {
|
sym::discriminant_value => {
|
||||||
let assoc_items = tcx.associated_item_def_ids(
|
let assoc_items = tcx.associated_item_def_ids(
|
||||||
|
|
|
@ -2058,7 +2058,7 @@ symbols! {
|
||||||
type_macros,
|
type_macros,
|
||||||
type_name,
|
type_name,
|
||||||
type_privacy_lints,
|
type_privacy_lints,
|
||||||
typed_swap,
|
typed_swap_nonoverlapping,
|
||||||
u128,
|
u128,
|
||||||
u128_legacy_const_max,
|
u128_legacy_const_max,
|
||||||
u128_legacy_const_min,
|
u128_legacy_const_min,
|
||||||
|
|
|
@ -3940,6 +3940,21 @@ pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[rustc_nounwind]
|
||||||
|
#[inline]
|
||||||
|
#[rustc_intrinsic]
|
||||||
|
#[rustc_intrinsic_const_stable_indirect]
|
||||||
|
#[rustc_allow_const_fn_unstable(const_swap_nonoverlapping)] // this is anyway not called since CTFE implements the intrinsic
|
||||||
|
#[cfg(bootstrap)]
|
||||||
|
pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) {
|
||||||
|
// SAFETY: The caller provided single non-overlapping items behind
|
||||||
|
// pointers, so swapping them with `count: 1` is fine.
|
||||||
|
unsafe { ptr::swap_nonoverlapping(x, y, 1) };
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(bootstrap)]
|
||||||
|
pub use typed_swap as typed_swap_nonoverlapping;
|
||||||
|
|
||||||
/// Non-overlapping *typed* swap of a single value.
|
/// Non-overlapping *typed* swap of a single value.
|
||||||
///
|
///
|
||||||
/// The codegen backends will replace this with a better implementation when
|
/// The codegen backends will replace this with a better implementation when
|
||||||
|
@ -3953,10 +3968,10 @@ pub const fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
|
||||||
#[rustc_nounwind]
|
#[rustc_nounwind]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_intrinsic]
|
#[rustc_intrinsic]
|
||||||
// Const-unstable because `swap_nonoverlapping` is const-unstable.
|
|
||||||
#[rustc_intrinsic_const_stable_indirect]
|
#[rustc_intrinsic_const_stable_indirect]
|
||||||
#[rustc_allow_const_fn_unstable(const_swap_nonoverlapping)] // this is anyway not called since CTFE implements the intrinsic
|
#[rustc_allow_const_fn_unstable(const_swap_nonoverlapping)] // this is anyway not called since CTFE implements the intrinsic
|
||||||
pub const unsafe fn typed_swap<T>(x: *mut T, y: *mut T) {
|
#[cfg(not(bootstrap))]
|
||||||
|
pub const unsafe fn typed_swap_nonoverlapping<T>(x: *mut T, y: *mut T) {
|
||||||
// SAFETY: The caller provided single non-overlapping items behind
|
// SAFETY: The caller provided single non-overlapping items behind
|
||||||
// pointers, so swapping them with `count: 1` is fine.
|
// pointers, so swapping them with `count: 1` is fine.
|
||||||
unsafe { ptr::swap_nonoverlapping(x, y, 1) };
|
unsafe { ptr::swap_nonoverlapping(x, y, 1) };
|
||||||
|
|
|
@ -730,7 +730,7 @@ pub unsafe fn uninitialized<T>() -> T {
|
||||||
pub const fn swap<T>(x: &mut T, y: &mut T) {
|
pub const fn swap<T>(x: &mut T, y: &mut T) {
|
||||||
// SAFETY: `&mut` guarantees these are typed readable and writable
|
// SAFETY: `&mut` guarantees these are typed readable and writable
|
||||||
// as well as non-overlapping.
|
// as well as non-overlapping.
|
||||||
unsafe { intrinsics::typed_swap(x, y) }
|
unsafe { intrinsics::typed_swap_nonoverlapping(x, y) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Replaces `dest` with the default value of `T`, returning the previous `dest` value.
|
/// Replaces `dest` with the default value of `T`, returning the previous `dest` value.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
use std::intrinsics::typed_swap;
|
use std::intrinsics::typed_swap_nonoverlapping;
|
||||||
use std::ptr::addr_of_mut;
|
use std::ptr::addr_of_mut;
|
||||||
|
|
||||||
fn invalid_array() {
|
fn invalid_array() {
|
||||||
|
@ -10,7 +10,7 @@ fn invalid_array() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let a = addr_of_mut!(a).cast::<[bool; 100]>();
|
let a = addr_of_mut!(a).cast::<[bool; 100]>();
|
||||||
let b = addr_of_mut!(b).cast::<[bool; 100]>();
|
let b = addr_of_mut!(b).cast::<[bool; 100]>();
|
||||||
typed_swap(a, b); //~ERROR: constructing invalid value
|
typed_swap_nonoverlapping(a, b); //~ERROR: constructing invalid value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: Undefined Behavior: constructing invalid value at [0]: encountered 0x02, but expected a boolean
|
error: Undefined Behavior: constructing invalid value at [0]: encountered 0x02, but expected a boolean
|
||||||
--> tests/fail/intrinsics/typed-swap-invalid-array.rs:LL:CC
|
--> tests/fail/intrinsics/typed-swap-invalid-array.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | typed_swap(a, b);
|
LL | typed_swap_nonoverlapping(a, b);
|
||||||
| ^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered 0x02, but expected a boolean
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value at [0]: encountered 0x02, but expected a boolean
|
||||||
|
|
|
|
||||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
use std::intrinsics::typed_swap;
|
use std::intrinsics::typed_swap_nonoverlapping;
|
||||||
use std::ptr::addr_of_mut;
|
use std::ptr::addr_of_mut;
|
||||||
|
|
||||||
fn invalid_scalar() {
|
fn invalid_scalar() {
|
||||||
|
@ -10,7 +10,7 @@ fn invalid_scalar() {
|
||||||
unsafe {
|
unsafe {
|
||||||
let a = addr_of_mut!(a).cast::<bool>();
|
let a = addr_of_mut!(a).cast::<bool>();
|
||||||
let b = addr_of_mut!(b).cast::<bool>();
|
let b = addr_of_mut!(b).cast::<bool>();
|
||||||
typed_swap(a, b); //~ERROR: constructing invalid value
|
typed_swap_nonoverlapping(a, b); //~ERROR: constructing invalid value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: Undefined Behavior: constructing invalid value: encountered 0x02, but expected a boolean
|
error: Undefined Behavior: constructing invalid value: encountered 0x02, but expected a boolean
|
||||||
--> tests/fail/intrinsics/typed-swap-invalid-scalar.rs:LL:CC
|
--> tests/fail/intrinsics/typed-swap-invalid-scalar.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | typed_swap(a, b);
|
LL | typed_swap_nonoverlapping(a, b);
|
||||||
| ^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x02, but expected a boolean
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered 0x02, but expected a boolean
|
||||||
|
|
|
|
||||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
|
|
||||||
use std::intrinsics::typed_swap;
|
use std::intrinsics::typed_swap_nonoverlapping;
|
||||||
use std::ptr::addr_of_mut;
|
use std::ptr::addr_of_mut;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut a = [0_u8; 100];
|
let mut a = [0_u8; 100];
|
||||||
unsafe {
|
unsafe {
|
||||||
let a = addr_of_mut!(a);
|
let a = addr_of_mut!(a);
|
||||||
typed_swap(a, a); //~ERROR: called on overlapping ranges
|
typed_swap_nonoverlapping(a, a); //~ERROR: called on overlapping ranges
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: Undefined Behavior: `copy_nonoverlapping` called on overlapping ranges
|
error: Undefined Behavior: `copy_nonoverlapping` called on overlapping ranges
|
||||||
--> tests/fail/intrinsics/typed-swap-overlap.rs:LL:CC
|
--> tests/fail/intrinsics/typed-swap-overlap.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | typed_swap(a, a);
|
LL | typed_swap_nonoverlapping(a, a);
|
||||||
| ^^^^^^^^^^^^^^^^ `copy_nonoverlapping` called on overlapping ranges
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `copy_nonoverlapping` called on overlapping ranges
|
||||||
|
|
|
|
||||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
|
|
@ -8,14 +8,14 @@
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
|
|
||||||
use std::intrinsics::typed_swap;
|
use std::intrinsics::typed_swap_nonoverlapping;
|
||||||
|
|
||||||
// CHECK-LABEL: @swap_unit(
|
// CHECK-LABEL: @swap_unit(
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe fn swap_unit(x: &mut (), y: &mut ()) {
|
pub unsafe fn swap_unit(x: &mut (), y: &mut ()) {
|
||||||
// CHECK: start
|
// CHECK: start
|
||||||
// CHECK-NEXT: ret void
|
// CHECK-NEXT: ret void
|
||||||
typed_swap(x, y)
|
typed_swap_nonoverlapping(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @swap_i32(
|
// CHECK-LABEL: @swap_i32(
|
||||||
|
@ -32,7 +32,7 @@ pub unsafe fn swap_i32(x: &mut i32, y: &mut i32) {
|
||||||
// OPT3: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x, ptr align 4 %y, i64 4, i1 false)
|
// OPT3: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x, ptr align 4 %y, i64 4, i1 false)
|
||||||
// CHECK: store i32 %[[TEMP]], ptr %y, align 4
|
// CHECK: store i32 %[[TEMP]], ptr %y, align 4
|
||||||
// CHECK: ret void
|
// CHECK: ret void
|
||||||
typed_swap(x, y)
|
typed_swap_nonoverlapping(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @swap_pair(
|
// CHECK-LABEL: @swap_pair(
|
||||||
|
@ -47,7 +47,7 @@ pub unsafe fn swap_pair(x: &mut (i32, u32), y: &mut (i32, u32)) {
|
||||||
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x, ptr align 4 %y, i64 8, i1 false)
|
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x, ptr align 4 %y, i64 8, i1 false)
|
||||||
// CHECK: store i32
|
// CHECK: store i32
|
||||||
// CHECK: store i32
|
// CHECK: store i32
|
||||||
typed_swap(x, y)
|
typed_swap_nonoverlapping(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CHECK-LABEL: @swap_str(
|
// CHECK-LABEL: @swap_str(
|
||||||
|
@ -63,7 +63,7 @@ pub unsafe fn swap_str<'a>(x: &mut &'a str, y: &mut &'a str) {
|
||||||
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %x, ptr align 8 %y, i64 16, i1 false)
|
// CHECK: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %x, ptr align 8 %y, i64 16, i1 false)
|
||||||
// CHECK: store ptr
|
// CHECK: store ptr
|
||||||
// CHECK: store i64
|
// CHECK: store i64
|
||||||
typed_swap(x, y)
|
typed_swap_nonoverlapping(x, y)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OPT0-LABEL: @swap_string(
|
// OPT0-LABEL: @swap_string(
|
||||||
|
@ -73,5 +73,5 @@ pub unsafe fn swap_string(x: &mut String, y: &mut String) {
|
||||||
// OPT0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TEMP]], ptr align 8 %x, i64 24, i1 false)
|
// OPT0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %[[TEMP]], ptr align 8 %x, i64 24, i1 false)
|
||||||
// OPT0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %x, ptr align 8 %y, i64 24, i1 false)
|
// OPT0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %x, ptr align 8 %y, i64 24, i1 false)
|
||||||
// OPT0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %y, ptr align 8 %[[TEMP]], i64 24, i1 false)
|
// OPT0: call void @llvm.memcpy.p0.p0.i64(ptr align 8 %y, ptr align 8 %[[TEMP]], i64 24, i1 false)
|
||||||
typed_swap(x, y)
|
typed_swap_nonoverlapping(x, y)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue