summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Blanchard <anton@samba.org>2015-05-26 22:42:13 +1000
committerRemi Collet <remi@php.net>2015-07-28 18:38:23 +0200
commit305199a13163e246b909ef32880df032823bff05 (patch)
treea855e451319a524067c17d60bac3948d0fd96438
parenta581910a76276a152dae1953fdf3b25d8c9a8f85 (diff)
downloadphp-git-305199a13163e246b909ef32880df032823bff05.tar.gz
Improve performance of PowerPC64 ZEND_SIGNED_MULTIPLY_LONG
Detecting overflow with the XER is slow, partially because we have to clear it before use. We can do better by using a trick where we compare the high 64 bits of the result with the low 64 bits shifted right 63 bits. This is 7% faster on a POWER8 running a simple testcase: <?php function testcase($count = 100000000) { for ($i = 0; $i < $count; $i++) { $x = 1; $x = $x * 2; $x = $x * 2; $x = $x * 2; $x = $x * 2; } } testcase(); ?>
-rw-r--r--Zend/zend_multiply.h27
1 files changed, 13 insertions, 14 deletions
diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h
index b12c1e23b3..fc053d0e35 100644
--- a/Zend/zend_multiply.h
+++ b/Zend/zend_multiply.h
@@ -74,20 +74,19 @@
#elif defined(__powerpc64__) && defined(__GNUC__)
-#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
- long __tmpvar; \
- __asm__("li 14, 0\n\t" \
- "mtxer 14\n\t" \
- "mulldo. %0, %2,%3\n\t" \
- "xor %1, %1, %1\n\t" \
- "bns+ 0f\n\t" \
- "li %1, 1\n\t" \
- "0:\n" \
- : "=r"(__tmpvar),"=r"(usedval) \
- : "r"(a), "r"(b) \
- : "r14", "cc"); \
- if (usedval) (dval) = (double) (a) * (double) (b); \
- else (lval) = __tmpvar; \
+#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do { \
+ long __low, __high; \
+ __asm__("mulld %0,%2,%3\n\t" \
+ "mulhd %1,%2,%3\n" \
+ : "=&r"(__low), "=&r"(__high) \
+ : "r"(a), "r"(b)); \
+ if ((__low >> 63) != __high) { \
+ (dval) = (double) (a) * (double) (b); \
+ (usedval) = 1; \
+ } else { \
+ (lval) = __low; \
+ (usedval) = 0; \
+ } \
} while (0)
#elif SIZEOF_ZEND_LONG == 4