summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/opcache/Optimizer/zend_inference.c2
-rw-r--r--ext/opcache/Optimizer/zend_ssa.c8
-rw-r--r--ext/opcache/Optimizer/zend_ssa.h5
3 files changed, 11 insertions, 4 deletions
diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c
index 1838fe387b..93e91a3872 100644
--- a/ext/opcache/Optimizer/zend_inference.c
+++ b/ext/opcache/Optimizer/zend_inference.c
@@ -3285,7 +3285,7 @@ static int zend_update_type_info(const zend_op_array *op_array,
break;
case ZEND_FE_FETCH_R:
case ZEND_FE_FETCH_RW:
- tmp = t2;
+ tmp = t2 & MAY_BE_REF;
if (t1 & MAY_BE_OBJECT) {
if (opline->opcode == ZEND_FE_FETCH_RW) {
tmp |= MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
diff --git a/ext/opcache/Optimizer/zend_ssa.c b/ext/opcache/Optimizer/zend_ssa.c
index 64680be745..b4d581f247 100644
--- a/ext/opcache/Optimizer/zend_ssa.c
+++ b/ext/opcache/Optimizer/zend_ssa.c
@@ -772,6 +772,10 @@ add_op1_def:
}
}
+ zend_ssa_op *fe_fetch_ssa_op = blocks[n].len != 0
+ && ((end-1)->opcode == ZEND_FE_FETCH_R || (end-1)->opcode == ZEND_FE_FETCH_RW)
+ && (end-1)->op2_type == IS_CV
+ ? &ssa_ops[blocks[n].start + blocks[n].len - 1] : NULL;
for (i = 0; i < blocks[n].successors_count; i++) {
int succ = blocks[n].successors[i];
zend_ssa_phi *p;
@@ -801,6 +805,10 @@ add_op1_def:
}
ZEND_ASSERT(j < blocks[succ].predecessors_count);
p->sources[j] = var[p->var];
+ if (fe_fetch_ssa_op && i == 0 && p->sources[j] == fe_fetch_ssa_op->op2_def) {
+ /* On the exit edge of an FE_FETCH, use the pre-modification value instead. */
+ p->sources[j] = fe_fetch_ssa_op->op2_use;
+ }
}
}
for (p = ssa_blocks[succ].phis; p && (p->pi >= 0); p = p->next) {
diff --git a/ext/opcache/Optimizer/zend_ssa.h b/ext/opcache/Optimizer/zend_ssa.h
index 799af21532..5abe44c93d 100644
--- a/ext/opcache/Optimizer/zend_ssa.h
+++ b/ext/opcache/Optimizer/zend_ssa.h
@@ -215,10 +215,9 @@ static zend_always_inline zend_bool zend_ssa_is_no_val_use(const zend_op *opline
if (opline->opcode == ZEND_ASSIGN || opline->opcode == ZEND_UNSET_CV) {
return ssa_op->op1_use == var && ssa_op->op2_use != var;
}
- // TODO: Re-enable this after changing the SSA structure.
- /*if (opline->opcode == ZEND_FE_FETCH_R) {
+ if (opline->opcode == ZEND_FE_FETCH_R || opline->opcode == ZEND_FE_FETCH_RW) {
return ssa_op->op2_use == var && ssa_op->op1_use != var;
- }*/
+ }
if (ssa_op->result_use == var
&& opline->opcode != ZEND_ADD_ARRAY_ELEMENT
&& opline->opcode != ZEND_ADD_ARRAY_UNPACK) {