diff options
author | Konstantinos Margaritis <markos@codex.gr> | 2012-07-04 11:12:02 +0300 |
---|---|---|
committer | Konstantinos Margaritis <markos@codex.gr> | 2012-07-04 11:12:02 +0300 |
commit | f73753674424d49ca3682b8d7b2030d04eeb9fbe (patch) | |
tree | 2e6eb33818aaebdcd368fd04236c67dba7477848 /Eigen | |
parent | 9a97dac4d91ee20c0bbdef39270d5a1bc743c20e (diff) |
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.
Diffstat (limited to 'Eigen')
-rw-r--r-- | Eigen/src/Core/arch/NEON/PacketMath.h | 38 |
1 files changed, 11 insertions, 27 deletions
diff --git a/Eigen/src/Core/arch/NEON/PacketMath.h b/Eigen/src/Core/arch/NEON/PacketMath.h index 1eb082a5b..90dd335a1 100644 --- a/Eigen/src/Core/arch/NEON/PacketMath.h +++ b/Eigen/src/Core/arch/NEON/PacketMath.h @@ -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) { float32x2_t a_lo, a_hi, sum; - float s[2]; a_lo = vget_low_f32(a); a_hi = vget_high_f32(a); sum = vpadd_f32(a_lo, a_hi); sum = vpadd_f32(sum, sum); - vst1_f32(s, sum); - - return s[0]; + return vget_lane_f32(sum, 0); } 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) { int32x2_t a_lo, a_hi, sum; - int32_t s[2]; a_lo = vget_low_s32(a); a_hi = vget_high_s32(a); sum = vpadd_s32(a_lo, a_hi); sum = vpadd_s32(sum, sum); - vst1_s32(s, sum); - - return s[0]; + return vget_lane_s32(sum, 0); } 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) { float32x2_t a_lo, a_hi, prod; - float s[2]; // Get a_lo = |a1|a2| and a_hi = |a3|a4| 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); // Multiply prod with its swapped value |a2*a4|a1*a3| 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) { int32x2_t a_lo, a_hi, prod; - int32_t s[2]; // Get a_lo = |a1|a2| and a_hi = |a3|a4| a_lo = vget_low_s32(a); @@ -347,65 +338,58 @@ template<> EIGEN_STRONG_INLINE int predux_mul<Packet4i>(const Packet4i& a) prod = vmul_s32(a_lo, a_hi); // Multiply prod with its swapped value |a2*a4|a1*a3| prod = vmul_s32(prod, vrev64_s32(prod)); - vst1_s32(s, prod); - return s[0]; + return vget_lane_s32(prod, 0); } // min template<> EIGEN_STRONG_INLINE float predux_min<Packet4f>(const Packet4f& a) { float32x2_t a_lo, a_hi, min; - float s[2]; a_lo = vget_low_f32(a); a_hi = vget_high_f32(a); min = vpmin_f32(a_lo, a_hi); 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) { int32x2_t a_lo, a_hi, min; - int32_t s[2]; a_lo = vget_low_s32(a); a_hi = vget_high_s32(a); min = vpmin_s32(a_lo, a_hi); min = vpmin_s32(min, min); vst1_s32(s, min); - - return s[0]; + + return vget_lane_s32(min, 0); } // max template<> EIGEN_STRONG_INLINE float predux_max<Packet4f>(const Packet4f& a) { float32x2_t a_lo, a_hi, max; - float s[2]; a_lo = vget_low_f32(a); a_hi = vget_high_f32(a); max = vpmax_f32(a_lo, a_hi); 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) { int32x2_t a_lo, a_hi, max; - int32_t s[2]; a_lo = vget_low_s32(a); a_hi = vget_high_s32(a); 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, |