@@ -473,12 +473,23 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
473473#[ inline]
474474#[ rustc_const_unstable( feature = "const_swap" , issue = "83163" ) ]
475475pub ( crate ) const unsafe fn swap_nonoverlapping_one < T > ( x : * mut T , y : * mut T ) {
476- // Only apply the block optimization in `swap_nonoverlapping_bytes` for types
477- // at least as large as the block size, to avoid pessimizing codegen.
478- if mem:: size_of :: < T > ( ) >= 32 {
479- // SAFETY: the caller must uphold the safety contract for `swap_nonoverlapping`.
480- unsafe { swap_nonoverlapping ( x, y, 1 ) } ;
481- return ;
476+ // NOTE(eddyb) SPIR-V's Logical addressing model doesn't allow for arbitrary
477+ // reinterpretation of values as (chunkable) byte arrays, and the loop in the
478+ // block optimization in `swap_nonoverlapping_bytes` is hard to rewrite back
479+ // into the (unoptimized) direct swapping implementation, so we disable it.
480+ // FIXME(eddyb) the block optimization also prevents MIR optimizations from
481+ // understanding `mem::replace`, `Option::take`, etc. - a better overall
482+ // solution might be to make `swap_nonoverlapping` into an intrinsic, which
483+ // a backend can choose to implement using the block optimization, or not.
484+ #[ cfg( not( target_arch = "spirv" ) ) ]
485+ {
486+ // Only apply the block optimization in `swap_nonoverlapping_bytes` for types
487+ // at least as large as the block size, to avoid pessimizing codegen.
488+ if mem:: size_of :: < T > ( ) >= 32 {
489+ // SAFETY: the caller must uphold the safety contract for `swap_nonoverlapping`.
490+ unsafe { swap_nonoverlapping ( x, y, 1 ) } ;
491+ return ;
492+ }
482493 }
483494
484495 // Direct swapping, for the cases not going through the block optimization.
0 commit comments