about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard-Mihai Burtescu <eddyb@lyken.rs>2021-03-11 16:33:34 +0200
committerEduard-Mihai Burtescu <eddyb@lyken.rs>2021-04-04 22:26:27 +0300
commitbc6af97ed0088304a2430b74b47c182c65ce0b9f (patch)
treed03efb41b61daacc5db0256f368c6bb3a39e9931
parent3c3d3ddde967f66938966d6d557a3a4fe4d267ff (diff)
downloadrust-bc6af97ed0088304a2430b74b47c182c65ce0b9f.tar.gz
rust-bc6af97ed0088304a2430b74b47c182c65ce0b9f.zip
core: disable `ptr::swap_nonoverlapping_one`'s block optimization on SPIR-V.
-rw-r--r--library/core/src/ptr/mod.rs23
1 files changed, 17 insertions, 6 deletions
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 15aa4769697..f673a6fd178 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -473,12 +473,23 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
 #[inline]
 #[rustc_const_unstable(feature = "const_swap", issue = "83163")]
 pub(crate) const unsafe fn swap_nonoverlapping_one<T>(x: *mut T, y: *mut T) {
-    // Only apply the block optimization in `swap_nonoverlapping_bytes` for types
-    // at least as large as the block size, to avoid pessimizing codegen.
-    if mem::size_of::<T>() >= 32 {
-        // SAFETY: the caller must uphold the safety contract for `swap_nonoverlapping`.
-        unsafe { swap_nonoverlapping(x, y, 1) };
-        return;
+    // NOTE(eddyb) SPIR-V's Logical addressing model doesn't allow for arbitrary
+    // reinterpretation of values as (chunkable) byte arrays, and the loop in the
+    // block optimization in `swap_nonoverlapping_bytes` is hard to rewrite back
+    // into the (unoptimized) direct swapping implementation, so we disable it.
+    // FIXME(eddyb) the block optimization also prevents MIR optimizations from
+    // understanding `mem::replace`, `Option::take`, etc. - a better overall
+    // solution might be to make `swap_nonoverlapping` into an intrinsic, which
+    // a backend can choose to implement using the block optimization, or not.
+    #[cfg(not(target_arch = "spirv"))]
+    {
+        // Only apply the block optimization in `swap_nonoverlapping_bytes` for types
+        // at least as large as the block size, to avoid pessimizing codegen.
+        if mem::size_of::<T>() >= 32 {
+            // SAFETY: the caller must uphold the safety contract for `swap_nonoverlapping`.
+            unsafe { swap_nonoverlapping(x, y, 1) };
+            return;
+        }
     }
 
     // Direct swapping, for the cases not going through the block optimization.