From 6967de563e7adaa884d96f5498e6ac0a94d912f1 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Thu, 16 Jan 2025 13:57:07 +0100 Subject: [PATCH] Simplify ZEND_SIGNED_MULTIPLY_LONG() on Windows (GH-17477) For Clang, we just need to define the respective macros, since these built-ins are available in all supported Clang versions (>= 4.0.0, currently)[1]. For MSVC (and possibly other compilers) we use the respective APIs of intsafe.h[2] which are available as of Windows 7/Server 2008 R2. For x86 (and to a lesser extend for ARM64) that should also notably improve performance. [1] [2] --- Zend/zend_multiply.h | 53 +++++++++++++----------------------------- win32/build/config.w32 | 2 ++ 2 files changed, 18 insertions(+), 37 deletions(-) diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h index a64cd612148fe..1eece465feefa 100644 --- a/Zend/zend_multiply.h +++ b/Zend/zend_multiply.h @@ -79,46 +79,25 @@ else (lval) = __tmpvar; \ } while (0) -#elif defined(ZEND_WIN32) - -# ifdef _M_X64 -# pragma intrinsic(_mul128) -# define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \ - __int64 __high; \ - __int64 __low = _mul128((a), (b), &__high); \ - if ((__low >> 63I64) == __high) { \ - (usedval) = 0; \ - (lval) = __low; \ - } else { \ - (usedval) = 1; \ - (dval) = (double)(a) * (double)(b); \ - } \ -} while (0) -# elif defined(_M_ARM64) -# pragma intrinsic(__mulh) -# define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \ - __int64 __high = __mulh((a), (b)); \ - __int64 __low = (a) * (b); \ - if ((__low >> 63I64) == __high) { \ - (usedval) = 0; \ - (lval) = __low; \ - } else { \ - (usedval) = 1; \ - (dval) = (double)(a) * (double)(b); \ - } \ +#elif defined(ZEND_WIN32) && SIZEOF_LONG_LONG == SIZEOF_ZEND_LONG + +#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \ + long long __tmpvar; \ + if (((usedval) = FAILED(LongLongMult((a), (b), &__tmpvar)))) { \ + (dval) = (double) (a) * (double) (b); \ + } \ + else (lval) = __tmpvar; \ } while (0) -# else -# define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \ - zend_long __lres = (a) * (b); \ - long double __dres = (long double)(a) * (long double)(b); \ - long double __delta = (long double) __lres - __dres; \ - if ( ((usedval) = (( __dres + __delta ) != __dres))) { \ - (dval) = __dres; \ - } else { \ - (lval) = __lres; \ + +#elif defined(ZEND_WIN32) && SIZEOF_LONG == SIZEOF_ZEND_LONG + +#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \ + long __tmpvar; \ + if (((usedval) = FAILED(LongMult((a), (b), &__tmpvar)))) { \ + (dval) = (double) (a) * (double) (b); \ } \ + else (lval) = __tmpvar; \ } while (0) -# endif #elif defined(__powerpc64__) && defined(__GNUC__) diff --git a/win32/build/config.w32 b/win32/build/config.w32 index d2f8a611180e3..f98ec68d89b4b 100644 --- a/win32/build/config.w32 +++ b/win32/build/config.w32 @@ -374,6 +374,8 @@ if (VS_TOOLSET) { AC_DEFINE("PHP_HAVE_BUILTIN_SADDLL_OVERFLOW", 1, "Define to 1 if the compiler supports '__builtin_saddll_overflow'."); AC_DEFINE("PHP_HAVE_BUILTIN_SSUBL_OVERFLOW", 1, "Define to 1 if the compiler supports '__builtin_ssubl_overflow'."); AC_DEFINE("PHP_HAVE_BUILTIN_SSUBLL_OVERFLOW", 1, "Define to 1 if the compiler supports '__builtin_ssubll_overflow'."); + AC_DEFINE("PHP_HAVE_BUILTIN_SMULL_OVERFLOW", 1, "Define to 1 if the compiler supports '__builtin_smull_overflow '."); + AC_DEFINE("PHP_HAVE_BUILTIN_SMULLL_OVERFLOW", 1, "Define to 1 if the compiler supports '__builtin_smulll_overflow'."); if (PHP_UNCRITICAL_WARN_CHOKE != "no") { ADD_FLAG("CFLAGS", "-Wno-ignored-attributes -Wno-deprecated-declarations -Wno-missing-braces " + "-Wno-logical-op-parentheses -Wno-msvc-include -Wno-invalid-source-encoding -Wno-unknown-pragmas " +