Re: com php-src: Improve x86 inline assembler: Zend/zend_alloc.c Zend/zend_operators.h

From: Date: Mon, 06 May 2013 23:16:22 +0000
Subject: Re: com php-src: Improve x86 inline assembler: Zend/zend_alloc.c Zend/zend_operators.h
References: 1  Groups: php.cvs 
Request: Send a blank email to php-cvs+get-72136@lists.php.net to get a copy of this message
On 02/11/2013 04:53 AM, Ard Biesheuvel wrote:
Commit:    aa12cdc361b29b4050676763858b3cfa637be6cb
Author:    Ard Biesheuvel <ard.biesheuvel@linaro.org>         Mon, 11 Feb 2013 13:53:27 +0100
Parents: 5bfdf4f069975514a358473f7e7fee3710e50597 Branches: master
Link:       http://git.php.net/?p=php-src.git;a=commitdiff;h=aa12cdc361b29b4050676763858b3cfa637be6cb
Log: Improve x86 inline assembler - added cc annotation to inline asm that clobbers the condition flags - remove hardcoded constants (IS_LONG,IS_DOUBLE) - remove hardcoded offsets (zval->value, zval->type) Changed paths: M Zend/zend_alloc.c M Zend/zend_operators.h
Hi Ard, The changes to zend_operators.h break compilation with GCC 3. Can you review https://bugs.php.net/bug.php?id=64780 ? Even if GCC 3 is pretty much gone there might still be someone who wants to build PHP 5.5 with it e.g. as a step during a platform migration. Since retaining the old assembler code in an #ifdef is painless to do, it won't hurt PHP to keep it a bit longer. Chris
Diff: diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 1cc2c67..98ab6be 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -667,12 +667,12 @@ static inline unsigned int zend_mm_high_bit(size_t _size) #if defined(__GNUC__) && (defined(__native_client__) || defined(i386)) unsigned int n; - __asm__("bsrl %1,%0\n\t" : "=r" (n) : "rm" (_size)); + __asm__("bsrl %1,%0\n\t" : "=r" (n) : "rm" (_size) : "cc"); return n; #elif defined(__GNUC__) && defined(__x86_64__) unsigned long n;
-        __asm__("bsrq %1,%0\n\t" : "=r" (n) : "rm"  (_size));
+        __asm__("bsrq %1,%0\n\t" : "=r" (n) : "rm"  (_size) : "cc");
          return (unsigned int)n;
#elif defined(_MSC_VER) && defined(_M_IX86) __asm { @@ -693,17 +693,17 @@ static inline unsigned int zend_mm_low_bit(size_t _size) #if defined(__GNUC__) && (defined(__native_client__) || defined(i386)) unsigned int n; - __asm__("bsfl %1,%0\n\t" : "=r" (n) : "rm" (_size)); + __asm__("bsfl %1,%0\n\t" : "=r" (n) : "rm" (_size) : "cc"); return n; #elif defined(__GNUC__) && defined(__x86_64__)
          unsigned long n;
-        __asm__("bsfq %1,%0\n\t" : "=r" (n) : "rm"  (_size));
+        __asm__("bsfq %1,%0\n\t" : "=r" (n) : "rm"  (_size) : "cc");
          return (unsigned int)n;
#elif defined(_MSC_VER) && defined(_M_IX86) __asm { bsf eax, _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; diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index e395fd3..93c60e4 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -477,6 +477,10 @@ ZEND_API void zend_update_current_locale(void); #define zend_update_current_locale() #endif +/* The offset in bytes between the value and type fields of a zval */ +#define ZVAL_OFFSETOF_TYPE \ + (__builtin_offsetof(zval,type) - __builtin_offsetof(zval,value)) + static zend_always_inline int fast_increment_function(zval *op1) { if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) { @@ -486,20 +490,26 @@ static zend_always_inline int fast_increment_function(zval *op1) "jno 0f\n\t" "movl $0x0, (%0)\n\t" "movl $0x41e00000, 0x4(%0)\n\t" - "movb $0x2,0xc(%0)\n" + "movb %1, %c2(%0)\n" "0:" : - : "r"(op1)); + : "r"(&op1->value), + "n"(IS_DOUBLE), + "n"(ZVAL_OFFSETOF_TYPE) + : "cc"); #elif defined(__GNUC__) && defined(__x86_64__) __asm__( "incq (%0)\n\t" "jno 0f\n\t" "movl $0x0, (%0)\n\t" "movl $0x43e00000, 0x4(%0)\n\t" - "movb $0x2,0x14(%0)\n" + "movb %1, %c2(%0)\n" "0:" : - : "r"(op1)); + : "r"(&op1->value), + "n"(IS_DOUBLE), + "n"(ZVAL_OFFSETOF_TYPE) + : "cc"); #else if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MAX)) { /* switch to double */ @@ -523,20 +533,26 @@ static zend_always_inline int fast_decrement_function(zval *op1) "jno 0f\n\t" "movl $0x00200000, (%0)\n\t" "movl $0xc1e00000, 0x4(%0)\n\t" - "movb $0x2,0xc(%0)\n" + "movb %1,%c2(%0)\n" "0:" : - : "r"(op1)); + : "r"(&op1->value), + "n"(IS_DOUBLE), + "n"(ZVAL_OFFSETOF_TYPE) + : "cc"); #elif defined(__GNUC__) && defined(__x86_64__) __asm__( "decq (%0)\n\t" "jno 0f\n\t" "movl $0x00000000, (%0)\n\t" "movl $0xc3e00000, 0x4(%0)\n\t" - "movb $0x2,0x14(%0)\n" + "movb %1,%c2(%0)\n" "0:" : - : "r"(op1)); + : "r"(&op1->value), + "n"(IS_DOUBLE), + "n"(ZVAL_OFFSETOF_TYPE) + : "cc"); #else if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MIN)) { /* switch to double */ @@ -561,40 +577,46 @@ static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *o "addl (%2), %%eax\n\t"
  			"jo     0f\n\t"
"movl %%eax, (%0)\n\t" - "movb $0x1,0xc(%0)\n\t" + "movb %3, %c5(%0)\n\t"
  			"jmp    1f\n"
"0:\n\t" "fildl (%1)\n\t" "fildl (%2)\n\t" "faddp %%st, %%st(1)\n\t" - "movb $0x2,0xc(%0)\n\t" + "movb %4, %c5(%0)\n\t" "fstpl (%0)\n" "1:" : - : "r"(result), - "r"(op1), - "r"(op2) - : "eax"); + : "r"(&result->value), + "r"(&op1->value), + "r"(&op2->value), + "n"(IS_LONG), + "n"(IS_DOUBLE), + "n"(ZVAL_OFFSETOF_TYPE) + : "eax","cc"); #elif defined(__GNUC__) && defined(__x86_64__) __asm__( "movq (%1), %%rax\n\t" "addq (%2), %%rax\n\t"
  			"jo     0f\n\t"
"movq %%rax, (%0)\n\t" - "movb $0x1,0x14(%0)\n\t" + "movb %3, %c5(%0)\n\t"
  			"jmp    1f\n"
"0:\n\t" "fildq (%1)\n\t" "fildq (%2)\n\t" "faddp %%st, %%st(1)\n\t" - "movb $0x2,0x14(%0)\n\t" + "movb %4, %c5(%0)\n\t" "fstpl (%0)\n" "1:" : - : "r"(result), - "r"(op1), - "r"(op2) - : "rax"); + : "r"(&result->value), + "r"(&op1->value), + "r"(&op2->value), + "n"(IS_LONG), + "n"(IS_DOUBLE), + "n"(ZVAL_OFFSETOF_TYPE) + : "rax","cc"); #else Z_LVAL_P(result) = Z_LVAL_P(op1) + Z_LVAL_P(op2); @@ -636,7 +658,7 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o "subl (%2), %%eax\n\t"
  			"jo     0f\n\t"
"movl %%eax, (%0)\n\t" - "movb $0x1,0xc(%0)\n\t" + "movb %3, %c5(%0)\n\t"
  			"jmp    1f\n"
"0:\n\t" "fildl (%2)\n\t" @@ -646,21 +668,24 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o #else "fsubp %%st, %%st(1)\n\t" #endif - "movb $0x2,0xc(%0)\n\t" + "movb %4, %c5(%0)\n\t" "fstpl (%0)\n" "1:" : - : "r"(result), - "r"(op1), - "r"(op2) - : "eax"); + : "r"(&result->value), + "r"(&op1->value), + "r"(&op2->value), + "n"(IS_LONG), + "n"(IS_DOUBLE), + "n"(ZVAL_OFFSETOF_TYPE) + : "eax","cc"); #elif defined(__GNUC__) && defined(__x86_64__) __asm__( "movq (%1), %%rax\n\t" "subq (%2), %%rax\n\t"
  			"jo     0f\n\t"
"movq %%rax, (%0)\n\t" - "movb $0x1,0x14(%0)\n\t" + "movb %3, %c5(%0)\n\t"
  			"jmp    1f\n"
"0:\n\t" "fildq (%2)\n\t" @@ -670,14 +695,17 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o #else "fsubp %%st, %%st(1)\n\t" #endif - "movb $0x2,0x14(%0)\n\t" + "movb %4, %c5(%0)\n\t" "fstpl (%0)\n" "1:" : - : "r"(result), - "r"(op1), - "r"(op2) - : "rax"); + : "r"(&result->value), + "r"(&op1->value), + "r"(&op2->value), + "n"(IS_LONG), + "n"(IS_DOUBLE), + "n"(ZVAL_OFFSETOF_TYPE) + : "rax","cc"); #else Z_LVAL_P(result) = Z_LVAL_P(op1) - Z_LVAL_P(op2);
-- christopher.jones@oracle.com http://twitter.com/ghrd Newly updated, free PHP & Oracle book: http://www.oracle.com/technetwork/topics/php/underground-php-oracle-manual-098250.html

« previous php.cvs (#72136) next »