1
0
mirror of https://github.com/php/php-src.git synced 2026-04-04 06:32:49 +02:00

Support CFG construction without live range splitting

We must not split at live range boundaries for SSA constructions,
otherwise an OP_DATA instruction may be separated into new block
and not picked up during renaming.

It's also unnecessary for this use case and only blows up the CFG.
This commit is contained in:
Nikita Popov
2016-02-09 12:40:02 +01:00
parent 4095d5f245
commit 7174af4074
4 changed files with 48 additions and 32 deletions

View File

@@ -1749,7 +1749,7 @@ void zend_optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx)
/* Build CFG */
checkpoint = zend_arena_checkpoint(ctx->arena);
if (zend_build_cfg(&ctx->arena, op_array, 0, &cfg, NULL) != SUCCESS) {
if (zend_build_cfg(&ctx->arena, op_array, ZEND_CFG_SPLIT_AT_LIVE_RANGES, &cfg, NULL) != SUCCESS) {
zend_arena_release(&ctx->arena, checkpoint);
return;
}

View File

@@ -91,33 +91,35 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg *
do {
changed = 0;
/* Add brk/cont paths */
for (j = 0; j < op_array->last_live_range; j++) {
if (op_array->live_range[j].var == (uint32_t)-1) {
/* this live range already removed */
continue;
}
b = blocks + block_map[op_array->live_range[j].start];
if (b->flags & ZEND_BB_REACHABLE) {
while (op_array->opcodes[b->start].opcode == ZEND_NOP && b->start != b->end) {
b->start++;
}
if (op_array->opcodes[b->start].opcode == ZEND_NOP &&
b->start == b->end &&
b->successors[0] == block_map[op_array->live_range[j].end]) {
/* mark as removed (empty live range) */
op_array->live_range[j].var = (uint32_t)-1;
if (cfg->split_at_live_ranges) {
/* Add live range paths */
for (j = 0; j < op_array->last_live_range; j++) {
if (op_array->live_range[j].var == (uint32_t)-1) {
/* this live range already removed */
continue;
}
b->flags |= ZEND_BB_GEN_VAR;
b = blocks + block_map[op_array->live_range[j].end];
b->flags |= ZEND_BB_KILL_VAR;
if (!(b->flags & ZEND_BB_REACHABLE)) {
changed = 1;
zend_mark_reachable(op_array->opcodes, blocks, b);
b = blocks + block_map[op_array->live_range[j].start];
if (b->flags & ZEND_BB_REACHABLE) {
while (op_array->opcodes[b->start].opcode == ZEND_NOP && b->start != b->end) {
b->start++;
}
if (op_array->opcodes[b->start].opcode == ZEND_NOP &&
b->start == b->end &&
b->successors[0] == block_map[op_array->live_range[j].end]) {
/* mark as removed (empty live range) */
op_array->live_range[j].var = (uint32_t)-1;
continue;
}
b->flags |= ZEND_BB_GEN_VAR;
b = blocks + block_map[op_array->live_range[j].end];
b->flags |= ZEND_BB_KILL_VAR;
if (!(b->flags & ZEND_BB_REACHABLE)) {
changed = 1;
zend_mark_reachable(op_array->opcodes, blocks, b);
}
} else {
ZEND_ASSERT(!(blocks[block_map[op_array->live_range[j].end]].flags & ZEND_BB_REACHABLE));
}
} else {
ZEND_ASSERT(!(blocks[block_map[op_array->live_range[j].end]].flags & ZEND_BB_REACHABLE));
}
}
@@ -244,6 +246,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
zend_basic_block *blocks;
zval *zv;
cfg->split_at_live_ranges = (build_flags & ZEND_CFG_SPLIT_AT_LIVE_RANGES) != 0;
cfg->map = block_map = zend_arena_calloc(arena, op_array->last, sizeof(uint32_t));
if (!block_map) {
return FAILURE;
@@ -391,10 +394,14 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
break;
}
}
for (j = 0; j < op_array->last_live_range; j++) {
BB_START(op_array->live_range[j].start);
BB_START(op_array->live_range[j].end);
if (cfg->split_at_live_ranges) {
for (j = 0; j < op_array->last_live_range; j++) {
BB_START(op_array->live_range[j].start);
BB_START(op_array->live_range[j].end);
}
}
if (op_array->last_try_catch) {
for (j = 0; j < op_array->last_try_catch; j++) {
BB_START(op_array->try_catch_array[j].try_op);

View File

@@ -86,6 +86,7 @@ typedef struct _zend_cfg {
zend_basic_block *blocks; /* array of basic blocks */
int *predecessors;
uint32_t *map;
unsigned int split_at_live_ranges : 1;
} zend_cfg;
/* Build Flags */
@@ -94,6 +95,7 @@ typedef struct _zend_cfg {
#define ZEND_SSA_DEBUG_LIVENESS (1<<29)
#define ZEND_SSA_DEBUG_PHI_PLACEMENT (1<<28)
#define ZEND_SSA_RC_INFERENCE (1<<27)
#define ZEND_CFG_SPLIT_AT_LIVE_RANGES (1<<26)
#define CRT_CONSTANT_EX(op_array, node, rt_constants) \
((rt_constants) ? \

View File

@@ -957,10 +957,17 @@ void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, cons
if (op_array->last_live_range) {
fprintf(stderr, "LIVE RANGES:\n");
for (i = 0; i < op_array->last_live_range; i++) {
fprintf(stderr, " %u: BB%u - BB%u ",
EX_VAR_TO_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK),
cfg->map[op_array->live_range[i].start],
cfg->map[op_array->live_range[i].end]);
if (cfg->split_at_live_ranges) {
fprintf(stderr, " %u: BB%u - BB%u ",
EX_VAR_TO_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK),
cfg->map[op_array->live_range[i].start],
cfg->map[op_array->live_range[i].end]);
} else {
fprintf(stderr, " %u: L%u - L%u ",
EX_VAR_TO_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK),
op_array->live_range[i].start,
op_array->live_range[i].end);
}
switch (op_array->live_range[i].var & ZEND_LIVE_MASK) {
case ZEND_LIVE_TMPVAR:
fprintf(stderr, "(tmp/var)\n");