@@ -460,6 +460,48 @@ namespace xsimd
460460 return (typename batch_bool<double , A>::register_type)_mm256_cmp_pd_mask (self, self, _CMP_UNORD_Q);
461461 }
462462
463+ // bitwise_rshift — signed int64 uses the native EVEX arithmetic shift
464+ // (VPSRAQ / VPSRAVQ, lat 1 / CPI 0.5). Every other width/sign keeps the
465+ // inherited avx2 codegen (srai/srav for 32-bit, srli for unsigned 64).
466+ template <class A , class T , class = std::enable_if_t <std::is_integral<T>::value>>
467+ XSIMD_INLINE batch<T, A> bitwise_rshift (batch<T, A> const & self, int32_t other, requires_arch<avx512vl_256>) noexcept
468+ {
469+ XSIMD_IF_CONSTEXPR (std::is_signed<T>::value && sizeof (T) == 8 )
470+ {
471+ return _mm256_srai_epi64 (self, other);
472+ }
473+ else
474+ {
475+ return bitwise_rshift (self, other, avx2 {});
476+ }
477+ }
478+ template <size_t shift, class A , class T , class = std::enable_if_t <std::is_integral<T>::value>>
479+ XSIMD_INLINE batch<T, A> bitwise_rshift (batch<T, A> const & self, requires_arch<avx512vl_256>) noexcept
480+ {
481+ constexpr auto bits = std::numeric_limits<T>::digits + std::numeric_limits<T>::is_signed;
482+ static_assert (shift < bits, " Shift amount must be less than the number of bits in T" );
483+ XSIMD_IF_CONSTEXPR (std::is_signed<T>::value && sizeof (T) == 8 )
484+ {
485+ return _mm256_srai_epi64 (self, shift);
486+ }
487+ else
488+ {
489+ return bitwise_rshift<shift>(self, avx2 {});
490+ }
491+ }
492+ template <class A , class T , class = std::enable_if_t <std::is_integral<T>::value>>
493+ XSIMD_INLINE batch<T, A> bitwise_rshift (batch<T, A> const & self, batch<T, A> const & other, requires_arch<avx512vl_256>) noexcept
494+ {
495+ XSIMD_IF_CONSTEXPR (std::is_signed<T>::value && sizeof (T) == 8 )
496+ {
497+ return _mm256_srav_epi64 (self, other);
498+ }
499+ else
500+ {
501+ return bitwise_rshift (self, other, avx2 {});
502+ }
503+ }
504+
463505 // rotl
464506 template <class A , class T , class = std::enable_if_t <std::is_integral<T>::value>>
465507 XSIMD_INLINE batch<T, A> rotl (batch<T, A> const & self, batch<T, A> const & other, requires_arch<avx512vl_256>) noexcept
@@ -505,18 +547,18 @@ namespace xsimd
505547 template <class A , class T , class = std::enable_if_t <std::is_integral<T>::value>>
506548 XSIMD_INLINE batch<T, A> rotr (batch<T, A> const & self, batch<T, A> const & other, requires_arch<avx512vl_256>) noexcept
507549 {
508- XSIMD_IF_CONSTEXPR (std::is_unsigned<T>::value )
550+ XSIMD_IF_CONSTEXPR (sizeof (T) == 4 )
509551 {
510- XSIMD_IF_CONSTEXPR (sizeof (T) == 4 )
511- {
512- return _mm256_rorv_epi32 (self, other);
513- }
514- else XSIMD_IF_CONSTEXPR (sizeof (T) == 8 )
515- {
516- return _mm256_rorv_epi64 (self, other);
517- }
552+ return _mm256_rorv_epi32 (self, other);
553+ }
554+ else XSIMD_IF_CONSTEXPR (sizeof (T) == 8 )
555+ {
556+ return _mm256_rorv_epi64 (self, other);
557+ }
558+ else
559+ {
560+ return rotr (self, other, avx2 {});
518561 }
519- return rotr (self, other, avx2 {});
520562 }
521563 template <class A , class T , class = std::enable_if_t <std::is_integral<T>::value>>
522564 XSIMD_INLINE batch<T, A> rotr (batch<T, A> const & self, int32_t other, requires_arch<avx512vl_256>) noexcept
@@ -529,18 +571,83 @@ namespace xsimd
529571 {
530572 constexpr auto bits = std::numeric_limits<T>::digits + std::numeric_limits<T>::is_signed;
531573 static_assert (count < bits, " Count must be less than the number of bits in T" );
532- XSIMD_IF_CONSTEXPR (std::is_unsigned<T>::value )
574+ XSIMD_IF_CONSTEXPR (sizeof (T) == 4 )
533575 {
534- XSIMD_IF_CONSTEXPR (sizeof (T) == 4 )
535- {
536- return _mm256_ror_epi32 (self, count);
537- }
538- else XSIMD_IF_CONSTEXPR (sizeof (T) == 8 )
539- {
540- return _mm256_ror_epi64 (self, count);
541- }
576+ return _mm256_ror_epi32 (self, count);
542577 }
543- return rotr<count>(self, avx2 {});
578+ else XSIMD_IF_CONSTEXPR (sizeof (T) == 8 )
579+ {
580+ return _mm256_ror_epi64 (self, count);
581+ }
582+ else
583+ {
584+ return rotr<count>(self, avx2 {});
585+ }
586+ }
587+
588+ // compress — native EVEX VPCOMPRESS{PS,PD,Q,D} for the widths with VL
589+ // forms. 8/16-bit need AVX512_VBMI2, so they fall through to common{}.
590+ template <class A >
591+ XSIMD_INLINE batch<float , A> compress (batch<float , A> const & self, batch_bool<float , A> const & mask, requires_arch<avx512vl_256>) noexcept
592+ {
593+ return _mm256_maskz_compress_ps (mask.mask (), self);
594+ }
595+ template <class A >
596+ XSIMD_INLINE batch<double , A> compress (batch<double , A> const & self, batch_bool<double , A> const & mask, requires_arch<avx512vl_256>) noexcept
597+ {
598+ return _mm256_maskz_compress_pd (mask.mask (), self);
599+ }
600+ template <class A >
601+ 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
602+ {
603+ return _mm256_maskz_compress_epi32 (mask.mask (), self);
604+ }
605+ template <class A >
606+ 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
607+ {
608+ return _mm256_maskz_compress_epi32 (mask.mask (), self);
609+ }
610+ template <class A >
611+ 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
612+ {
613+ return _mm256_maskz_compress_epi64 (mask.mask (), self);
614+ }
615+ template <class A >
616+ 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
617+ {
618+ return _mm256_maskz_compress_epi64 (mask.mask (), self);
619+ }
620+
621+ // expand
622+ template <class A >
623+ XSIMD_INLINE batch<float , A> expand (batch<float , A> const & self, batch_bool<float , A> const & mask, requires_arch<avx512vl_256>) noexcept
624+ {
625+ return _mm256_maskz_expand_ps (mask.mask (), self);
626+ }
627+ template <class A >
628+ XSIMD_INLINE batch<double , A> expand (batch<double , A> const & self, batch_bool<double , A> const & mask, requires_arch<avx512vl_256>) noexcept
629+ {
630+ return _mm256_maskz_expand_pd (mask.mask (), self);
631+ }
632+ template <class A >
633+ 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
634+ {
635+ return _mm256_maskz_expand_epi32 (mask.mask (), self);
636+ }
637+ template <class A >
638+ 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
639+ {
640+ return _mm256_maskz_expand_epi32 (mask.mask (), self);
641+ }
642+ template <class A >
643+ 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
644+ {
645+ return _mm256_maskz_expand_epi64 (mask.mask (), self);
646+ }
647+ template <class A >
648+ 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
649+ {
650+ return _mm256_maskz_expand_epi64 (mask.mask (), self);
544651 }
545652
546653 // all
0 commit comments