diff options
| author | Eduard-Mihai Burtescu <eddyb@lyken.rs> | 2021-03-11 16:33:34 +0200 |
|---|---|---|
| committer | Eduard-Mihai Burtescu <eddyb@lyken.rs> | 2021-04-04 22:26:27 +0300 |
| commit | bc6af97ed0088304a2430b74b47c182c65ce0b9f (patch) | |
| tree | d03efb41b61daacc5db0256f368c6bb3a39e9931 | |
| parent | 3c3d3ddde967f66938966d6d557a3a4fe4d267ff (diff) | |
| download | rust-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.rs | 23 |
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. |
