On 02/04/2013 01:50 PM, Dmitry Stogov wrote:
I can't remember if I did any special benchmarks except for bench.php when I introduced fast math functions. That time, I rearranged the code to allow inlining of the most probable paths and added assembler code to catch overflow (C can't do it in optimal way). As I remember the bench.php showed some visible improvement.
OK, in that case I would still recommend using fewer hardcoded numbers and offsets: please refer to the applied patch, it makes things a bit more robust.
However, as I don't expect any speedup for ARM in this area, I will not pursue this any further.
Are there any other optimizations involving inline assembler that you implemented for PHP? I would like to review them to see if I need to add an ARM version.
Cheers, Ard.
>From 16f61b05b3911c91b52c5eff66c2274d5a7c817f Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel <ard.biesheu...@linaro.org> Date: Mon, 4 Feb 2013 17:56:11 +0100 Subject: [PATCH] Remove hardcoded constants and struct offsets from asm arithmetic --- Zend/zend_operators.h | 80 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index 20a5277..b51a000 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -476,6 +476,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)) { @@ -485,20 +489,24 @@ 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)); #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)); #else if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MAX)) { /* switch to double */ @@ -522,20 +530,24 @@ 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)); #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)); #else if (UNEXPECTED(Z_LVAL_P(op1) == LONG_MIN)) { /* switch to double */ @@ -560,19 +572,22 @@ 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) + : "r"(&result->value), + "r"(&op1->value), + "r"(&op2->value), + "n"(IS_LONG), + "n"(IS_DOUBLE), + "n"(ZVAL_OFFSETOF_TYPE) : "eax"); #elif defined(__GNUC__) && defined(__x86_64__) __asm__( @@ -580,19 +595,22 @@ static zend_always_inline int fast_add_function(zval *result, zval *op1, zval *o "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) + : "r"(&result->value), + "r"(&op1->value), + "r"(&op2->value), + "n"(IS_LONG), + "n"(IS_DOUBLE), + "n"(ZVAL_OFFSETOF_TYPE) : "rax"); #else Z_LVAL_P(result) = Z_LVAL_P(op1) + Z_LVAL_P(op2); @@ -635,7 +653,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" @@ -645,13 +663,16 @@ 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) + : "r"(&result->value), + "r"(&op1->value), + "r"(&op2->value), + "n"(IS_LONG), + "n"(IS_DOUBLE), + "n"(ZVAL_OFFSETOF_TYPE) : "eax"); #elif defined(__GNUC__) && defined(__x86_64__) __asm__( @@ -659,7 +680,7 @@ static zend_always_inline int fast_sub_function(zval *result, zval *op1, zval *o "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" @@ -669,13 +690,16 @@ 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) + : "r"(&result->value), + "r"(&op1->value), + "r"(&op2->value), + "n"(IS_LONG), + "n"(IS_DOUBLE), + "n"(ZVAL_OFFSETOF_TYPE) : "rax"); #else Z_LVAL_P(result) = Z_LVAL_P(op1) - Z_LVAL_P(op2); -- 1.7.10.4
-- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php