Skip to content

Commit 6967de5

Browse files
authored
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] <https://releases.llvm.org/4.0.0/tools/clang/docs/LanguageExtensions.html> [2] <https://learn.microsoft.com/en-us/windows/win32/api/intsafe/>
1 parent 39f1d25 commit 6967de5

File tree

2 files changed

+18
-37
lines changed

2 files changed

+18
-37
lines changed

Zend/zend_multiply.h

Lines changed: 16 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -79,46 +79,25 @@
7979
else (lval) = __tmpvar; \
8080
} while (0)
8181

82-
#elif defined(ZEND_WIN32)
83-
84-
# ifdef _M_X64
85-
# pragma intrinsic(_mul128)
86-
# define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
87-
__int64 __high; \
88-
__int64 __low = _mul128((a), (b), &__high); \
89-
if ((__low >> 63I64) == __high) { \
90-
(usedval) = 0; \
91-
(lval) = __low; \
92-
} else { \
93-
(usedval) = 1; \
94-
(dval) = (double)(a) * (double)(b); \
95-
} \
96-
} while (0)
97-
# elif defined(_M_ARM64)
98-
# pragma intrinsic(__mulh)
99-
# define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
100-
__int64 __high = __mulh((a), (b)); \
101-
__int64 __low = (a) * (b); \
102-
if ((__low >> 63I64) == __high) { \
103-
(usedval) = 0; \
104-
(lval) = __low; \
105-
} else { \
106-
(usedval) = 1; \
107-
(dval) = (double)(a) * (double)(b); \
108-
} \
82+
#elif defined(ZEND_WIN32) && SIZEOF_LONG_LONG == SIZEOF_ZEND_LONG
83+
84+
#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
85+
long long __tmpvar; \
86+
if (((usedval) = FAILED(LongLongMult((a), (b), &__tmpvar)))) { \
87+
(dval) = (double) (a) * (double) (b); \
88+
} \
89+
else (lval) = __tmpvar; \
10990
} while (0)
110-
# else
111-
# define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
112-
zend_long __lres = (a) * (b); \
113-
long double __dres = (long double)(a) * (long double)(b); \
114-
long double __delta = (long double) __lres - __dres; \
115-
if ( ((usedval) = (( __dres + __delta ) != __dres))) { \
116-
(dval) = __dres; \
117-
} else { \
118-
(lval) = __lres; \
91+
92+
#elif defined(ZEND_WIN32) && SIZEOF_LONG == SIZEOF_ZEND_LONG
93+
94+
#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
95+
long __tmpvar; \
96+
if (((usedval) = FAILED(LongMult((a), (b), &__tmpvar)))) { \
97+
(dval) = (double) (a) * (double) (b); \
11998
} \
99+
else (lval) = __tmpvar; \
120100
} while (0)
121-
# endif
122101

123102
#elif defined(__powerpc64__) && defined(__GNUC__)
124103

win32/build/config.w32

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,8 @@ if (VS_TOOLSET) {
374374
AC_DEFINE("PHP_HAVE_BUILTIN_SADDLL_OVERFLOW", 1, "Define to 1 if the compiler supports '__builtin_saddll_overflow'.");
375375
AC_DEFINE("PHP_HAVE_BUILTIN_SSUBL_OVERFLOW", 1, "Define to 1 if the compiler supports '__builtin_ssubl_overflow'.");
376376
AC_DEFINE("PHP_HAVE_BUILTIN_SSUBLL_OVERFLOW", 1, "Define to 1 if the compiler supports '__builtin_ssubll_overflow'.");
377+
AC_DEFINE("PHP_HAVE_BUILTIN_SMULL_OVERFLOW", 1, "Define to 1 if the compiler supports '__builtin_smull_overflow '.");
378+
AC_DEFINE("PHP_HAVE_BUILTIN_SMULLL_OVERFLOW", 1, "Define to 1 if the compiler supports '__builtin_smulll_overflow'.");
377379
if (PHP_UNCRITICAL_WARN_CHOKE != "no") {
378380
ADD_FLAG("CFLAGS", "-Wno-ignored-attributes -Wno-deprecated-declarations -Wno-missing-braces " +
379381
"-Wno-logical-op-parentheses -Wno-msvc-include -Wno-invalid-source-encoding -Wno-unknown-pragmas " +

0 commit comments

Comments
 (0)