ht_dec.c: Improve MSVC arm64 popcount performance (#1479)
authorPeter Johnson <johnson.peter@gmail.com>
Sat, 9 Dec 2023 21:02:11 +0000 (13:02 -0800)
committerGitHub <noreply@github.com>
Sat, 9 Dec 2023 21:02:11 +0000 (22:02 +0100)
Use NEON instructions for ARM64 (implementation based on microsoft/STL#2127).

Godbolt output here: https://godbolt.org/z/q7GPTqT14

src/lib/openjp2/ht_dec.c

index 9ea061f37478dd8aa70b42a4cf910a0cac28722d..a554b24a6a2ce45d5ebc1fd0afd7ca131d1881db 100644 (file)
 #define OPJ_COMPILER_GNUC
 #endif
 
+#if defined(OPJ_COMPILER_MSVC) && defined(_M_ARM64) \
+    && !defined(_M_ARM64EC) && !defined(_M_CEE_PURE) && !defined(__CUDACC__) \
+    && !defined(__INTEL_COMPILER) && !defined(__clang__)
+#define MSVC_NEON_INTRINSICS
+#endif
+
+#ifdef MSVC_NEON_INTRINSICS
+#include <arm64_neon.h>
+#endif
+
 //************************************************************************/
 /** @brief Displays the error message for disabling the decoding of SPP and
   * MRP passes
@@ -71,6 +81,9 @@ OPJ_UINT32 population_count(OPJ_UINT32 val)
 {
 #if defined(OPJ_COMPILER_MSVC) && (defined(_M_IX86) || defined(_M_AMD64))
     return (OPJ_UINT32)__popcnt(val);
+#elif defined(OPJ_COMPILER_MSVC) && defined(MSVC_NEON_INTRINSICS)
+    const __n64 temp = neon_cnt(__uint64ToN64_v(val));
+    return neon_addv8(temp).n8_i8[0];
 #elif (defined OPJ_COMPILER_GNUC)
     return (OPJ_UINT32)__builtin_popcount(val);
 #else