From 14b8e6796db02b4036eeedd16ee5d448bfeae99b Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Tue, 1 Mar 2022 13:00:33 -0800 Subject: [PATCH] [EXPERIMENT] Double-check that the load-store approach in 94412 wasn't a problem Mark suggests that it wasn't, but I'll make this just to check that copy_nonoverlapping isn't better. --- library/core/src/mem/mod.rs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 8a99bed6a96ab..4c139d850d3cf 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -740,15 +740,7 @@ pub const fn swap(x: &mut T, y: &mut T) { #[rustc_const_unstable(feature = "const_swap", issue = "83163")] #[inline] pub(crate) const fn swap_simple(x: &mut T, y: &mut T) { - // We arrange for this to typically be called with small types, - // so this reads-and-writes approach is actually better than using - // copy_nonoverlapping as it easily puts things in LLVM registers - // directly and doesn't end up inlining allocas. - // And LLVM actually optimizes it to 3Ă—memcpy if called with - // a type larger than it's willing to keep in a register. - // Having typed reads and writes in MIR here is also good as - // it lets MIRI and CTFE understand them better, including things - // like enforcing type validity for them. + // Make sure the same operations are done on the two sides. // Importantly, read+copy_nonoverlapping+write introduces confusing // asymmetry to the behaviour where one value went through read+write // whereas the other was copied over by the intrinsic (see #94371). @@ -756,10 +748,11 @@ pub(crate) const fn swap_simple(x: &mut T, y: &mut T) { // SAFETY: exclusive references are always valid to read/write, // including being aligned, and nothing here panics so it's drop-safe. unsafe { - let a = ptr::read(x); - let b = ptr::read(y); - ptr::write(x, b); - ptr::write(y, a); + let mut z = MaybeUninit::::uninit(); + let z = z.as_mut_ptr(); + ptr::copy_nonoverlapping(x, z, 1); + ptr::copy_nonoverlapping(y, x, 1); + ptr::copy_nonoverlapping(z, y, 1); } }