mirror of
https://github.com/php/php-src.git
synced 2025-08-18 23:18:56 +02:00
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).
This commit is contained in:
parent
261eb5cc89
commit
a5944f8dd5
4 changed files with 28 additions and 46 deletions
|
@ -25,21 +25,19 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg
|
||||||
int set_size;
|
int set_size;
|
||||||
zend_basic_block *blocks = cfg->blocks;
|
zend_basic_block *blocks = cfg->blocks;
|
||||||
int blocks_count = cfg->blocks_count;
|
int blocks_count = cfg->blocks_count;
|
||||||
zend_bitset tmp, gen, def, use, in, out;
|
zend_bitset tmp, def, use, in, out;
|
||||||
zend_op *opline;
|
zend_op *opline;
|
||||||
uint32_t k, var_num;
|
uint32_t k, var_num;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
/* FIXME: can we use "gen" instead of "def" for flow analyzing? */
|
|
||||||
set_size = dfg->size;
|
set_size = dfg->size;
|
||||||
tmp = dfg->tmp;
|
tmp = dfg->tmp;
|
||||||
gen = dfg->gen;
|
|
||||||
def = dfg->def;
|
def = dfg->def;
|
||||||
use = dfg->use;
|
use = dfg->use;
|
||||||
in = dfg->in;
|
in = dfg->in;
|
||||||
out = dfg->out;
|
out = dfg->out;
|
||||||
|
|
||||||
/* Collect "gen", "def" and "use" sets */
|
/* Collect "def" and "use" sets */
|
||||||
for (j = 0; j < blocks_count; j++) {
|
for (j = 0; j < blocks_count; j++) {
|
||||||
if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
|
if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) {
|
||||||
continue;
|
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_def;
|
||||||
}
|
}
|
||||||
goto op1_use;
|
goto op1_use;
|
||||||
|
case ZEND_UNSET_VAR:
|
||||||
|
ZEND_ASSERT(opline->extended_value & ZEND_QUICK_SET);
|
||||||
|
/* break missing intentionally */
|
||||||
case ZEND_ASSIGN:
|
case ZEND_ASSIGN:
|
||||||
case ZEND_ASSIGN_REF:
|
case ZEND_ASSIGN_REF:
|
||||||
case ZEND_BIND_GLOBAL:
|
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_REF:
|
||||||
case ZEND_SEND_VAR_NO_REF:
|
case ZEND_SEND_VAR_NO_REF:
|
||||||
case ZEND_FE_RESET_RW:
|
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_ADD:
|
||||||
case ZEND_ASSIGN_SUB:
|
case ZEND_ASSIGN_SUB:
|
||||||
case ZEND_ASSIGN_MUL:
|
case ZEND_ASSIGN_MUL:
|
||||||
|
@ -132,7 +122,11 @@ op1_def:
|
||||||
case ZEND_FETCH_OBJ_FUNC_ARG:
|
case ZEND_FETCH_OBJ_FUNC_ARG:
|
||||||
case ZEND_FETCH_OBJ_UNSET:
|
case ZEND_FETCH_OBJ_UNSET:
|
||||||
case ZEND_VERIFY_RETURN_TYPE:
|
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:
|
default:
|
||||||
op1_use:
|
op1_use:
|
||||||
if (!DFG_ISSET(def, set_size, j, var_num)) {
|
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)) {
|
} else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) {
|
||||||
var_num = EX_VAR_TO_NUM(opline->op1.var);
|
var_num = EX_VAR_TO_NUM(opline->op1.var);
|
||||||
if (opline->opcode == ZEND_VERIFY_RETURN_TYPE) {
|
if (opline->opcode == ZEND_VERIFY_RETURN_TYPE) {
|
||||||
DFG_SET(gen, set_size, j, var_num);
|
DFG_SET(use, set_size, j, var_num);
|
||||||
}
|
DFG_SET(def, set_size, j, var_num);
|
||||||
if (!DFG_ISSET(def, set_size, j, var_num)) {
|
} else if (!DFG_ISSET(def, set_size, j, var_num)) {
|
||||||
DFG_SET(use, 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_R:
|
||||||
case ZEND_FE_FETCH_RW:
|
case ZEND_FE_FETCH_RW:
|
||||||
op2_def:
|
op2_def:
|
||||||
if (!DFG_ISSET(use, set_size, j, var_num)) {
|
// FIXME: include into "use" too ...?
|
||||||
// FIXME: include into "use" to ...?
|
DFG_SET(use, set_size, j, var_num);
|
||||||
DFG_SET(use, set_size, j, var_num);
|
DFG_SET(def, set_size, j, var_num);
|
||||||
DFG_SET(def, set_size, j, var_num);
|
|
||||||
}
|
|
||||||
DFG_SET(gen, set_size, j, var_num);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
op2_use:
|
op2_use:
|
||||||
|
@ -182,10 +173,7 @@ op2_use:
|
||||||
} else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
|
} else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) {
|
||||||
var_num = EX_VAR_TO_NUM(opline->op2.var);
|
var_num = EX_VAR_TO_NUM(opline->op2.var);
|
||||||
if (opline->opcode == ZEND_FE_FETCH_R || opline->opcode == ZEND_FE_FETCH_RW) {
|
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(def, set_size, j, var_num);
|
|
||||||
}
|
|
||||||
DFG_SET(gen, set_size, j, var_num);
|
|
||||||
} else {
|
} else {
|
||||||
if (!DFG_ISSET(def, set_size, j, var_num)) {
|
if (!DFG_ISSET(def, set_size, j, var_num)) {
|
||||||
DFG_SET(use, 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)) {
|
if (opline->result_type & (IS_CV|IS_VAR|IS_TMP_VAR)) {
|
||||||
var_num = EX_VAR_TO_NUM(opline->result.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(def, set_size, j, var_num);
|
|
||||||
}
|
|
||||||
DFG_SET(gen, set_size, j, var_num);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ typedef struct _zend_dfg {
|
||||||
int vars;
|
int vars;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
zend_bitset tmp;
|
zend_bitset tmp;
|
||||||
zend_bitset gen;
|
|
||||||
zend_bitset def;
|
zend_bitset def;
|
||||||
zend_bitset use;
|
zend_bitset use;
|
||||||
zend_bitset in;
|
zend_bitset in;
|
||||||
|
|
|
@ -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++) {
|
for (j = 0; j < cfg->blocks_count; j++) {
|
||||||
fprintf(stderr, " BB%d:\n", 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, "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, "use", DFG_BITSET(dfg->use, dfg->size, j));
|
||||||
zend_dump_var_set(op_array, "in ", DFG_BITSET(dfg->in, dfg->size, j));
|
zend_dump_var_set(op_array, "in ", DFG_BITSET(dfg->in, dfg->size, j));
|
||||||
|
|
|
@ -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;
|
zend_ssa_block *ssa_blocks;
|
||||||
int blocks_count = ssa->cfg.blocks_count;
|
int blocks_count = ssa->cfg.blocks_count;
|
||||||
uint32_t set_size;
|
uint32_t set_size;
|
||||||
zend_bitset tmp, gen, in;
|
zend_bitset tmp, def, in;
|
||||||
int *var = NULL;
|
int *var = NULL;
|
||||||
int i, j, k, changed;
|
int i, j, k, changed;
|
||||||
zend_dfg dfg;
|
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.size = set_size = zend_bitset_len(dfg.vars);
|
||||||
dfg.tmp = do_alloca((set_size * sizeof(zend_ulong)) * (blocks_count * 5 + 1), dfg_use_heap);
|
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));
|
memset(dfg.tmp, 0, (set_size * sizeof(zend_ulong)) * (blocks_count * 5 + 1));
|
||||||
dfg.gen = dfg.tmp + set_size;
|
dfg.def = dfg.tmp + set_size;
|
||||||
dfg.def = dfg.gen + set_size * blocks_count;
|
|
||||||
dfg.use = dfg.def + set_size * blocks_count;
|
dfg.use = dfg.def + set_size * blocks_count;
|
||||||
dfg.in = dfg.use + set_size * blocks_count;
|
dfg.in = dfg.use + set_size * blocks_count;
|
||||||
dfg.out = dfg.in + 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;
|
tmp = dfg.tmp;
|
||||||
gen = dfg.gen;
|
def = dfg.def;
|
||||||
in = dfg.in;
|
in = dfg.in;
|
||||||
|
|
||||||
/* SSA construction, Step 1: Propagate "gen" sets in merge points */
|
/* SSA construction, Step 1: Propagate "def" sets in merge points */
|
||||||
do {
|
do {
|
||||||
changed = 0;
|
changed = 0;
|
||||||
for (j = 0; j < blocks_count; j++) {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
if (j >= 0 && (blocks[j].predecessors_count > 1 || j == 0)) {
|
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++) {
|
for (k = 0; k < blocks[j].predecessors_count; k++) {
|
||||||
i = ssa->cfg.predecessors[blocks[j].predecessor_offset + k];
|
i = ssa->cfg.predecessors[blocks[j].predecessor_offset + k];
|
||||||
while (i != -1 && i != blocks[j].idom) {
|
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;
|
i = blocks[i].idom;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!zend_bitset_equal(gen + (j * set_size), tmp, set_size)) {
|
if (!zend_bitset_equal(def + (j * set_size), tmp, set_size)) {
|
||||||
zend_bitset_copy(gen + (j * set_size), tmp, set_size);
|
zend_bitset_copy(def + (j * set_size), tmp, set_size);
|
||||||
changed = 1;
|
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++) {
|
for (k = 0; k < blocks[j].predecessors_count; k++) {
|
||||||
i = ssa->cfg.predecessors[blocks[j].predecessor_offset + k];
|
i = ssa->cfg.predecessors[blocks[j].predecessor_offset + k];
|
||||||
while (i != -1 && i != blocks[j].idom) {
|
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;
|
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) {
|
||||||
if (p->pi >= 0) {
|
if (p->pi >= 0) {
|
||||||
if (zend_bitset_in(in + (j * set_size), p->var) &&
|
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);
|
zend_bitset_incl(tmp, p->var);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue