Consider https://rust.godbolt.org/z/dY8schnG4
Input:
#![feature(portable_simd)]
use std::simd::ToBytes;
use core::simd::u8x16;
use core::simd::u16x8;
use core::arch::x86_64::_mm_packus_epi16;
#[inline(always)]
pub fn simd_pack_sse2(a: u16x8, b: u16x8) -> u8x16 {
unsafe {
_mm_packus_epi16(a.into(), b.into()).into()
}
}
#[inline(always)]
pub fn simd_pack_portable(a: u16x8, b: u16x8) -> u8x16 {
let first: u8x16 = a.to_le_bytes();
let second: u8x16 = b.to_le_bytes();
let (ret, _) = first.deinterleave(second);
ret
}
#[inline(always)]
fn split_u16_stride(stride: &[u16; 16]) -> (&[u16; 8], &[u16; 8]) {
let (chunks, _) = stride.as_chunks::<8>();
(&chunks[0], &chunks[1])
}
#[unsafe(no_mangle)]
pub fn pack_portable(src: &[u16; 16], dst: &mut [u8; 16]) {
let (a, b) = split_u16_stride(src);
let packed = simd_pack_portable((*a).into(), (*b).into());
*dst = packed.to_array();
}
#[unsafe(no_mangle)]
pub fn pack_sse2(src: &[u16; 16], dst: &mut [u8; 16]) {
let (a, b) = split_u16_stride(src);
let packed = simd_pack_sse2((*a).into(), (*b).into());
*dst = packed.to_array();
}
Output:
.LCPI0_0:
.short 255
.short 255
.short 255
.short 255
.short 255
.short 255
.short 255
.short 255
pack_portable:
movdqu xmm0, xmmword ptr [rdi]
movdqu xmm1, xmmword ptr [rdi + 16]
movdqa xmm2, xmmword ptr [rip + .LCPI0_0]
pand xmm1, xmm2
pand xmm0, xmm2
packuswb xmm0, xmm1
movdqu xmmword ptr [rsi], xmm0
ret
.LCPI1_0:
.short 255
.short 255
.short 255
.short 255
.short 255
.short 255
.short 255
.short 255
pack_sse2:
movdqu xmm0, xmmword ptr [rdi]
movdqu xmm1, xmmword ptr [rdi + 16]
pxor xmm2, xmm2
pmaxsw xmm0, xmm2
movdqa xmm3, xmmword ptr [rip + .LCPI1_0]
pminsw xmm0, xmm3
pmaxsw xmm1, xmm2
pminsw xmm1, xmm3
packuswb xmm0, xmm1
movdqu xmmword ptr [rsi], xmm0
ret
Expected pack_sse2 to compile like this instead:
pack_sse2:
movdqu xmm0, xmmword ptr [rdi]
movdqu xmm1, xmmword ptr [rdi + 16]
packuswb xmm0, xmm1
movdqu xmmword ptr [rsi], xmm0
ret
By code inspection, #2033 is the likely regressor. It seems problematic that it landed without tests to ensure that the optimizer actually recognizes the pattern.
Consider https://rust.godbolt.org/z/dY8schnG4
Input:
Output:
Expected
pack_sse2to compile like this instead:By code inspection, #2033 is the likely regressor. It seems problematic that it landed without tests to ensure that the optimizer actually recognizes the pattern.