Commit:    e2453276e95165bf3b765d27781405c816821c15
Author:    Ard Biesheuvel <ard.biesheu...@linaro.org>         Mon, 11 Feb 2013 
14:36:58 +0100
Parents:   aa12cdc361b29b4050676763858b3cfa637be6cb
Branches:  master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=e2453276e95165bf3b765d27781405c816821c15

Log:
Low-level ARM optimizations

- added ARM versions of zend_mm_high_bit()/zend_mm_low_bit()
- improved safe_address()

Changed paths:
  M  Zend/zend_alloc.c
  M  Zend/zend_multiply.h


Diff:
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index 98ab6be..1c76bd4 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -678,6 +678,8 @@ static inline unsigned int zend_mm_high_bit(size_t _size)
        __asm {
                bsr eax, _size
        }
+#elif defined(__GNUC__) && (defined(__arm__) ||  defined(__aarch64__))
+       return (8 * SIZEOF_SIZE_T - 1) - __builtin_clzl(_size);
 #else
        unsigned int n = 0;
        while (_size != 0) {
@@ -704,6 +706,8 @@ static inline unsigned int zend_mm_low_bit(size_t _size)
        __asm {
                bsf eax, _size
        }
+#elif defined(__GNUC__) && (defined(__arm__) || defined(__aarch64__))
+       return __builtin_ctzl(_size);
 #else
        static const int offset[16] = {4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0};
        unsigned int n;
@@ -2494,6 +2498,47 @@ static inline size_t safe_address(size_t nmemb, size_t 
size, size_t offset)
         return res;
 }
 
+#elif defined(__GNUC__) && defined(__arm__)
+
+static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
+{
+        size_t res;
+        unsigned long overflow;
+
+        __asm__ ("umlal %0,%1,%2,%3"
+             : "=r"(res), "=r"(overflow)
+             : "r"(nmemb),
+               "r"(size),
+               "0"(offset),
+               "1"(0));
+
+        if (UNEXPECTED(overflow)) {
+                zend_error_noreturn(E_ERROR, "Possible integer overflow in 
memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
+                return 0;
+        }
+        return res;
+}
+
+#elif defined(__GNUC__) && defined(__aarch64__)
+
+static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
+{
+        size_t res;
+        unsigned long overflow;
+
+        __asm__ ("mul %0,%2,%3\n\tumulh %1,%2,%3\n\tadds %0,%0,%4\n\tadc 
%1,%1,%1"
+             : "=&r"(res), "=&r"(overflow)
+             : "r"(nmemb),
+               "r"(size),
+               "r"(offset));
+
+        if (UNEXPECTED(overflow)) {
+                zend_error_noreturn(E_ERROR, "Possible integer overflow in 
memory allocation (%zu * %zu + %zu)", nmemb, size, offset);
+                return 0;
+        }
+        return res;
+}
+
 #elif SIZEOF_SIZE_T == 4 && defined(HAVE_ZEND_LONG64)
 
 static inline size_t safe_address(size_t nmemb, size_t size, size_t offset)
diff --git a/Zend/zend_multiply.h b/Zend/zend_multiply.h
index c3c9657..e52956f 100644
--- a/Zend/zend_multiply.h
+++ b/Zend/zend_multiply.h
@@ -13,7 +13,7 @@
    | lice...@zend.com so we can mail you a copy immediately.              |
    +----------------------------------------------------------------------+
    | Authors: Sascha Schumann <sas...@schumann.cx>                        |
-   |          Ard Biesheuvel <a...@ard.nu>                                 |
+   |          Ard Biesheuvel <ard.biesheu...@linaro.org>                  |
    +----------------------------------------------------------------------+
 */
 
@@ -43,6 +43,31 @@
        else (lval) = __tmpvar;                                                 
                                \
 } while (0)
 
+#elif defined(__arm__) && defined(__GNUC__)
+
+#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do {      \
+       long __tmpvar;                                                          
                                        \
+       __asm__("smull %0, %1, %2, %3\n"                                        
                        \
+               "sub %1, %1, %0, asr #31"                                       
                                \
+                       : "=r"(__tmpvar), "=r"(usedval)                         
                        \
+                       : "r"(a), "r"(b));                                      
                                        \
+       if (usedval) (dval) = (double) (a) * (double) (b);                      
        \
+       else (lval) = __tmpvar;                                                 
                                \
+} while (0)
+
+#elif defined(__aarch64__) && defined(__GNUC__)
+
+#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do {      \
+       long __tmpvar;                                                          
                                        \
+       __asm__("mul %0, %2, %3\n"                                              
                                \
+               "smulh %1, %2, %3\n"                                            
                                \
+               "sub %1, %1, %0, asr #63\n"                                     
                                \
+                       : "=X"(__tmpvar), "=X"(usedval)                         
                        \
+                       : "X"(a), "X"(b));                                      
                                        \
+       if (usedval) (dval) = (double) (a) * (double) (b);                      
        \
+       else (lval) = __tmpvar;                                                 
                                \
+} while (0)
+
 #elif SIZEOF_LONG == 4 && defined(HAVE_ZEND_LONG64)
 
 #define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do {      \
@@ -58,15 +83,15 @@
 
 #else
 
-#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do {              
\
-       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;                                                
                                                \
-       }                                                                       
                                                                \
+#define ZEND_SIGNED_MULTIPLY_LONG(a, b, lval, dval, usedval) do {      \
+       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;                                                
                                        \
+       }                                                                       
                                                        \
 } while (0)
 
 #endif


--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to