[prev in list] [next in list] [prev in thread] [next in thread] 

List:       php-cvs
Subject:    [PHP-CVS] [php-src] PHP-8.1: JIT: Allow register allocation for result of STRLEN and COUNT instructi
From:       Dmitry Stogov <noreply () php ! net>
Date:       2021-09-30 18:51:19
Message-ID: NTFtLmOHq5CgCCvUFGTFEnWYl4ogneoGJwVMnvbKtqM () main ! php ! net
[Download RAW message or body]

Author: Dmitry Stogov (dstogov)
Date: 2021-09-30T21:50:53+03:00

Commit: https://github.com/php/php-src/commit/7be7ec3098637af4d93ce433ce43f5e1d6c8fd7a
 Raw diff: https://github.com/php/php-src/commit/7be7ec3098637af4d93ce433ce43f5e1d6c8fd7a.diff


JIT: Allow register allocation for result of STRLEN and COUNT instructions

Changed paths:
  M  ext/opcache/jit/zend_jit.c
  M  ext/opcache/jit/zend_jit_arm64.dasc
  M  ext/opcache/jit/zend_jit_trace.c
  M  ext/opcache/jit/zend_jit_x86.dasc


Diff:

diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c
index dbd4039c4c97..01701105040a 100644
--- a/ext/opcache/jit/zend_jit.c
+++ b/ext/opcache/jit/zend_jit.c
@@ -3827,7 +3827,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa \
                *ssa, const zend_op
 						if ((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_STRING) {
 							break;
 						}
-						if (!zend_jit_strlen(&dasm_state, opline, op1_info, OP1_REG_ADDR())) {
+						if (!zend_jit_strlen(&dasm_state, opline, op1_info, OP1_REG_ADDR(), \
RES_REG_ADDR())) {  goto jit_failure;
 						}
 						goto done;
@@ -3836,7 +3836,7 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa \
                *ssa, const zend_op
 						if ((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) != MAY_BE_ARRAY) {
 							break;
 						}
-						if (!zend_jit_count(&dasm_state, opline, op1_info, OP1_REG_ADDR(), \
zend_may_throw(opline, ssa_op, op_array, ssa))) { +						if \
(!zend_jit_count(&dasm_state, opline, op1_info, OP1_REG_ADDR(), RES_REG_ADDR(), \
zend_may_throw(opline, ssa_op, op_array, ssa))) {  goto jit_failure;
 						}
 						goto done;
diff --git a/ext/opcache/jit/zend_jit_arm64.dasc \
b/ext/opcache/jit/zend_jit_arm64.dasc index e00bde7b3b6c..2cfe99a11e89 100644
--- a/ext/opcache/jit/zend_jit_arm64.dasc
+++ b/ext/opcache/jit/zend_jit_arm64.dasc
@@ -13563,10 +13563,8 @@ static int zend_jit_echo(dasm_State **Dst, const zend_op \
*opline, uint32_t op1_i  return 1;
 }
 
-static int zend_jit_strlen(dasm_State **Dst, const zend_op *opline, uint32_t \
op1_info, zend_jit_addr op1_addr) +static int zend_jit_strlen(dasm_State **Dst, const \
zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr, zend_jit_addr res_addr)  \
                {
-	zend_jit_addr res_addr = RES_ADDR();
-
 	if (opline->op1_type == IS_CONST) {
 		zval *zv;
 		size_t len;
@@ -13576,23 +13574,33 @@ static int zend_jit_strlen(dasm_State **Dst, const zend_op \
*opline, uint32_t op1  len = Z_STRLEN_P(zv);
 
 		|	SET_ZVAL_LVAL res_addr, len, TMP1, TMP2
-		|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
+		if (Z_MODE(res_addr) == IS_MEM_ZVAL) {
+			|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
+		} else if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, res_addr, \
MAY_BE_LONG)) { +			return 0;
+		}
 	} else {
 		ZEND_ASSERT((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_STRING);
 
-		|	GET_ZVAL_PTR REG0, op1_addr, TMP1
-		|	ldr REG0, [REG0, #offsetof(zend_string, len)]
-		|	SET_ZVAL_LVAL_FROM_REG res_addr, REG0, TMP1
-		|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
+		if (Z_MODE(res_addr) == IS_REG) {
+			|	GET_ZVAL_PTR Rx(Z_REG(res_addr)), op1_addr, TMP1
+			|	ldr Rx(Z_REG(res_addr)), [Rx(Z_REG(res_addr)), #offsetof(zend_string, len)]
+			if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, res_addr, \
MAY_BE_LONG)) { +				return 0;
+			}
+		} else {
+			|	GET_ZVAL_PTR REG0, op1_addr, TMP1
+			|	ldr REG0, [REG0, #offsetof(zend_string, len)]
+			|	SET_ZVAL_LVAL_FROM_REG res_addr, REG0, TMP1
+			|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
+		}
 		|	FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline, ZREG_TMP1, ZREG_TMP2
 	}
 	return 1;
 }
 
-static int zend_jit_count(dasm_State **Dst, const zend_op *opline, uint32_t \
op1_info, zend_jit_addr op1_addr, int may_throw) +static int \
zend_jit_count(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, \
zend_jit_addr op1_addr, zend_jit_addr res_addr, int may_throw)  {
-	zend_jit_addr res_addr = RES_ADDR();
-
 	if (opline->op1_type == IS_CONST) {
 		zval *zv;
 		zend_long count;
@@ -13602,16 +13610,29 @@ static int zend_jit_count(dasm_State **Dst, const zend_op \
*opline, uint32_t op1_  count = zend_hash_num_elements(Z_ARRVAL_P(zv));
 
 		|	SET_ZVAL_LVAL res_addr, count, TMP1, TMP2
-		|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
+		if (Z_MODE(res_addr) == IS_MEM_ZVAL) {
+			|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
+		} else if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, res_addr, \
MAY_BE_LONG)) { +			return 0;
+		}
 	} else {
 		ZEND_ASSERT((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY);
 		// Note: See the implementation of ZEND_COUNT in Zend/zend_vm_def.h - arrays do \
not contain IS_UNDEF starting in php 8.1+.  
-		|	GET_ZVAL_PTR REG0, op1_addr, TMP1
-		// Sign-extend the 32-bit value to a potentially 64-bit zend_long
-		|	ldr REG0w, [REG0, #offsetof(HashTable, nNumOfElements)]
-		|	SET_ZVAL_LVAL_FROM_REG res_addr, REG0, TMP1
-		|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
+		if (Z_MODE(res_addr) == IS_REG) {
+			|	GET_ZVAL_PTR Rx(Z_REG(res_addr)), op1_addr, TMP1
+			// Sign-extend the 32-bit value to a potentially 64-bit zend_long
+			|	ldr Rw(Z_REG(res_addr)), [Rx(Z_REG(res_addr)), #offsetof(HashTable, \
nNumOfElements)] +			if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, \
res_addr, MAY_BE_LONG)) { +				return 0;
+			}
+		} else {
+			|	GET_ZVAL_PTR REG0, op1_addr, TMP1
+			// Sign-extend the 32-bit value to a potentially 64-bit zend_long
+			|	ldr REG0w, [REG0, #offsetof(HashTable, nNumOfElements)]
+			|	SET_ZVAL_LVAL_FROM_REG res_addr, REG0, TMP1
+			|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG, TMP1w, TMP2
+		}
 		|	FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline, ZREG_TMP1, ZREG_TMP2
 	}
 
@@ -14686,6 +14707,14 @@ static bool zend_jit_opline_supports_reg(const zend_op_array \
*op_array, zend_ssa  return opline->op1_type == IS_CV
 				&& !(op1_info & ((MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF) - MAY_BE_LONG))
 				&& (op2_info & MAY_BE_LONG);
+		case ZEND_STRLEN:
+			op1_info = OP1_INFO();
+			return (opline->op1_type & (IS_CV|IS_CONST))
+				&& (op1_info & (MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF)) == MAY_BE_STRING;
+		case ZEND_COUNT:
+			op1_info = OP1_INFO();
+			return (opline->op1_type & (IS_CV|IS_CONST))
+				&& (op1_info & (MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF)) == MAY_BE_ARRAY;
 		case ZEND_BOOL:
 		case ZEND_BOOL_NOT:
 		case ZEND_JMPZ:
diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c
index f53dd8ff7818..a3053c4c3c92 100644
--- a/ext/opcache/jit/zend_jit_trace.c
+++ b/ext/opcache/jit/zend_jit_trace.c
@@ -5731,7 +5731,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec \
*trace_buffer, uint32_t par  break;
 							}
 						}
-						if (!zend_jit_strlen(&dasm_state, opline, op1_info, op1_addr)) {
+						if (!zend_jit_strlen(&dasm_state, opline, op1_info, op1_addr, RES_REG_ADDR())) \
{  goto jit_failure;
 						}
 						goto done;
@@ -5753,7 +5753,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec \
*trace_buffer, uint32_t par  break;
 							}
 						}
-						if (!zend_jit_count(&dasm_state, opline, op1_info, op1_addr, \
zend_may_throw(opline, ssa_op, op_array, ssa))) { +						if \
(!zend_jit_count(&dasm_state, opline, op1_info, op1_addr, RES_REG_ADDR(), \
zend_may_throw(opline, ssa_op, op_array, ssa))) {  goto jit_failure;
 						}
 						goto done;
diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc
index 91548af82b65..82657bde6cfb 100644
--- a/ext/opcache/jit/zend_jit_x86.dasc
+++ b/ext/opcache/jit/zend_jit_x86.dasc
@@ -14412,10 +14412,8 @@ static int zend_jit_echo(dasm_State **Dst, const zend_op \
*opline, uint32_t op1_i  return 1;
 }
 
-static int zend_jit_strlen(dasm_State **Dst, const zend_op *opline, uint32_t \
op1_info, zend_jit_addr op1_addr) +static int zend_jit_strlen(dasm_State **Dst, const \
zend_op *opline, uint32_t op1_info, zend_jit_addr op1_addr, zend_jit_addr res_addr)  \
                {
-	zend_jit_addr res_addr = RES_ADDR();
-
 	if (opline->op1_type == IS_CONST) {
 		zval *zv;
 		size_t len;
@@ -14425,23 +14423,33 @@ static int zend_jit_strlen(dasm_State **Dst, const zend_op \
*opline, uint32_t op1  len = Z_STRLEN_P(zv);
 
 		|	SET_ZVAL_LVAL res_addr, len
-		|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG
+		if (Z_MODE(res_addr) == IS_MEM_ZVAL) {
+			|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG
+		} else if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, res_addr, \
MAY_BE_LONG)) { +			return 0;
+		}
 	} else {
 		ZEND_ASSERT((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_STRING);
 
-		|	GET_ZVAL_PTR r0, op1_addr
-		|	mov r0, aword [r0 + offsetof(zend_string, len)]
-		|	SET_ZVAL_LVAL res_addr, r0
-		|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG
+		if (Z_MODE(res_addr) == IS_REG) {
+			|	GET_ZVAL_PTR Ra(Z_REG(res_addr)), op1_addr
+			|	mov Ra(Z_REG(res_addr)), aword [Ra(Z_REG(res_addr))+offsetof(zend_string, len)]
+			if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, res_addr, \
MAY_BE_LONG)) { +				return 0;
+			}
+		} else {
+			|	GET_ZVAL_PTR r0, op1_addr
+			|	mov r0, aword [r0 + offsetof(zend_string, len)]
+			|	SET_ZVAL_LVAL res_addr, r0
+			|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG
+		}
 		|	FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline
 	}
 	return 1;
 }
 
-static int zend_jit_count(dasm_State **Dst, const zend_op *opline, uint32_t \
op1_info, zend_jit_addr op1_addr, int may_throw) +static int \
zend_jit_count(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, \
zend_jit_addr op1_addr, zend_jit_addr res_addr, int may_throw)  {
-	zend_jit_addr res_addr = RES_ADDR();
-
 	if (opline->op1_type == IS_CONST) {
 		zval *zv;
 		zend_long count;
@@ -14451,16 +14459,29 @@ static int zend_jit_count(dasm_State **Dst, const zend_op \
*opline, uint32_t op1_  count = zend_hash_num_elements(Z_ARRVAL_P(zv));
 
 		|	SET_ZVAL_LVAL res_addr, count
-		|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG
+		if (Z_MODE(res_addr) == IS_MEM_ZVAL) {
+			|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG
+		} else if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, res_addr, \
MAY_BE_LONG)) { +			return 0;
+		}
 	} else {
 		ZEND_ASSERT((op1_info & (MAY_BE_UNDEF|MAY_BE_ANY|MAY_BE_REF)) == MAY_BE_ARRAY);
 		// Note: See the implementation of ZEND_COUNT in Zend/zend_vm_def.h - arrays do \
not contain IS_UNDEF starting in php 8.1+.  
-		|	GET_ZVAL_PTR r0, op1_addr
-		// Sign-extend the 32-bit value to a potentially 64-bit zend_long
-		|	mov eax, dword [r0 + offsetof(HashTable, nNumOfElements)]
-		|	SET_ZVAL_LVAL res_addr, r0
-		|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG
+		if (Z_MODE(res_addr) == IS_REG) {
+			|	GET_ZVAL_PTR Ra(Z_REG(res_addr)), op1_addr
+			// Sign-extend the 32-bit value to a potentially 64-bit zend_long
+			|	mov Rd(Z_REG(res_addr)), dword [Ra(Z_REG(res_addr))+offsetof(HashTable, \
nNumOfElements)] +			if (!zend_jit_store_var_if_necessary(Dst, opline->result.var, \
res_addr, MAY_BE_LONG)) { +				return 0;
+			}
+		} else {
+			|	GET_ZVAL_PTR r0, op1_addr
+			// Sign-extend the 32-bit value to a potentially 64-bit zend_long
+			|	mov eax, dword [r0 + offsetof(HashTable, nNumOfElements)]
+			|	SET_ZVAL_LVAL res_addr, r0
+			|	SET_ZVAL_TYPE_INFO res_addr, IS_LONG
+		}
 		|	FREE_OP opline->op1_type, opline->op1, op1_info, 0, opline
 	}
 
@@ -15552,6 +15573,14 @@ static bool zend_jit_opline_supports_reg(const zend_op_array \
*op_array, zend_ssa  return opline->op1_type == IS_CV
 				&& !(op1_info & ((MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF) - MAY_BE_LONG))
 				&& (op2_info & MAY_BE_LONG);
+		case ZEND_STRLEN:
+			op1_info = OP1_INFO();
+			return (opline->op1_type & (IS_CV|IS_CONST))
+				&& (op1_info & (MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF)) == MAY_BE_STRING;
+		case ZEND_COUNT:
+			op1_info = OP1_INFO();
+			return (opline->op1_type & (IS_CV|IS_CONST))
+				&& (op1_info & (MAY_BE_ANY|MAY_BE_REF|MAY_BE_UNDEF)) == MAY_BE_ARRAY;
 		case ZEND_BOOL:
 		case ZEND_BOOL_NOT:
 		case ZEND_JMPZ:

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


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic