diff --git a/ext/opcache/Optimizer/zend_dfg.c b/ext/opcache/Optimizer/zend_dfg.c index 4bf5d7913fe..8644a7c27e5 100644 --- a/ext/opcache/Optimizer/zend_dfg.c +++ b/ext/opcache/Optimizer/zend_dfg.c @@ -20,7 +20,7 @@ #include "zend_compile.h" #include "zend_dfg.h" -int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg *dfg) /* {{{ */ +int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg *dfg, uint32_t build_flags) /* {{{ */ { int set_size; zend_basic_block *blocks = cfg->blocks; @@ -89,6 +89,24 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg } if (opline->op1_type == IS_CV) { switch (opline->opcode) { + case ZEND_ADD_ARRAY_ELEMENT: + case ZEND_INIT_ARRAY: + if ((build_flags & ZEND_SSA_RC_INFERENCE) + || (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + goto op1_def; + } + goto op1_use; + case ZEND_FE_RESET_R: + if (build_flags & ZEND_SSA_RC_INFERENCE) { + goto op1_def; + } + goto op1_use; + case ZEND_YIELD: + if ((build_flags & ZEND_SSA_RC_INFERENCE) + || (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + goto op1_def; + } + goto op1_use; case ZEND_ASSIGN: case ZEND_ASSIGN_REF: case ZEND_BIND_GLOBAL: @@ -96,11 +114,8 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg case ZEND_SEND_VAR_EX: case ZEND_SEND_REF: case ZEND_SEND_VAR_NO_REF: - case ZEND_FE_RESET_R: case ZEND_FE_RESET_RW: - case ZEND_ADD_ARRAY_ELEMENT: - case ZEND_INIT_ARRAY: - case ZEND_YIELD: +op1_def: if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(opline->op1.var))) { // FIXME: include into "use" to ...? DFG_SET(use, set_size, j, EX_VAR_TO_NUM(opline->op1.var)); @@ -141,6 +156,7 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg case ZEND_FETCH_OBJ_UNSET: DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->op1.var)); default: +op1_use: if (!DFG_ISSET(def, set_size, j, EX_VAR_TO_NUM(opline->op1.var))) { DFG_SET(use, set_size, j, EX_VAR_TO_NUM(opline->op1.var)); } @@ -154,10 +170,19 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg if (opline->op2_type == IS_CV) { switch (opline->opcode) { case ZEND_ASSIGN: + if (build_flags & ZEND_SSA_RC_INFERENCE) { + goto op2_def; + } + goto op2_use; + case ZEND_BIND_LEXICAL: + if ((build_flags & ZEND_SSA_RC_INFERENCE) || opline->extended_value) { + goto op2_def; + } + goto op2_use; case ZEND_ASSIGN_REF: case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: - case ZEND_BIND_LEXICAL: +op2_def: if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(opline->op2.var))) { // FIXME: include into "use" to ...? DFG_SET(use, set_size, j, EX_VAR_TO_NUM(opline->op2.var)); @@ -166,6 +191,7 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->op2.var)); break; default: +op2_use: if (!DFG_ISSET(def, set_size, j, EX_VAR_TO_NUM(opline->op2.var))) { DFG_SET(use, set_size, j, EX_VAR_TO_NUM(opline->op2.var)); } diff --git a/ext/opcache/Optimizer/zend_dfg.h b/ext/opcache/Optimizer/zend_dfg.h index ebbb98a65b0..9d864992cac 100644 --- a/ext/opcache/Optimizer/zend_dfg.h +++ b/ext/opcache/Optimizer/zend_dfg.h @@ -44,7 +44,7 @@ typedef struct _zend_dfg { BEGIN_EXTERN_C() -int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg *dfg); +int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg *dfg, uint32_t build_flags); END_EXTERN_C() diff --git a/ext/opcache/Optimizer/zend_ssa.c b/ext/opcache/Optimizer/zend_ssa.c index b984d41bad7..e80be77d2f0 100644 --- a/ext/opcache/Optimizer/zend_ssa.c +++ b/ext/opcache/Optimizer/zend_ssa.c @@ -532,7 +532,7 @@ int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t b dfg.in = dfg.use + set_size * blocks_count; dfg.out = dfg.in + set_size * blocks_count; - if (zend_build_dfg(op_array, &ssa->cfg, &dfg) != SUCCESS) { + if (zend_build_dfg(op_array, &ssa->cfg, &dfg, build_flags) != SUCCESS) { free_alloca(dfg.tmp, dfg_use_heap); return FAILURE; }