Fixed cpuinfo in LLVM GCC & Added AVX2 detection
authorXinchen Hui <laruence@gmail.com>
Sat, 10 Feb 2018 09:37:38 +0000 (17:37 +0800)
committerXinchen Hui <laruence@gmail.com>
Sat, 10 Feb 2018 09:38:30 +0000 (17:38 +0800)
Seems it only defines __builtin_cpu_supports but no __builtin_cpu_init
(Apple LLVM version 9.0.0 (clang-900.0.38))

Zend/zend.c
Zend/zend_cpuinfo.c
Zend/zend_cpuinfo.h
configure.ac

index dc0cab8cc02670b0c3fd8beffbbefdbd8e77328b..e62f9e1a480c7931ff774f70fbbafb2c1f300633 100644 (file)
@@ -743,6 +743,7 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) /
 #endif
 
        zend_cpu_startup();
+       zend_cpu_supports(ZEND_CPU_FEATURE_AVX2);
 
 #ifdef ZEND_WIN32
        php_win32_cp_set_by_id(65001);
index 988ceb252199fa7d958fa2aecb6cef997bd93117..43252a7cca11b926ac4f83a76e94d0eb1dcb9d8b 100644 (file)
@@ -29,46 +29,53 @@ typedef struct _zend_cpu_info {
 static zend_cpu_info cpuinfo = {0};
 
 #if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
-static void __zend_cpuid(uint32_t func, uint32_t subfunc) {
+static void __zend_cpuid(uint32_t func, uint32_t subfunc, zend_cpu_info *cpuinfo) {
        __asm__ __volatile__ (
                "cpuid"
-               : "=a"(cpuinfo.eax), "=b"(cpuinfo.ebx), "=c"(cpuinfo.ecx), "=d"(cpuinfo.edx)
+               : "=a"(cpuinfo->eax), "=b"(cpuinfo->ebx), "=c"(cpuinfo->ecx), "=d"(cpuinfo->edx)
                : "a"(func), "c"(subfunc)
        );
 }
 #elif defined(ZEND_WIN32)
 # include <intrin.h>
-static void __zend_cpuid(uint32_t func, uint32_t subfunc) {
+static void __zend_cpuid(uint32_t func, uint32_t subfunc, zend_cpu_info *cpuinfo) {
        int regs[4];
 
        __cpuidex(regs, func, subfunc);
 
-       cpuinfo.eax = regs[0];
-       cpuinfo.ebx = regs[1];
-       cpuinfo.ecx = regs[2];
-       cpuinfo.edx = regs[3];
+       cpuinfo->eax = regs[0];
+       cpuinfo->ebx = regs[1];
+       cpuinfo->ecx = regs[2];
+       cpuinfo->edx = regs[3];
 }
 #else
-static void __zend_cpuid(uint32_t func, uint32_t subfunc) {
-       cpuinfo.eax = 0;
+static void __zend_cpuid(uint32_t func, uint32_t subfunc, zend_cpu_info *cpuinfo) {
+       cpuinfo->eax = 0;
 }
 #endif
 
 void zend_cpu_startup(void)
 {
        if (!cpuinfo.initialized) {
+               zend_cpu_info ebx;
+
                cpuinfo.initialized = 1;
-               __zend_cpuid(0, 0);
+               __zend_cpuid(0, 0, &cpuinfo);
                if (cpuinfo.eax == 0) {
                        return;
                }
-               __zend_cpuid(1, 0);
+               __zend_cpuid(1, 0, &cpuinfo);
+               /* for avx2 */
+               __zend_cpuid(7, 0, &ebx);
+               cpuinfo.ebx = ebx.ebx;
        }
 }
 
 ZEND_API int zend_cpu_supports(zend_cpu_feature feature) {
        if (feature & ZEND_CPU_EDX_MASK) {
                return (cpuinfo.edx & (feature & ~ZEND_CPU_EDX_MASK));
+       } else if (feature & ZEND_CPU_EBX_MASK) {
+               return (cpuinfo.ebx & (feature & ~ZEND_CPU_EBX_MASK));
        } else {
                return (cpuinfo.ecx & feature);
        }
index c077366bd8323f551764eaaf8a8bf161205bab70..d0d3a936e1175a58dcbe5eb3884ecb78c7a27b96 100644 (file)
@@ -21,6 +21,7 @@
 
 #include "zend.h"
 
+#define ZEND_CPU_EBX_MASK     (1<<30)
 #define ZEND_CPU_EDX_MASK     (1<<31)
 
 typedef enum _zend_cpu_feature {
@@ -55,9 +56,12 @@ typedef enum _zend_cpu_feature {
        ZEND_CPU_FEATURE_OSXSAVE                = (1<<27) ,
        ZEND_CPU_FEATURE_AVX                    = (1<<28),
        ZEND_CPU_FEATURE_F16C                   = (1<<29),
-       ZEND_CPU_FEATURE_RDRAND                 = (1<<30),
+       /* intentionally don't support  = (1<<30) */
        /* intentionally don't support  = (1<<31) */
 
+       /* EBX */
+       ZEND_CPU_FEATURE_AVX2                   = (1<<5 | ZEND_CPU_EBX_MASK),
+
        /* EDX */
        ZEND_CPU_FEATURE_FPU                    = (1<<0 | ZEND_CPU_EDX_MASK),
        ZEND_CPU_FEATURE_VME                    = (1<<1 | ZEND_CPU_EDX_MASK),
@@ -88,47 +92,59 @@ typedef enum _zend_cpu_feature {
        ZEND_CPU_FEATURE_SSE2                   = (1<<26 | ZEND_CPU_EDX_MASK),
        ZEND_CPU_FEATURE_SS                             = (1<<27 | ZEND_CPU_EDX_MASK),
        ZEND_CPU_FEATURE_HT                             = (1<<28 | ZEND_CPU_EDX_MASK),
-       ZEND_CPU_FEATURE_TM                             = (1<<29 | ZEND_CPU_EDX_MASK),
-       ZEND_CPU_FEATURE_IA64                   = (1<<30 | ZEND_CPU_EDX_MASK)
+       ZEND_CPU_FEATURE_TM                             = (1<<29 | ZEND_CPU_EDX_MASK)
+       /*intentionally don't support   = (1<<30 | ZEND_CPU_EDX_MASK)*/
        /*intentionally don't support   = (1<<31 | ZEND_CPU_EDX_MASK)*/
 } zend_cpu_feature;
 
 void zend_cpu_startup();
 ZEND_API int zend_cpu_supports(zend_cpu_feature feature);
 
-#ifdef PHP_HAVE_BUILTIN_CPU_SUPPORTS
+#if PHP_HAVE_BUILTIN_CPU_SUPPORTS
 /* NOTE: you should use following inline function in
  * resolver functions (ifunc), as it could be called
  * before all PLT symbols are resloved. in other words,
  * resolver functions should not depends any external
  * functions */
 static zend_always_inline int zend_cpu_support_sse2() {
+#if PHP_HAVE_BUILTIN_CPU_INIT
        __builtin_cpu_init();
+#endif
        return __builtin_cpu_supports("sse2");
 }
 
 static zend_always_inline int zend_cpu_support_sse3() {
+#if PHP_HAVE_BUILTIN_CPU_INIT
        __builtin_cpu_init();
+#endif
        return __builtin_cpu_supports("sse3");
 }
 
 static zend_always_inline int zend_cpu_support_sse41() {
+#if PHP_HAVE_BUILTIN_CPU_INIT
        __builtin_cpu_init();
+#endif
        return __builtin_cpu_supports("sse4.1");
 }
 
 static zend_always_inline int zend_cpu_support_sse42() {
+#if PHP_HAVE_BUILTIN_CPU_INIT
        __builtin_cpu_init();
+#endif
        return __builtin_cpu_supports("sse4.2");
 }
 
 static zend_always_inline int zend_cpu_support_avx() {
+#if PHP_HAVE_BUILTIN_CPU_INIT
        __builtin_cpu_init();
+#endif
        return __builtin_cpu_supports("avx");
 }
 
 static zend_always_inline int zend_cpu_support_avx2() {
+#if PHP_HAVE_BUILTIN_CPU_INIT
        __builtin_cpu_init();
+#endif
        return __builtin_cpu_supports("avx2");
 }
 #else
index 4d754364dbf6206dc8886e086867506028677440..811faa97ed8eae5bb83c56eec7f816384c170eba 100644 (file)
@@ -566,6 +566,8 @@ dnl Check __builtin_ssubl_overflow
 PHP_CHECK_BUILTIN_SSUBL_OVERFLOW
 dnl Check __builtin_ssubll_overflow
 PHP_CHECK_BUILTIN_SSUBLL_OVERFLOW
+dnl Check __builtin_cpu_init
+PHP_CHECK_BUILTIN_CPU_INIT
 dnl Check __builtin_cpu_supports
 PHP_CHECK_BUILTIN_CPU_SUPPORTS