@@ -473,12 +473,23 @@ pub const unsafe fn swap_nonoverlapping<T>(x: *mut T, y: *mut T, count: usize) {
473
473
#[ inline]
474
474
#[ rustc_const_unstable( feature = "const_swap" , issue = "83163" ) ]
475
475
pub ( 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
+ }
482
493
}
483
494
484
495
// Direct swapping, for the cases not going through the block optimization.
0 commit comments