diff options
-rw-r--r-- | ext/opcache/Optimizer/zend_inference.c | 2 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_ssa.c | 8 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_ssa.h | 5 |
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) { |