From a5944f8dd5c45a95bb0cfdea52dd2301fab1f39c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 21 Apr 2016 23:12:28 +0200 Subject: [PATCH] Merge def and gen sets For live-variable analysis it does not matter if def includes variables that are previously use in the same block, the data flow equations still have the same result. As such there is no need to compute separate gen & def sets. I'm keeping the name "def", because use of "gen" in this context is pretty confusing (gen is usually the use set, not the def set). --- ext/opcache/Optimizer/zend_dfg.c | 51 +++++++++++-------------------- ext/opcache/Optimizer/zend_dfg.h | 1 - ext/opcache/Optimizer/zend_dump.c | 1 - ext/opcache/Optimizer/zend_ssa.c | 21 ++++++------- 4 files changed, 28 insertions(+), 46 deletions(-) diff --git a/ext/opcache/Optimizer/zend_dfg.c b/ext/opcache/Optimizer/zend_dfg.c index b45aac41fb..c1972128d5 100644 --- a/ext/opcache/Optimizer/zend_dfg.c +++ b/ext/opcache/Optimizer/zend_dfg.c @@ -25,21 +25,19 @@ 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_bitset tmp, def, use, in, out; zend_op *opline; 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++) { if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) { continue; @@ -84,6 +82,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: @@ -92,17 +93,6 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg case ZEND_SEND_REF: case ZEND_SEND_VAR_NO_REF: case ZEND_FE_RESET_RW: -op1_def: - if (!DFG_ISSET(use, set_size, j, var_num)) { - // FIXME: include into "use" to ...? - DFG_SET(use, set_size, j, var_num); - DFG_SET(def, set_size, j, var_num); - } - DFG_SET(gen, set_size, j, var_num); - 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: @@ -132,7 +122,11 @@ op1_def: case ZEND_FETCH_OBJ_FUNC_ARG: case ZEND_FETCH_OBJ_UNSET: case ZEND_VERIFY_RETURN_TYPE: - DFG_SET(gen, set_size, j, var_num); +op1_def: + // FIXME: include into "use" too ...? + 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, var_num)) { @@ -142,9 +136,9 @@ op1_use: } else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { var_num = EX_VAR_TO_NUM(opline->op1.var); if (opline->opcode == ZEND_VERIFY_RETURN_TYPE) { - DFG_SET(gen, set_size, j, var_num); - } - if (!DFG_ISSET(def, set_size, j, var_num)) { + 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); } } @@ -165,12 +159,9 @@ op1_use: case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: op2_def: - if (!DFG_ISSET(use, set_size, j, var_num)) { - // FIXME: include into "use" to ...? - DFG_SET(use, set_size, j, var_num); - DFG_SET(def, set_size, j, var_num); - } - DFG_SET(gen, set_size, j, var_num); + // 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: @@ -182,10 +173,7 @@ op2_use: } 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, var_num)) { - DFG_SET(def, set_size, j, var_num); - } - DFG_SET(gen, 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); @@ -194,10 +182,7 @@ op2_use: } if (opline->result_type & (IS_CV|IS_VAR|IS_TMP_VAR)) { var_num = EX_VAR_TO_NUM(opline->result.var); - if (!DFG_ISSET(use, set_size, j, var_num)) { - DFG_SET(def, set_size, j, var_num); - } - DFG_SET(gen, set_size, j, var_num); + DFG_SET(def, set_size, j, var_num); } } } diff --git a/ext/opcache/Optimizer/zend_dfg.h b/ext/opcache/Optimizer/zend_dfg.h index 9d864992ca..5ed8cfc5d0 100644 --- a/ext/opcache/Optimizer/zend_dfg.h +++ b/ext/opcache/Optimizer/zend_dfg.h @@ -26,7 +26,6 @@ typedef struct _zend_dfg { int vars; uint32_t size; zend_bitset tmp; - zend_bitset gen; zend_bitset def; zend_bitset use; zend_bitset in; diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c index ba5fb8a0ce..986e470345 100644 --- a/ext/opcache/Optimizer/zend_dump.c +++ b/ext/opcache/Optimizer/zend_dump.c @@ -1143,7 +1143,6 @@ void zend_dump_dfg(const zend_op_array *op_array, const zend_cfg *cfg, const zen for (j = 0; j < cfg->blocks_count; j++) { fprintf(stderr, " BB%d:\n", j); - zend_dump_var_set(op_array, "gen", DFG_BITSET(dfg->gen, dfg->size, j)); zend_dump_var_set(op_array, "def", DFG_BITSET(dfg->def, dfg->size, j)); zend_dump_var_set(op_array, "use", DFG_BITSET(dfg->use, dfg->size, j)); zend_dump_var_set(op_array, "in ", DFG_BITSET(dfg->in, dfg->size, j)); diff --git a/ext/opcache/Optimizer/zend_ssa.c b/ext/opcache/Optimizer/zend_ssa.c index 9d5f5a8e18..c70ecc52fc 100644 --- a/ext/opcache/Optimizer/zend_ssa.c +++ b/ext/opcache/Optimizer/zend_ssa.c @@ -765,7 +765,7 @@ int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t b zend_ssa_block *ssa_blocks; int blocks_count = ssa->cfg.blocks_count; uint32_t set_size; - zend_bitset tmp, gen, in; + zend_bitset tmp, def, in; int *var = NULL; int i, j, k, changed; zend_dfg dfg; @@ -784,8 +784,7 @@ int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t b dfg.size = set_size = zend_bitset_len(dfg.vars); dfg.tmp = do_alloca((set_size * sizeof(zend_ulong)) * (blocks_count * 5 + 1), dfg_use_heap); memset(dfg.tmp, 0, (set_size * sizeof(zend_ulong)) * (blocks_count * 5 + 1)); - dfg.gen = dfg.tmp + set_size; - dfg.def = dfg.gen + set_size * blocks_count; + dfg.def = dfg.tmp + set_size; dfg.use = dfg.def + set_size * blocks_count; dfg.in = dfg.use + set_size * blocks_count; dfg.out = dfg.in + set_size * blocks_count; @@ -800,10 +799,10 @@ int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t b } tmp = dfg.tmp; - gen = dfg.gen; + def = dfg.def; in = dfg.in; - /* SSA construction, Step 1: Propagate "gen" sets in merge points */ + /* SSA construction, Step 1: Propagate "def" sets in merge points */ do { changed = 0; for (j = 0; j < blocks_count; j++) { @@ -811,16 +810,16 @@ int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t b continue; } if (j >= 0 && (blocks[j].predecessors_count > 1 || j == 0)) { - zend_bitset_copy(tmp, gen + (j * set_size), set_size); + zend_bitset_copy(tmp, def + (j * set_size), set_size); for (k = 0; k < blocks[j].predecessors_count; k++) { i = ssa->cfg.predecessors[blocks[j].predecessor_offset + k]; while (i != -1 && i != blocks[j].idom) { - zend_bitset_union_with_intersection(tmp, tmp, gen + (i * set_size), in + (j * set_size), set_size); + zend_bitset_union_with_intersection(tmp, tmp, def + (i * set_size), in + (j * set_size), set_size); i = blocks[i].idom; } } - if (!zend_bitset_equal(gen + (j * set_size), tmp, set_size)) { - zend_bitset_copy(gen + (j * set_size), tmp, set_size); + if (!zend_bitset_equal(def + (j * set_size), tmp, set_size)) { + zend_bitset_copy(def + (j * set_size), tmp, set_size); changed = 1; } } @@ -850,7 +849,7 @@ int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t b for (k = 0; k < blocks[j].predecessors_count; k++) { i = ssa->cfg.predecessors[blocks[j].predecessor_offset + k]; while (i != -1 && i != blocks[j].idom) { - zend_bitset_union_with_intersection(tmp, tmp, gen + (i * set_size), in + (j * set_size), set_size); + zend_bitset_union_with_intersection(tmp, tmp, def + (i * set_size), in + (j * set_size), set_size); i = blocks[i].idom; } } @@ -907,7 +906,7 @@ int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t b if (p) { if (p->pi >= 0) { if (zend_bitset_in(in + (j * set_size), p->var) && - !zend_bitset_in(gen + (i * set_size), p->var)) { + !zend_bitset_in(def + (i * set_size), p->var)) { zend_bitset_incl(tmp, p->var); } } else { -- 2.50.1