From: Dmitry Stogov Date: Tue, 12 Nov 2019 10:49:55 +0000 (+0300) Subject: Optimize $x === null into is_null($x) X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=36afe4e39ec724eab19c54c1492db030721d0ec1;p=php Optimize $x === null into is_null($x) --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 982becce4b..fbbb5163f4 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -7385,8 +7385,28 @@ void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */ break; } } - } - if (opcode == ZEND_CONCAT) { + } else if (opcode == ZEND_IS_IDENTICAL || opcode == ZEND_IS_NOT_IDENTICAL) { + /* convert $x === null to is_null($x) (i.e. ZEND_TYPE_CHECK opcode). Do the same thing for false/true. (covers IS_NULL, IS_FALSE, and IS_TRUE) */ + if (left_node.op_type == IS_CONST) { + if (Z_TYPE(left_node.u.constant) <= IS_TRUE && Z_TYPE(left_node.u.constant) >= IS_NULL) { + zend_op *opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &right_node, NULL); + opline->extended_value = + (opcode == ZEND_IS_IDENTICAL) ? + (1 << Z_TYPE(left_node.u.constant)) : + (MAY_BE_ANY - (1 << Z_TYPE(left_node.u.constant))); + return; + } + } else if (right_node.op_type == IS_CONST) { + if (Z_TYPE(right_node.u.constant) <= IS_TRUE && Z_TYPE(right_node.u.constant) >= IS_NULL) { + zend_op *opline = zend_emit_op_tmp(result, ZEND_TYPE_CHECK, &left_node, NULL); + opline->extended_value = + (opcode == ZEND_IS_IDENTICAL) ? + (1 << Z_TYPE(right_node.u.constant)) : + (MAY_BE_ANY - (1 << Z_TYPE(right_node.u.constant))); + return; + } + } + } else if (opcode == ZEND_CONCAT) { /* convert constant operands to strings at compile-time */ if (left_node.op_type == IS_CONST) { if (Z_TYPE(left_node.u.constant) == IS_ARRAY) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 01b3bcf9f2..a8ab1ff375 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -7848,7 +7848,7 @@ ZEND_VM_HOT_NOCONST_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMPVAR|CV, ANY, TYPE_MAS value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R); if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { ZEND_VM_C_LABEL(type_check_resource): - if (EXPECTED(Z_TYPE_P(value) != IS_RESOURCE) + if (opline->extended_value != MAY_BE_RESOURCE || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) { result = 1; } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a5b1e2e752..5da5452b69 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4436,7 +4436,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_C value = RT_CONSTANT(opline, opline->op1); if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { type_check_resource: - if (EXPECTED(Z_TYPE_P(value) != IS_RESOURCE) + if (opline->extended_value != MAY_BE_RESOURCE || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) { result = 1; } @@ -13254,7 +13254,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_TM value = _get_zval_ptr_var(opline->op1.var EXECUTE_DATA_CC); if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { type_check_resource: - if (EXPECTED(Z_TYPE_P(value) != IS_RESOURCE) + if (opline->extended_value != MAY_BE_RESOURCE || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) { result = 1; } @@ -36407,7 +36407,7 @@ static ZEND_VM_HOT ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CV value = EX_VAR(opline->op1.var); if ((opline->extended_value >> (uint32_t)Z_TYPE_P(value)) & 1) { type_check_resource: - if (EXPECTED(Z_TYPE_P(value) != IS_RESOURCE) + if (opline->extended_value != MAY_BE_RESOURCE || EXPECTED(NULL != zend_rsrc_list_get_rsrc_type(Z_RES_P(value)))) { result = 1; } diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c index 68b3d4a99f..515532b3b4 100644 --- a/ext/opcache/Optimizer/zend_dump.c +++ b/ext/opcache/Optimizer/zend_dump.c @@ -516,7 +516,8 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block * fprintf(stderr, " (bool)"); break; default: - fprintf(stderr, " (\?\?\?)"); + fprintf(stderr, " TYPE"); + zend_dump_type_info(opline->extended_value, NULL, 0, dump_flags); break; } } else if (ZEND_VM_EXT_EVAL == (flags & ZEND_VM_EXT_MASK)) { diff --git a/ext/opcache/Optimizer/zend_ssa.c b/ext/opcache/Optimizer/zend_ssa.c index 5fd4ccbd9d..14d88bc39b 100644 --- a/ext/opcache/Optimizer/zend_ssa.c +++ b/ext/opcache/Optimizer/zend_ssa.c @@ -161,7 +161,7 @@ static inline void pi_not_type_mask(zend_ssa_phi *phi, uint32_t type_mask) { } static inline uint32_t mask_for_type_check(uint32_t type) { if (type & MAY_BE_ARRAY) { - return MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; + return type | (MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF); } else { return type; } diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index dc40387c1b..568dab3f01 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -8003,7 +8003,7 @@ static int zend_jit_type_check(dasm_State **Dst, const zend_op *opline, int b, i zend_bool smart_branch = 0; zend_jit_addr op1_addr = zend_jit_decode_op(op_array, opline->op1_type, opline->op1, opline, NULL, -1); - if (opline->extended_value & MAY_BE_RESOURCE) { + if (opline->extended_value == MAY_BE_RESOURCE) { // TODO: support for is_resource() ??? goto fallback; }