Respect RC_INFERENCE during DFG construction

To avoid inserting phis that are only relevant with rc inference
enabled. Suprisingly, this affects only 0.8% of phis.
This commit is contained in:
Nikita Popov 2016-01-23 16:56:27 +01:00
parent 949aaea66e
commit c2fea2a46d
3 changed files with 34 additions and 8 deletions

View File

@ -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));
}

View File

@ -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()

View File

@ -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;
}