mirror of
https://gitlab.com/libeigen/eigen.git
synced 2025-09-23 23:03:15 +08:00
fix NEON port, use vget_lane_*() instead of temporary variables (saves extra
load/store), following advice by Josh Bleecher Snyder <josharian@gmail.com>. Also implement pmadd() using vmla instead of nested padd/pmul.
This commit is contained in:
parent
9a97dac4d9
commit
f737536744
@ -252,15 +252,12 @@ template<> EIGEN_STRONG_INLINE Packet4i pabs(const Packet4i& a) { return vabsq_s
|
|||||||
template<> EIGEN_STRONG_INLINE float predux<Packet4f>(const Packet4f& a)
|
template<> EIGEN_STRONG_INLINE float predux<Packet4f>(const Packet4f& a)
|
||||||
{
|
{
|
||||||
float32x2_t a_lo, a_hi, sum;
|
float32x2_t a_lo, a_hi, sum;
|
||||||
float s[2];
|
|
||||||
|
|
||||||
a_lo = vget_low_f32(a);
|
a_lo = vget_low_f32(a);
|
||||||
a_hi = vget_high_f32(a);
|
a_hi = vget_high_f32(a);
|
||||||
sum = vpadd_f32(a_lo, a_hi);
|
sum = vpadd_f32(a_lo, a_hi);
|
||||||
sum = vpadd_f32(sum, sum);
|
sum = vpadd_f32(sum, sum);
|
||||||
vst1_f32(s, sum);
|
return vget_lane_f32(sum, 0);
|
||||||
|
|
||||||
return s[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet4f preduxp<Packet4f>(const Packet4f* vecs)
|
template<> EIGEN_STRONG_INLINE Packet4f preduxp<Packet4f>(const Packet4f* vecs)
|
||||||
@ -286,15 +283,12 @@ template<> EIGEN_STRONG_INLINE Packet4f preduxp<Packet4f>(const Packet4f* vecs)
|
|||||||
template<> EIGEN_STRONG_INLINE int predux<Packet4i>(const Packet4i& a)
|
template<> EIGEN_STRONG_INLINE int predux<Packet4i>(const Packet4i& a)
|
||||||
{
|
{
|
||||||
int32x2_t a_lo, a_hi, sum;
|
int32x2_t a_lo, a_hi, sum;
|
||||||
int32_t s[2];
|
|
||||||
|
|
||||||
a_lo = vget_low_s32(a);
|
a_lo = vget_low_s32(a);
|
||||||
a_hi = vget_high_s32(a);
|
a_hi = vget_high_s32(a);
|
||||||
sum = vpadd_s32(a_lo, a_hi);
|
sum = vpadd_s32(a_lo, a_hi);
|
||||||
sum = vpadd_s32(sum, sum);
|
sum = vpadd_s32(sum, sum);
|
||||||
vst1_s32(s, sum);
|
return vget_lane_s32(sum, 0);
|
||||||
|
|
||||||
return s[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE Packet4i preduxp<Packet4i>(const Packet4i* vecs)
|
template<> EIGEN_STRONG_INLINE Packet4i preduxp<Packet4i>(const Packet4i* vecs)
|
||||||
@ -322,7 +316,6 @@ template<> EIGEN_STRONG_INLINE Packet4i preduxp<Packet4i>(const Packet4i* vecs)
|
|||||||
template<> EIGEN_STRONG_INLINE float predux_mul<Packet4f>(const Packet4f& a)
|
template<> EIGEN_STRONG_INLINE float predux_mul<Packet4f>(const Packet4f& a)
|
||||||
{
|
{
|
||||||
float32x2_t a_lo, a_hi, prod;
|
float32x2_t a_lo, a_hi, prod;
|
||||||
float s[2];
|
|
||||||
|
|
||||||
// Get a_lo = |a1|a2| and a_hi = |a3|a4|
|
// Get a_lo = |a1|a2| and a_hi = |a3|a4|
|
||||||
a_lo = vget_low_f32(a);
|
a_lo = vget_low_f32(a);
|
||||||
@ -331,14 +324,12 @@ template<> EIGEN_STRONG_INLINE float predux_mul<Packet4f>(const Packet4f& a)
|
|||||||
prod = vmul_f32(a_lo, a_hi);
|
prod = vmul_f32(a_lo, a_hi);
|
||||||
// Multiply prod with its swapped value |a2*a4|a1*a3|
|
// Multiply prod with its swapped value |a2*a4|a1*a3|
|
||||||
prod = vmul_f32(prod, vrev64_f32(prod));
|
prod = vmul_f32(prod, vrev64_f32(prod));
|
||||||
vst1_f32(s, prod);
|
|
||||||
|
|
||||||
return s[0];
|
return vget_lane_f32(prod, 0);
|
||||||
}
|
}
|
||||||
template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a)
|
template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a)
|
||||||
{
|
{
|
||||||
int32x2_t a_lo, a_hi, prod;
|
int32x2_t a_lo, a_hi, prod;
|
||||||
int32_t s[2];
|
|
||||||
|
|
||||||
// Get a_lo = |a1|a2| and a_hi = |a3|a4|
|
// Get a_lo = |a1|a2| and a_hi = |a3|a4|
|
||||||
a_lo = vget_low_s32(a);
|
a_lo = vget_low_s32(a);
|
||||||
@ -347,29 +338,26 @@ template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a)
|
|||||||
prod = vmul_s32(a_lo, a_hi);
|
prod = vmul_s32(a_lo, a_hi);
|
||||||
// Multiply prod with its swapped value |a2*a4|a1*a3|
|
// Multiply prod with its swapped value |a2*a4|a1*a3|
|
||||||
prod = vmul_s32(prod, vrev64_s32(prod));
|
prod = vmul_s32(prod, vrev64_s32(prod));
|
||||||
vst1_s32(s, prod);
|
|
||||||
|
|
||||||
return s[0];
|
return vget_lane_s32(prod, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// min
|
// min
|
||||||
template<> EIGEN_STRONG_INLINE float predux_min<Packet4f>(const Packet4f& a)
|
template<> EIGEN_STRONG_INLINE float predux_min<Packet4f>(const Packet4f& a)
|
||||||
{
|
{
|
||||||
float32x2_t a_lo, a_hi, min;
|
float32x2_t a_lo, a_hi, min;
|
||||||
float s[2];
|
|
||||||
|
|
||||||
a_lo = vget_low_f32(a);
|
a_lo = vget_low_f32(a);
|
||||||
a_hi = vget_high_f32(a);
|
a_hi = vget_high_f32(a);
|
||||||
min = vpmin_f32(a_lo, a_hi);
|
min = vpmin_f32(a_lo, a_hi);
|
||||||
min = vpmin_f32(min, min);
|
min = vpmin_f32(min, min);
|
||||||
vst1_f32(s, min);
|
|
||||||
|
|
||||||
return s[0];
|
return vget_lane_f32(min, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE int predux_min<Packet4i>(const Packet4i& a)
|
template<> EIGEN_STRONG_INLINE int predux_min<Packet4i>(const Packet4i& a)
|
||||||
{
|
{
|
||||||
int32x2_t a_lo, a_hi, min;
|
int32x2_t a_lo, a_hi, min;
|
||||||
int32_t s[2];
|
|
||||||
|
|
||||||
a_lo = vget_low_s32(a);
|
a_lo = vget_low_s32(a);
|
||||||
a_hi = vget_high_s32(a);
|
a_hi = vget_high_s32(a);
|
||||||
@ -377,35 +365,31 @@ template<> EIGEN_STRONG_INLINE int predux_min<Packet4i>(const Packet4i& a)
|
|||||||
min = vpmin_s32(min, min);
|
min = vpmin_s32(min, min);
|
||||||
vst1_s32(s, min);
|
vst1_s32(s, min);
|
||||||
|
|
||||||
return s[0];
|
return vget_lane_s32(min, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// max
|
// max
|
||||||
template<> EIGEN_STRONG_INLINE float predux_max<Packet4f>(const Packet4f& a)
|
template<> EIGEN_STRONG_INLINE float predux_max<Packet4f>(const Packet4f& a)
|
||||||
{
|
{
|
||||||
float32x2_t a_lo, a_hi, max;
|
float32x2_t a_lo, a_hi, max;
|
||||||
float s[2];
|
|
||||||
|
|
||||||
a_lo = vget_low_f32(a);
|
a_lo = vget_low_f32(a);
|
||||||
a_hi = vget_high_f32(a);
|
a_hi = vget_high_f32(a);
|
||||||
max = vpmax_f32(a_lo, a_hi);
|
max = vpmax_f32(a_lo, a_hi);
|
||||||
max = vpmax_f32(max, max);
|
max = vpmax_f32(max, max);
|
||||||
vst1_f32(s, max);
|
|
||||||
|
|
||||||
return s[0];
|
return vget_lane_s32(max, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a)
|
template<> EIGEN_STRONG_INLINE int predux_max<Packet4i>(const Packet4i& a)
|
||||||
{
|
{
|
||||||
int32x2_t a_lo, a_hi, max;
|
int32x2_t a_lo, a_hi, max;
|
||||||
int32_t s[2];
|
|
||||||
|
|
||||||
a_lo = vget_low_s32(a);
|
a_lo = vget_low_s32(a);
|
||||||
a_hi = vget_high_s32(a);
|
a_hi = vget_high_s32(a);
|
||||||
max = vpmax_s32(a_lo, a_hi);
|
max = vpmax_s32(a_lo, a_hi);
|
||||||
max = vpmax_s32(max, max);
|
|
||||||
vst1_s32(s, max);
|
|
||||||
|
|
||||||
return s[0];
|
return vget_lane_s32(max, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this PALIGN_NEON business is to work around a bug in LLVM Clang 3.0 causing incorrect compilation errors,
|
// this PALIGN_NEON business is to work around a bug in LLVM Clang 3.0 causing incorrect compilation errors,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user