about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libcore/mem.rs2
-rw-r--r--src/libcore/ptr.rs13
-rw-r--r--src/test/codegen/swap-small-types.rs27
3 files changed, 41 insertions, 1 deletions
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index 8fb4e0d6a02..a0fe6e98806 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -638,7 +638,7 @@ pub unsafe fn uninitialized<T>() -> T {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn swap<T>(x: &mut T, y: &mut T) {
     unsafe {
-        ptr::swap_nonoverlapping(x, y, 1);
+        ptr::swap_nonoverlapping_one(x, y);
     }
 }
 
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index d8e061496d9..d020e14be4c 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -188,6 +188,19 @@ pub unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
 }
 
 #[inline]
+pub(crate) unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
+    // For types smaller than the block optimization below,
+    // just swap directly to avoid pessimizing codegen.
+    if mem::size_of::<T>() < 32 {
+        let z = read(x);
+        copy_nonoverlapping(y, x, 1);
+        write(y, z);
+    } else {
+        swap_nonoverlapping(x, y, 1);
+    }
+}
+
+#[inline]
 unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
     // The approach here is to utilize simd to swap x & y efficiently. Testing reveals
     // that swapping either 32 bytes or 64 bytes at a time is most efficient for intel
diff --git a/src/test/codegen/swap-small-types.rs b/src/test/codegen/swap-small-types.rs
new file mode 100644
index 00000000000..46406ee5182
--- /dev/null
+++ b/src/test/codegen/swap-small-types.rs
@@ -0,0 +1,27 @@
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// compile-flags: -O
+// only-x86_64
+
+#![crate_type = "lib"]
+
+use std::mem::swap;
+
+type RGB48 = [u16; 3];
+
+// CHECK-LABEL: @swap_rgb48
+#[no_mangle]
+pub fn swap_rgb48(x: &mut RGB48, y: &mut RGB48) {
+// CHECK-NOT: alloca
+// CHECK: load i48
+// CHECK: store i48
+    swap(x, y)
+}