diff --git a/include/xsimd/arch/xsimd_lasx.hpp b/include/xsimd/arch/xsimd_lasx.hpp index 55aa982b7..0b10360fd 100644 --- a/include/xsimd/arch/xsimd_lasx.hpp +++ b/include/xsimd/arch/xsimd_lasx.hpp @@ -1106,7 +1106,29 @@ namespace xsimd XSIMD_INLINE std::enable_if_t, batch> swizzle(batch const& self, batch_constant mask, requires_arch) noexcept { - return swizzle(self, mask.as_batch(), lasx {}); + if constexpr (detail::is_identity(mask)) + return self; + else if constexpr (sizeof(T) == 1 + && (!detail::is_cross_lane(mask) + || detail::is_only_from_lo(mask) + || detail::is_only_from_hi(mask))) + { + constexpr auto lane_mask = mask % std::integral_constant(); + auto const self_int = detail::lasx_to_int(self); + + __m256i src; + if constexpr (!detail::is_cross_lane(mask)) + src = self_int; + else if constexpr (detail::is_only_from_lo(mask)) + src = __lasx_xvpermi_q(self_int, self_int, 0x00); + else + src = __lasx_xvpermi_q(self_int, self_int, 0x11); + + return detail::lasx_from_int( + __lasx_xvshuf_b(src, src, detail::lasx_to_int(lane_mask.as_batch()))); + } + else + return swizzle(self, mask.as_batch(), lasx {}); } } } diff --git a/include/xsimd/arch/xsimd_lsx.hpp b/include/xsimd/arch/xsimd_lsx.hpp index 598d01e9f..7f1ca30fe 100644 --- a/include/xsimd/arch/xsimd_lsx.hpp +++ b/include/xsimd/arch/xsimd_lsx.hpp @@ -999,7 +999,10 @@ namespace xsimd XSIMD_INLINE std::enable_if_t, batch> swizzle(batch const& self, batch_constant mask, requires_arch) noexcept { - return swizzle(self, mask.as_batch(), lsx {}); + if constexpr (detail::is_identity(mask)) + return self; + else + return swizzle(self, mask.as_batch(), lsx {}); } } }