@@ -494,6 +494,48 @@ namespace xsimd
494494 return (typename batch_bool<double , A>::register_type)_mm256_cmp_pd_mask (self, self, _CMP_UNORD_Q);
495495 }
496496
497+ // bitwise_rshift — signed int64 uses the native EVEX arithmetic shift
498+ // (VPSRAQ / VPSRAVQ, lat 1 / CPI 0.5). Every other width/sign keeps the
499+ // inherited avx2 codegen (srai/srav for 32-bit, srli for unsigned 64).
500+ template <class A , class T , class = std::enable_if_t <std::is_integral<T>::value>>
501+ XSIMD_INLINE batch<T, A> bitwise_rshift (batch<T, A> const & self, int32_t other, requires_arch<avx512vl_256>) noexcept
502+ {
503+ XSIMD_IF_CONSTEXPR (std::is_signed<T>::value && sizeof (T) == 8 )
504+ {
505+ return _mm256_srai_epi64 (self, other);
506+ }
507+ else
508+ {
509+ return bitwise_rshift (self, other, avx2 {});
510+ }
511+ }
512+ template <size_t shift, class A , class T , class = std::enable_if_t <std::is_integral<T>::value>>
513+ XSIMD_INLINE batch<T, A> bitwise_rshift (batch<T, A> const & self, requires_arch<avx512vl_256>) noexcept
514+ {
515+ constexpr auto bits = std::numeric_limits<T>::digits + std::numeric_limits<T>::is_signed;
516+ static_assert (shift < bits, " Shift amount must be less than the number of bits in T" );
517+ XSIMD_IF_CONSTEXPR (std::is_signed<T>::value && sizeof (T) == 8 )
518+ {
519+ return _mm256_srai_epi64 (self, shift);
520+ }
521+ else
522+ {
523+ return bitwise_rshift<shift>(self, avx2 {});
524+ }
525+ }
526+ template <class A , class T , class = std::enable_if_t <std::is_integral<T>::value>>
527+ XSIMD_INLINE batch<T, A> bitwise_rshift (batch<T, A> const & self, batch<T, A> const & other, requires_arch<avx512vl_256>) noexcept
528+ {
529+ XSIMD_IF_CONSTEXPR (std::is_signed<T>::value && sizeof (T) == 8 )
530+ {
531+ return _mm256_srav_epi64 (self, other);
532+ }
533+ else
534+ {
535+ return bitwise_rshift (self, other, avx2 {});
536+ }
537+ }
538+
497539 // rotl
498540 template <class A , class T , class = std::enable_if_t <std::is_integral<T>::value>>
499541 XSIMD_INLINE batch<T, A> rotl (batch<T, A> const & self, batch<T, A> const & other, requires_arch<avx512vl_256>) noexcept
@@ -539,18 +581,18 @@ namespace xsimd
539581 template <class A , class T , class = std::enable_if_t <std::is_integral<T>::value>>
540582 XSIMD_INLINE batch<T, A> rotr (batch<T, A> const & self, batch<T, A> const & other, requires_arch<avx512vl_256>) noexcept
541583 {
542- XSIMD_IF_CONSTEXPR (std::is_unsigned<T>::value )
584+ XSIMD_IF_CONSTEXPR (sizeof (T) == 4 )
543585 {
544- XSIMD_IF_CONSTEXPR (sizeof (T) == 4 )
545- {
546- return _mm256_rorv_epi32 (self, other);
547- }
548- else XSIMD_IF_CONSTEXPR (sizeof (T) == 8 )
549- {
550- return _mm256_rorv_epi64 (self, other);
551- }
586+ return _mm256_rorv_epi32 (self, other);
587+ }
588+ else XSIMD_IF_CONSTEXPR (sizeof (T) == 8 )
589+ {
590+ return _mm256_rorv_epi64 (self, other);
591+ }
592+ else
593+ {
594+ return rotr (self, other, avx2 {});
552595 }
553- return rotr (self, other, avx2 {});
554596 }
555597 template <class A , class T , class = std::enable_if_t <std::is_integral<T>::value>>
556598 XSIMD_INLINE batch<T, A> rotr (batch<T, A> const & self, int32_t other, requires_arch<avx512vl_256>) noexcept
@@ -563,18 +605,83 @@ namespace xsimd
563605 {
564606 constexpr auto bits = std::numeric_limits<T>::digits + std::numeric_limits<T>::is_signed;
565607 static_assert (count < bits, " Count must be less than the number of bits in T" );
566- XSIMD_IF_CONSTEXPR (std::is_unsigned<T>::value )
608+ XSIMD_IF_CONSTEXPR (sizeof (T) == 4 )
567609 {
568- XSIMD_IF_CONSTEXPR (sizeof (T) == 4 )
569- {
570- return _mm256_ror_epi32 (self, count);
571- }
572- else XSIMD_IF_CONSTEXPR (sizeof (T) == 8 )
573- {
574- return _mm256_ror_epi64 (self, count);
575- }
610+ return _mm256_ror_epi32 (self, count);
576611 }
577- return rotr<count>(self, avx2 {});
612+ else XSIMD_IF_CONSTEXPR (sizeof (T) == 8 )
613+ {
614+ return _mm256_ror_epi64 (self, count);
615+ }
616+ else
617+ {
618+ return rotr<count>(self, avx2 {});
619+ }
620+ }
621+
622+ // compress — native EVEX VPCOMPRESS{PS,PD,Q,D} for the widths with VL
623+ // forms. 8/16-bit need AVX512_VBMI2, so they fall through to common{}.
624+ template <class A >
625+ XSIMD_INLINE batch<float , A> compress (batch<float , A> const & self, batch_bool<float , A> const & mask, requires_arch<avx512vl_256>) noexcept
626+ {
627+ return _mm256_maskz_compress_ps (mask.mask (), self);
628+ }
629+ template <class A >
630+ XSIMD_INLINE batch<double , A> compress (batch<double , A> const & self, batch_bool<double , A> const & mask, requires_arch<avx512vl_256>) noexcept
631+ {
632+ return _mm256_maskz_compress_pd (mask.mask (), self);
633+ }
634+ template <class A >
635+ XSIMD_INLINE batch<int32_t , A> compress (batch<int32_t , A> const & self, batch_bool<int32_t , A> const & mask, requires_arch<avx512vl_256>) noexcept
636+ {
637+ return _mm256_maskz_compress_epi32 (mask.mask (), self);
638+ }
639+ template <class A >
640+ XSIMD_INLINE batch<uint32_t , A> compress (batch<uint32_t , A> const & self, batch_bool<uint32_t , A> const & mask, requires_arch<avx512vl_256>) noexcept
641+ {
642+ return _mm256_maskz_compress_epi32 (mask.mask (), self);
643+ }
644+ template <class A >
645+ XSIMD_INLINE batch<int64_t , A> compress (batch<int64_t , A> const & self, batch_bool<int64_t , A> const & mask, requires_arch<avx512vl_256>) noexcept
646+ {
647+ return _mm256_maskz_compress_epi64 (mask.mask (), self);
648+ }
649+ template <class A >
650+ XSIMD_INLINE batch<uint64_t , A> compress (batch<uint64_t , A> const & self, batch_bool<uint64_t , A> const & mask, requires_arch<avx512vl_256>) noexcept
651+ {
652+ return _mm256_maskz_compress_epi64 (mask.mask (), self);
653+ }
654+
655+ // expand
656+ template <class A >
657+ XSIMD_INLINE batch<float , A> expand (batch<float , A> const & self, batch_bool<float , A> const & mask, requires_arch<avx512vl_256>) noexcept
658+ {
659+ return _mm256_maskz_expand_ps (mask.mask (), self);
660+ }
661+ template <class A >
662+ XSIMD_INLINE batch<double , A> expand (batch<double , A> const & self, batch_bool<double , A> const & mask, requires_arch<avx512vl_256>) noexcept
663+ {
664+ return _mm256_maskz_expand_pd (mask.mask (), self);
665+ }
666+ template <class A >
667+ XSIMD_INLINE batch<int32_t , A> expand (batch<int32_t , A> const & self, batch_bool<int32_t , A> const & mask, requires_arch<avx512vl_256>) noexcept
668+ {
669+ return _mm256_maskz_expand_epi32 (mask.mask (), self);
670+ }
671+ template <class A >
672+ XSIMD_INLINE batch<uint32_t , A> expand (batch<uint32_t , A> const & self, batch_bool<uint32_t , A> const & mask, requires_arch<avx512vl_256>) noexcept
673+ {
674+ return _mm256_maskz_expand_epi32 (mask.mask (), self);
675+ }
676+ template <class A >
677+ XSIMD_INLINE batch<int64_t , A> expand (batch<int64_t , A> const & self, batch_bool<int64_t , A> const & mask, requires_arch<avx512vl_256>) noexcept
678+ {
679+ return _mm256_maskz_expand_epi64 (mask.mask (), self);
680+ }
681+ template <class A >
682+ XSIMD_INLINE batch<uint64_t , A> expand (batch<uint64_t , A> const & self, batch_bool<uint64_t , A> const & mask, requires_arch<avx512vl_256>) noexcept
683+ {
684+ return _mm256_maskz_expand_epi64 (mask.mask (), self);
578685 }
579686
580687 // all
0 commit comments