mirror of
https://github.com/opencv/opencv.git
synced 2026-07-31 00:03:03 +04:00
core:test Expand hal_intrin tests to support SIMD256
This commit is contained in:
@@ -154,7 +154,7 @@ using namespace CV_CPU_OPTIMIZATION_HAL_NAMESPACE;
|
||||
// but some of AVX2 intrinsics get v256_ prefix instead of v_, e.g. v256_load() vs v_load().
|
||||
// Correspondingly, the wide intrinsics (which are mapped to the "widest"
|
||||
// available instruction set) will get vx_ prefix
|
||||
// (and will be mapped to v256_ counterparts) (e.g. vx_load() => v245_load())
|
||||
// (and will be mapped to v256_ counterparts) (e.g. vx_load() => v256_load())
|
||||
#if CV_AVX2
|
||||
|
||||
#include "opencv2/core/hal/intrin_avx.hpp"
|
||||
@@ -214,14 +214,16 @@ CV_CPU_OPTIMIZATION_HAL_NAMESPACE_BEGIN
|
||||
inline vtyp vx_setzero_##short_typ() { return prefix##_setzero_##short_typ(); } \
|
||||
inline vtyp vx_##loadsfx(const typ* ptr) { return prefix##_##loadsfx(ptr); } \
|
||||
inline vtyp vx_##loadsfx##_aligned(const typ* ptr) { return prefix##_##loadsfx##_aligned(ptr); } \
|
||||
inline vtyp vx_##loadsfx##_low(const typ* ptr) { return prefix##_##loadsfx##_low(ptr); } \
|
||||
inline vtyp vx_##loadsfx##_halves(const typ* ptr0, const typ* ptr1) { return prefix##_##loadsfx##_halves(ptr0, ptr1); } \
|
||||
inline void vx_store(typ* ptr, const vtyp& v) { return v_store(ptr, v); } \
|
||||
inline void vx_store_aligned(typ* ptr, const vtyp& v) { return v_store_aligned(ptr, v); }
|
||||
|
||||
#define CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND(typ, wtyp, prefix) \
|
||||
inline wtyp vx_load_expand(const typ* ptr) { return prefix##_load_expand(ptr); }
|
||||
inline wtyp vx_load_expand(const typ* ptr) { return prefix##_load_expand(ptr); }
|
||||
|
||||
#define CV_INTRIN_DEFINE_WIDE_LOAD_EXPAND_Q(typ, qtyp, prefix) \
|
||||
inline qtyp vx_load_expand_q(const typ* ptr) { return prefix##_load_expand_q(ptr); }
|
||||
inline qtyp vx_load_expand_q(const typ* ptr) { return prefix##_load_expand_q(ptr); }
|
||||
|
||||
#define CV_INTRIN_DEFINE_WIDE_INTRIN_WITH_EXPAND(typ, vtyp, short_typ, wtyp, qtyp, prefix, loadsfx) \
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(typ, vtyp, short_typ, prefix, loadsfx) \
|
||||
@@ -316,7 +318,7 @@ template<typename _Tp> struct V_RegTraits
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN_ALL_TYPES(v256)
|
||||
CV_INTRIN_DEFINE_WIDE_INTRIN(double, v_float64, f64, v256, load)
|
||||
inline void vx_cleanup() { v256_cleanup(); }
|
||||
#elif CV_SIMD128
|
||||
#elif CV_SIMD128 || CV_SIMD128_CPP
|
||||
typedef v_uint8x16 v_uint8;
|
||||
typedef v_int8x16 v_int8;
|
||||
typedef v_uint16x8 v_uint16;
|
||||
|
||||
@@ -407,6 +407,11 @@ inline v_float16x16 v256_load_f16(const short* ptr)
|
||||
inline v_float16x16 v256_load_f16_aligned(const short* ptr)
|
||||
{ return v_float16x16(_mm256_load_si256((const __m256i*)ptr)); }
|
||||
|
||||
inline v_float16x16 v256_load_f16_low(const short* ptr)
|
||||
{ return v_float16x16(v256_load_low(ptr).val); }
|
||||
inline v_float16x16 v256_load_f16_halves(const short* ptr0, const short* ptr1)
|
||||
{ return v_float16x16(v256_load_halves(ptr0, ptr1).val); }
|
||||
|
||||
inline void v_store(short* ptr, const v_float16x16& a)
|
||||
{ _mm256_storeu_si256((__m256i*)ptr, a.val); }
|
||||
inline void v_store_aligned(short* ptr, const v_float16x16& a)
|
||||
@@ -819,94 +824,80 @@ OPENCV_HAL_IMPL_AVX_BIN_FUNC(v_max, v_float64x4, _mm256_max_pd)
|
||||
template<int imm>
|
||||
inline v_uint8x32 v_rotate_left(const v_uint8x32& a, const v_uint8x32& b)
|
||||
{
|
||||
enum {IMM_R = (16 - imm) & 0xFF};
|
||||
enum {IMM_R2 = (32 - imm) & 0xFF};
|
||||
|
||||
if (imm == 0) return a;
|
||||
if (imm == 32) return b;
|
||||
if (imm > 32) return v_uint8x32();
|
||||
|
||||
__m256i swap = _mm256_permute2x128_si256(a.val, b.val, 0x03);
|
||||
|
||||
switch(imm)
|
||||
{
|
||||
case 0: return a;
|
||||
case 32: return b;
|
||||
case 16: return v_uint8x32(swap);
|
||||
}
|
||||
|
||||
if (imm < 16) return v_uint8x32(_mm256_alignr_epi8(a.val, swap, 16 - imm));
|
||||
if (imm < 32) return v_uint8x32(_mm256_alignr_epi8(swap, b.val, 32 - imm));
|
||||
|
||||
return v_uint8x32();
|
||||
if (imm == 16) return v_uint8x32(swap);
|
||||
if (imm < 16) return v_uint8x32(_mm256_alignr_epi8(a.val, swap, IMM_R));
|
||||
return v_uint8x32(_mm256_alignr_epi8(swap, b.val, IMM_R2)); // imm < 32
|
||||
}
|
||||
|
||||
template<int imm>
|
||||
inline v_uint8x32 v_rotate_right(const v_uint8x32& a, const v_uint8x32& b)
|
||||
{
|
||||
enum {IMM_L = (imm - 16) & 0xFF};
|
||||
|
||||
if (imm == 0) return a;
|
||||
if (imm == 32) return b;
|
||||
if (imm > 32) return v_uint8x32();
|
||||
|
||||
__m256i swap = _mm256_permute2x128_si256(a.val, b.val, 0x21);
|
||||
|
||||
switch(imm)
|
||||
{
|
||||
case 0: return a;
|
||||
case 32: return b;
|
||||
case 16: return v_uint8x32(swap);
|
||||
}
|
||||
|
||||
if (imm < 16) return v_uint8x32(_mm256_alignr_epi8(swap, a.val, imm));
|
||||
if (imm < 32) return v_uint8x32(_mm256_alignr_epi8(b.val, swap, imm - 16));
|
||||
|
||||
return v_uint8x32();
|
||||
if (imm == 16) return v_uint8x32(swap);
|
||||
if (imm < 16) return v_uint8x32(_mm256_alignr_epi8(swap, a.val, imm));
|
||||
return v_uint8x32(_mm256_alignr_epi8(b.val, swap, IMM_L));
|
||||
}
|
||||
|
||||
template<int imm>
|
||||
inline v_uint8x32 v_rotate_left(const v_uint8x32& a)
|
||||
{
|
||||
v_uint8x32 res;
|
||||
enum {IMM_L = (imm - 16) & 0xFF};
|
||||
enum {IMM_R = (16 - imm) & 0xFF};
|
||||
|
||||
if (imm == 0) return a;
|
||||
if (imm > 32) return v_uint8x32();
|
||||
|
||||
// ESAC control[3] ? [127:0] = 0
|
||||
__m256i swapz = _mm256_permute2x128_si256(a.val, a.val, _MM_SHUFFLE(0, 0, 2, 0));
|
||||
|
||||
if (imm == 0)
|
||||
return a;
|
||||
if (imm == 16)
|
||||
res.val = swapz;
|
||||
else if (imm < 16)
|
||||
res.val = _mm256_alignr_epi8(a.val, swapz, 16 - imm);
|
||||
else if (imm < 32)
|
||||
res.val = _mm256_slli_si256(swapz, imm - 16);
|
||||
else
|
||||
return v_uint8x32();
|
||||
return res;
|
||||
if (imm == 16) return v_uint8x32(swapz);
|
||||
if (imm < 16) return v_uint8x32(_mm256_alignr_epi8(a.val, swapz, IMM_R));
|
||||
return v_uint8x32(_mm256_slli_si256(swapz, IMM_L));
|
||||
}
|
||||
|
||||
template<int imm>
|
||||
inline v_uint8x32 v_rotate_right(const v_uint8x32& a)
|
||||
{
|
||||
v_uint8x32 res;
|
||||
enum {IMM_L = (imm - 16) & 0xFF};
|
||||
|
||||
if (imm == 0) return a;
|
||||
if (imm > 32) return v_uint8x32();
|
||||
|
||||
// ESAC control[3] ? [127:0] = 0
|
||||
__m256i swapz = _mm256_permute2x128_si256(a.val, a.val, _MM_SHUFFLE(2, 0, 0, 1));
|
||||
|
||||
if (imm == 0)
|
||||
return a;
|
||||
if (imm == 16)
|
||||
res.val = swapz;
|
||||
else if (imm < 16)
|
||||
res.val = _mm256_alignr_epi8(swapz, a.val, imm);
|
||||
else if (imm < 32)
|
||||
res.val = _mm256_srli_si256(swapz, imm - 16);
|
||||
else
|
||||
return v_uint8x32();
|
||||
return res;
|
||||
if (imm == 16) return v_uint8x32(swapz);
|
||||
if (imm < 16) return v_uint8x32(_mm256_alignr_epi8(swapz, a.val, imm));
|
||||
return v_uint8x32(_mm256_srli_si256(swapz, IMM_L));
|
||||
}
|
||||
|
||||
#define OPENCV_HAL_IMPL_AVX_ROTATE_CAST(intrin, _Tpvec, cast) \
|
||||
template<int imm> \
|
||||
inline _Tpvec intrin(const _Tpvec& a, const _Tpvec& b) \
|
||||
{ \
|
||||
const int w = sizeof(typename _Tpvec::lane_type); \
|
||||
v_uint8x32 ret = intrin<imm*w>(v_reinterpret_as_u8(a), \
|
||||
v_reinterpret_as_u8(b)); \
|
||||
return _Tpvec(cast(ret.val)); \
|
||||
} \
|
||||
template<int imm> \
|
||||
inline _Tpvec intrin(const _Tpvec& a) \
|
||||
{ \
|
||||
const int w = sizeof(typename _Tpvec::lane_type); \
|
||||
v_uint8x32 ret = intrin<imm*w>(v_reinterpret_as_u8(a)); \
|
||||
return _Tpvec(cast(ret.val)); \
|
||||
#define OPENCV_HAL_IMPL_AVX_ROTATE_CAST(intrin, _Tpvec, cast) \
|
||||
template<int imm> \
|
||||
inline _Tpvec intrin(const _Tpvec& a, const _Tpvec& b) \
|
||||
{ \
|
||||
enum {IMMxW = imm * sizeof(typename _Tpvec::lane_type)}; \
|
||||
v_uint8x32 ret = intrin<IMMxW>(v_reinterpret_as_u8(a), \
|
||||
v_reinterpret_as_u8(b)); \
|
||||
return _Tpvec(cast(ret.val)); \
|
||||
} \
|
||||
template<int imm> \
|
||||
inline _Tpvec intrin(const _Tpvec& a) \
|
||||
{ \
|
||||
enum {IMMxW = imm * sizeof(typename _Tpvec::lane_type)}; \
|
||||
v_uint8x32 ret = intrin<IMMxW>(v_reinterpret_as_u8(a)); \
|
||||
return _Tpvec(cast(ret.val)); \
|
||||
}
|
||||
|
||||
#define OPENCV_HAL_IMPL_AVX_ROTATE(_Tpvec) \
|
||||
|
||||
@@ -319,6 +319,9 @@ static inline void cv_vst1_f16(void* ptr, float16x4_t a)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef vdup_n_f16
|
||||
#define vdup_n_f16(v) (float16x4_t){v, v, v, v}
|
||||
#endif
|
||||
|
||||
struct v_float16x8
|
||||
{
|
||||
@@ -889,6 +892,11 @@ inline v_float16x8 v_load_f16(const short* ptr)
|
||||
inline v_float16x8 v_load_f16_aligned(const short* ptr)
|
||||
{ return v_float16x8(cv_vld1q_f16(ptr)); }
|
||||
|
||||
inline v_float16x8 v_load_f16_low(const short* ptr)
|
||||
{ return v_float16x8(vcombine_f16(cv_vld1_f16(ptr), vdup_n_f16((float16_t)0))); }
|
||||
inline v_float16x8 v_load_f16_halves(const short* ptr0, const short* ptr1)
|
||||
{ return v_float16x8(vcombine_f16(cv_vld1_f16(ptr0), cv_vld1_f16(ptr1))); }
|
||||
|
||||
inline void v_store(short* ptr, const v_float16x8& a)
|
||||
{ cv_vst1q_f16(ptr, a.val); }
|
||||
inline void v_store_aligned(short* ptr, const v_float16x8& a)
|
||||
|
||||
@@ -1308,6 +1308,11 @@ inline v_float16x8 v_load_f16(const short* ptr)
|
||||
inline v_float16x8 v_load_f16_aligned(const short* ptr)
|
||||
{ return v_float16x8(_mm_load_si128((const __m128i*)ptr)); }
|
||||
|
||||
inline v_float16x8 v_load_f16_low(const short* ptr)
|
||||
{ return v_float16x8(v_load_low(ptr).val); }
|
||||
inline v_float16x8 v_load_f16_halves(const short* ptr0, const short* ptr1)
|
||||
{ return v_float16x8(v_load_halves(ptr0, ptr1).val); }
|
||||
|
||||
inline void v_store(short* ptr, const v_float16x8& a)
|
||||
{ _mm_storeu_si128((__m128i*)ptr, a.val); }
|
||||
inline void v_store_aligned(short* ptr, const v_float16x8& a)
|
||||
|
||||
Reference in New Issue
Block a user