]> granicus.if.org Git - php/commitdiff
Respect RC_INFERENCE during DFG construction
authorNikita Popov <nikic@php.net>
Sat, 23 Jan 2016 15:56:27 +0000 (16:56 +0100)
committerNikita Popov <nikic@php.net>
Sun, 24 Jan 2016 22:04:06 +0000 (23:04 +0100)
To avoid inserting phis that are only relevant with rc inference
enabled. Suprisingly, this affects only 0.8% of phis.

ext/opcache/Optimizer/zend_dfg.c
ext/opcache/Optimizer/zend_dfg.h
ext/opcache/Optimizer/zend_ssa.c

index 4bf5d7913fe5d0c71d79f0de3e4be272359045da..8644a7c27e5b113c57db95eb248fe324bd79f6a0 100644 (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));
                                                        }
index ebbb98a65b0877ce97c7b84041f30dabbab5705f..9d864992cacfaa47ccaa994f5885c60ffc2f895f 100644 (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()
 
index b984d41bad7b214597d53b40e57343d14645e9a7..e80be77d2f068fdf237f239587fe045cf665377a 100644 (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;
        }