summaryrefslogtreecommitdiff
path: root/ext/opcache/Optimizer/zend_dfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/opcache/Optimizer/zend_dfg.c')
-rw-r--r--ext/opcache/Optimizer/zend_dfg.c105
1 files changed, 50 insertions, 55 deletions
diff --git a/ext/opcache/Optimizer/zend_dfg.c b/ext/opcache/Optimizer/zend_dfg.c
index e72afd1701..97fc846d3c 100644
--- a/ext/opcache/Optimizer/zend_dfg.c
+++ b/ext/opcache/Optimizer/zend_dfg.c
@@ -25,43 +25,45 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg
int set_size;
zend_basic_block *blocks = cfg->blocks;
int blocks_count = cfg->blocks_count;
- zend_bitset tmp, gen, def, use, in, out;
- zend_op *opline;
- uint32_t k;
+ zend_bitset tmp, def, use, in, out;
+ uint32_t k, var_num;
int j;
- /* FIXME: can we use "gen" instead of "def" for flow analyzing? */
set_size = dfg->size;
tmp = dfg->tmp;
- gen = dfg->gen;
def = dfg->def;
use = dfg->use;
in = dfg->in;
out = dfg->out;
- /* Collect "gen", "def" and "use" sets */
+ /* Collect "def" and "use" sets */
for (j = 0; j < blocks_count; j++) {
+ zend_op *opline, *end;
if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
continue;
}
- for (k = blocks[j].start; k <= blocks[j].end; k++) {
- opline = op_array->opcodes + k;
+
+ opline = op_array->opcodes + blocks[j].start;
+ end = opline + blocks[j].len;
+ for (; opline < end; opline++) {
if (opline->opcode != ZEND_OP_DATA) {
zend_op *next = opline + 1;
- if (k < blocks[j].end &&
- next->opcode == ZEND_OP_DATA) {
+ if (next < end && next->opcode == ZEND_OP_DATA) {
if (next->op1_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
- if (!DFG_ISSET(def, set_size, j, EX_VAR_TO_NUM(next->op1.var))) {
- DFG_SET(use, set_size, j, EX_VAR_TO_NUM(next->op1.var));
+ var_num = EX_VAR_TO_NUM(next->op1.var);
+ if (!DFG_ISSET(def, set_size, j, var_num)) {
+ DFG_SET(use, set_size, j, var_num);
}
}
if (next->op2_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
- if (!DFG_ISSET(def, set_size, j,EX_VAR_TO_NUM(next->op2.var))) {
- DFG_SET(use, set_size, j, EX_VAR_TO_NUM(next->op2.var));
+ var_num = EX_VAR_TO_NUM(next->op2.var);
+ if (!DFG_ISSET(def, set_size, j, var_num)) {
+ DFG_SET(use, set_size, j, var_num);
}
}
}
if (opline->op1_type == IS_CV) {
+ var_num = EX_VAR_TO_NUM(opline->op1.var);
switch (opline->opcode) {
case ZEND_ADD_ARRAY_ELEMENT:
case ZEND_INIT_ARRAY:
@@ -81,6 +83,9 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg
goto op1_def;
}
goto op1_use;
+ case ZEND_UNSET_VAR:
+ ZEND_ASSERT(opline->extended_value & ZEND_QUICK_SET);
+ /* break missing intentionally */
case ZEND_ASSIGN:
case ZEND_ASSIGN_REF:
case ZEND_BIND_GLOBAL:
@@ -88,18 +93,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_SEND_VAR_NO_REF_EX:
case ZEND_FE_RESET_RW:
-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));
- DFG_SET(def, set_size, j, EX_VAR_TO_NUM(opline->op1.var));
- }
- DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->op1.var));
- break;
- case ZEND_UNSET_VAR:
- ZEND_ASSERT(opline->extended_value & ZEND_QUICK_SET);
- /* break missing intentionally */
case ZEND_ASSIGN_ADD:
case ZEND_ASSIGN_SUB:
case ZEND_ASSIGN_MUL:
@@ -128,19 +123,30 @@ op1_def:
case ZEND_FETCH_OBJ_RW:
case ZEND_FETCH_OBJ_FUNC_ARG:
case ZEND_FETCH_OBJ_UNSET:
- DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->op1.var));
+ case ZEND_VERIFY_RETURN_TYPE:
+op1_def:
+ /* `def` always come along with dtor or separation,
+ * thus the origin var info might be also `use`d in the feature(CG) */
+ DFG_SET(use, set_size, j, var_num);
+ DFG_SET(def, set_size, j, var_num);
+ break;
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));
+ if (!DFG_ISSET(def, set_size, j, var_num)) {
+ DFG_SET(use, set_size, j, var_num);
}
}
} else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
- 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));
+ var_num = EX_VAR_TO_NUM(opline->op1.var);
+ if (opline->opcode == ZEND_VERIFY_RETURN_TYPE) {
+ DFG_SET(use, set_size, j, var_num);
+ DFG_SET(def, set_size, j, var_num);
+ } else if (!DFG_ISSET(def, set_size, j, var_num)) {
+ DFG_SET(use, set_size, j, var_num);
}
}
if (opline->op2_type == IS_CV) {
+ var_num = EX_VAR_TO_NUM(opline->op2.var);
switch (opline->opcode) {
case ZEND_ASSIGN:
if (build_flags & ZEND_SSA_RC_INFERENCE) {
@@ -156,42 +162,30 @@ op1_use:
case ZEND_FE_FETCH_R:
case ZEND_FE_FETCH_RW:
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));
- DFG_SET(def, set_size, j, EX_VAR_TO_NUM(opline->op2.var));
- }
- DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->op2.var));
+ // FIXME: include into "use" too ...?
+ DFG_SET(use, set_size, j, var_num);
+ DFG_SET(def, set_size, j, var_num);
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));
+ if (!DFG_ISSET(def, set_size, j, var_num)) {
+ DFG_SET(use, set_size, j, var_num);
}
break;
}
} else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
+ var_num = EX_VAR_TO_NUM(opline->op2.var);
if (opline->opcode == ZEND_FE_FETCH_R || opline->opcode == ZEND_FE_FETCH_RW) {
- if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(opline->op2.var))) {
- DFG_SET(def, set_size, j, EX_VAR_TO_NUM(opline->op2.var));
- }
- DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->op2.var));
+ DFG_SET(def, set_size, j, var_num);
} else {
- 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));
+ if (!DFG_ISSET(def, set_size, j, var_num)) {
+ DFG_SET(use, set_size, j, var_num);
}
}
}
- if (opline->result_type == IS_CV) {
- if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(opline->result.var))) {
- DFG_SET(def, set_size, j, EX_VAR_TO_NUM(opline->result.var));
- }
- DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->result.var));
- } else if (opline->result_type & (IS_VAR|IS_TMP_VAR)) {
- if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(opline->result.var))) {
- DFG_SET(def, set_size, j, EX_VAR_TO_NUM(opline->result.var));
- }
- DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->result.var));
+ if (opline->result_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
+ var_num = EX_VAR_TO_NUM(opline->result.var);
+ DFG_SET(def, set_size, j, var_num);
}
}
}
@@ -200,8 +194,9 @@ op2_use:
/* Calculate "in" and "out" sets */
{
uint32_t worklist_len = zend_bitset_len(blocks_count);
+ zend_bitset worklist;
ALLOCA_FLAG(use_heap);
- zend_bitset worklist = ZEND_BITSET_ALLOCA(worklist_len, use_heap);
+ worklist = ZEND_BITSET_ALLOCA(worklist_len, use_heap);
memset(worklist, 0, worklist_len * ZEND_BITSET_ELM_SIZE);
for (j = 0; j < blocks_count; j++) {
zend_bitset_incl(worklist, j);