Skip to content

Commit

Permalink
Use arena for temporary data.
Browse files Browse the repository at this point in the history
  • Loading branch information
dstogov committed Jul 7, 2017
1 parent 93d3e7d commit 58f7c17
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 81 deletions.
2 changes: 1 addition & 1 deletion ext/opcache/Optimizer/dfa_pass.c
Expand Up @@ -453,7 +453,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
zval tmp;

if (ZEND_OPTIMIZER_PASS_8 & ctx->optimization_level) {
if (sccp_optimize_op_array(op_array, ssa, call_map)) {
if (sccp_optimize_op_array(ctx, op_array, ssa, call_map)) {
remove_nops = 1;
}
if (ZEND_FUNC_INFO(op_array)) {
Expand Down
48 changes: 24 additions & 24 deletions ext/opcache/Optimizer/sccp.c
Expand Up @@ -1348,57 +1348,57 @@ static int replace_constant_operands(sccp_ctx *ctx) {
return removed_ops;
}

static void sccp_context_init(sccp_ctx *ctx,
static void sccp_context_init(zend_optimizer_ctx *ctx, sccp_ctx *sccp,
zend_ssa *ssa, zend_op_array *op_array, zend_call_info **call_map) {
int i;
ctx->call_map = call_map;
ctx->values = emalloc(sizeof(zval) * ssa->vars_count);
sccp->call_map = call_map;
sccp->values = zend_arena_alloc(&ctx->arena, sizeof(zval) * ssa->vars_count);

MAKE_TOP(&ctx->top);
MAKE_BOT(&ctx->bot);
MAKE_TOP(&sccp->top);
MAKE_BOT(&sccp->bot);

i = 0;
for (; i < op_array->last_var; ++i) {
/* These are all undefined variables, which we have to mark BOT.
* Otherwise the undefined variable warning might not be preserved. */
MAKE_BOT(&ctx->values[i]);
MAKE_BOT(&sccp->values[i]);
}
for (; i < ssa->vars_count; ++i) {
if (ssa->vars[i].alias) {
MAKE_BOT(&ctx->values[i]);
MAKE_BOT(&sccp->values[i]);
} else {
MAKE_TOP(&ctx->values[i]);
MAKE_TOP(&sccp->values[i]);
}
}
}

static void sccp_context_free(sccp_ctx *ctx) {
static void sccp_context_free(sccp_ctx *sccp) {
int i;
for (i = ctx->scdf.op_array->last_var; i < ctx->scdf.ssa->vars_count; ++i) {
zval_ptr_dtor_nogc(&ctx->values[i]);
for (i = sccp->scdf.op_array->last_var; i < sccp->scdf.ssa->vars_count; ++i) {
zval_ptr_dtor_nogc(&sccp->values[i]);
}
efree(ctx->values);
}

int sccp_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_call_info **call_map)
int sccp_optimize_op_array(zend_optimizer_ctx *ctx, zend_op_array *op_array, zend_ssa *ssa, zend_call_info **call_map)
{
sccp_ctx ctx;
sccp_ctx sccp;
int removed_ops = 0;
void *checkpoint = zend_arena_checkpoint(ctx->arena);

sccp_context_init(&ctx, ssa, op_array, call_map);
sccp_context_init(ctx, &sccp, ssa, op_array, call_map);

ctx.scdf.handlers.visit_instr = sccp_visit_instr;
ctx.scdf.handlers.visit_phi = sccp_visit_phi;
ctx.scdf.handlers.mark_feasible_successors = sccp_mark_feasible_successors;
sccp.scdf.handlers.visit_instr = sccp_visit_instr;
sccp.scdf.handlers.visit_phi = sccp_visit_phi;
sccp.scdf.handlers.mark_feasible_successors = sccp_mark_feasible_successors;

scdf_init(&ctx.scdf, op_array, ssa);
scdf_solve(&ctx.scdf, "SCCP");
scdf_init(ctx, &sccp.scdf, op_array, ssa);
scdf_solve(&sccp.scdf, "SCCP");

removed_ops += scdf_remove_unreachable_blocks(&ctx.scdf);
removed_ops += replace_constant_operands(&ctx);
removed_ops += scdf_remove_unreachable_blocks(&sccp.scdf);
removed_ops += replace_constant_operands(&sccp);

sccp_context_free(&ctx);
scdf_free(&ctx.scdf);
sccp_context_free(&sccp);
zend_arena_release(&ctx->arena, checkpoint);

return removed_ops;
}
100 changes: 48 additions & 52 deletions ext/opcache/Optimizer/scdf.c
Expand Up @@ -52,140 +52,136 @@
#define DEBUG_PRINT(...)
#endif

void scdf_mark_edge_feasible(scdf_ctx *ctx, int from, int to) {
uint32_t edge = scdf_edge(&ctx->ssa->cfg, from, to);
void scdf_mark_edge_feasible(scdf_ctx *scdf, int from, int to) {
uint32_t edge = scdf_edge(&scdf->ssa->cfg, from, to);

if (zend_bitset_in(ctx->feasible_edges, edge)) {
if (zend_bitset_in(scdf->feasible_edges, edge)) {
/* We already handled this edge */
return;
}

DEBUG_PRINT("Marking edge %d->%d feasible\n", from, to);
zend_bitset_incl(ctx->feasible_edges, edge);
zend_bitset_incl(scdf->feasible_edges, edge);

if (!zend_bitset_in(ctx->executable_blocks, to)) {
if (!zend_bitset_in(ctx->block_worklist, to)) {
if (!zend_bitset_in(scdf->executable_blocks, to)) {
if (!zend_bitset_in(scdf->block_worklist, to)) {
DEBUG_PRINT("Adding block %d to worklist\n", to);
}
zend_bitset_incl(ctx->block_worklist, to);
zend_bitset_incl(scdf->block_worklist, to);
} else {
/* Block is already executable, only a new edge became feasible.
* Reevaluate phi nodes to account for changed source operands. */
zend_ssa_block *ssa_block = &ctx->ssa->blocks[to];
zend_ssa_block *ssa_block = &scdf->ssa->blocks[to];
zend_ssa_phi *phi;
for (phi = ssa_block->phis; phi; phi = phi->next) {
zend_bitset_excl(ctx->phi_var_worklist, phi->ssa_var);
ctx->handlers.visit_phi(ctx, phi);
zend_bitset_excl(scdf->phi_var_worklist, phi->ssa_var);
scdf->handlers.visit_phi(scdf, phi);
}
}
}

void scdf_init(scdf_ctx *ctx, zend_op_array *op_array, zend_ssa *ssa) {
void scdf_init(zend_optimizer_ctx *ctx, scdf_ctx *scdf, zend_op_array *op_array, zend_ssa *ssa) {
uint32_t edges_count = 0;
int b;

for (b = 0; b < ssa->cfg.blocks_count; b++) {
edges_count += ssa->cfg.blocks[b].predecessors_count;
}

ctx->op_array = op_array;
ctx->ssa = ssa;
scdf->op_array = op_array;
scdf->ssa = ssa;

ctx->instr_worklist_len = zend_bitset_len(op_array->last);
ctx->phi_var_worklist_len = zend_bitset_len(ssa->vars_count);
ctx->block_worklist_len = zend_bitset_len(ssa->cfg.blocks_count);
scdf->instr_worklist_len = zend_bitset_len(op_array->last);
scdf->phi_var_worklist_len = zend_bitset_len(ssa->vars_count);
scdf->block_worklist_len = zend_bitset_len(ssa->cfg.blocks_count);

ctx->instr_worklist = ecalloc(
ctx->instr_worklist_len + ctx->phi_var_worklist_len + 2 * ctx->block_worklist_len + zend_bitset_len(edges_count),
scdf->instr_worklist = zend_arena_calloc(&ctx->arena,
scdf->instr_worklist_len + scdf->phi_var_worklist_len + 2 * scdf->block_worklist_len + zend_bitset_len(edges_count),
sizeof(zend_ulong));

ctx->phi_var_worklist = ctx->instr_worklist + ctx->instr_worklist_len;
ctx->block_worklist = ctx->phi_var_worklist + ctx->phi_var_worklist_len;
ctx->executable_blocks = ctx->block_worklist + ctx->block_worklist_len;
ctx->feasible_edges = ctx->executable_blocks + ctx->block_worklist_len;
scdf->phi_var_worklist = scdf->instr_worklist + scdf->instr_worklist_len;
scdf->block_worklist = scdf->phi_var_worklist + scdf->phi_var_worklist_len;
scdf->executable_blocks = scdf->block_worklist + scdf->block_worklist_len;
scdf->feasible_edges = scdf->executable_blocks + scdf->block_worklist_len;

zend_bitset_incl(ctx->block_worklist, 0);
zend_bitset_incl(ctx->executable_blocks, 0);
zend_bitset_incl(scdf->block_worklist, 0);
zend_bitset_incl(scdf->executable_blocks, 0);
}

void scdf_free(scdf_ctx *ctx) {
efree(ctx->instr_worklist);
}

void scdf_solve(scdf_ctx *ctx, const char *name) {
zend_ssa *ssa = ctx->ssa;
void scdf_solve(scdf_ctx *scdf, const char *name) {
zend_ssa *ssa = scdf->ssa;
DEBUG_PRINT("Start SCDF solve (%s)\n", name);
while (!zend_bitset_empty(ctx->instr_worklist, ctx->instr_worklist_len)
|| !zend_bitset_empty(ctx->phi_var_worklist, ctx->phi_var_worklist_len)
|| !zend_bitset_empty(ctx->block_worklist, ctx->block_worklist_len)
while (!zend_bitset_empty(scdf->instr_worklist, scdf->instr_worklist_len)
|| !zend_bitset_empty(scdf->phi_var_worklist, scdf->phi_var_worklist_len)
|| !zend_bitset_empty(scdf->block_worklist, scdf->block_worklist_len)
) {
int i;
while ((i = zend_bitset_pop_first(ctx->phi_var_worklist, ctx->phi_var_worklist_len)) >= 0) {
while ((i = zend_bitset_pop_first(scdf->phi_var_worklist, scdf->phi_var_worklist_len)) >= 0) {
zend_ssa_phi *phi = ssa->vars[i].definition_phi;
ZEND_ASSERT(phi);
if (zend_bitset_in(ctx->executable_blocks, phi->block)) {
ctx->handlers.visit_phi(ctx, phi);
if (zend_bitset_in(scdf->executable_blocks, phi->block)) {
scdf->handlers.visit_phi(scdf, phi);
}
}

while ((i = zend_bitset_pop_first(ctx->instr_worklist, ctx->instr_worklist_len)) >= 0) {
while ((i = zend_bitset_pop_first(scdf->instr_worklist, scdf->instr_worklist_len)) >= 0) {
int block_num = ssa->cfg.map[i];
if (zend_bitset_in(ctx->executable_blocks, block_num)) {
if (zend_bitset_in(scdf->executable_blocks, block_num)) {
zend_basic_block *block = &ssa->cfg.blocks[block_num];
zend_op *opline = &ctx->op_array->opcodes[i];
zend_op *opline = &scdf->op_array->opcodes[i];
zend_ssa_op *ssa_op = &ssa->ops[i];
if (opline->opcode == ZEND_OP_DATA) {
opline--;
ssa_op--;
}
ctx->handlers.visit_instr(ctx, opline, ssa_op);
scdf->handlers.visit_instr(scdf, opline, ssa_op);
if (i == block->start + block->len - 1) {
if (block->successors_count == 1) {
scdf_mark_edge_feasible(ctx, block_num, block->successors[0]);
scdf_mark_edge_feasible(scdf, block_num, block->successors[0]);
} else if (block->successors_count > 1) {
ctx->handlers.mark_feasible_successors(ctx, block_num, block, opline, ssa_op);
scdf->handlers.mark_feasible_successors(scdf, block_num, block, opline, ssa_op);
}
}
}
}

while ((i = zend_bitset_pop_first(ctx->block_worklist, ctx->block_worklist_len)) >= 0) {
while ((i = zend_bitset_pop_first(scdf->block_worklist, scdf->block_worklist_len)) >= 0) {
/* This block is now live. Interpret phis and instructions in it. */
zend_basic_block *block = &ssa->cfg.blocks[i];
zend_ssa_block *ssa_block = &ssa->blocks[i];

DEBUG_PRINT("Pop block %d from worklist\n", i);
zend_bitset_incl(ctx->executable_blocks, i);
zend_bitset_incl(scdf->executable_blocks, i);

{
zend_ssa_phi *phi;
for (phi = ssa_block->phis; phi; phi = phi->next) {
zend_bitset_excl(ctx->phi_var_worklist, phi->ssa_var);
ctx->handlers.visit_phi(ctx, phi);
zend_bitset_excl(scdf->phi_var_worklist, phi->ssa_var);
scdf->handlers.visit_phi(scdf, phi);
}
}

if (block->len == 0) {
/* Zero length blocks don't have a last instruction that would normally do this */
scdf_mark_edge_feasible(ctx, i, block->successors[0]);
scdf_mark_edge_feasible(scdf, i, block->successors[0]);
} else {
zend_op *opline;
int j, end = block->start + block->len;
for (j = block->start; j < end; j++) {
opline = &ctx->op_array->opcodes[j];
zend_bitset_excl(ctx->instr_worklist, j);
opline = &scdf->op_array->opcodes[j];
zend_bitset_excl(scdf->instr_worklist, j);
if (opline->opcode != ZEND_OP_DATA) {
ctx->handlers.visit_instr(ctx, opline, &ssa->ops[j]);
scdf->handlers.visit_instr(scdf, opline, &ssa->ops[j]);
}
}
if (block->successors_count == 1) {
scdf_mark_edge_feasible(ctx, i, block->successors[0]);
scdf_mark_edge_feasible(scdf, i, block->successors[0]);
} else if (block->successors_count > 1) {
if (opline->opcode == ZEND_OP_DATA) {
opline--;
j--;
}
ctx->handlers.mark_feasible_successors(ctx, i, block, opline, &ssa->ops[j-1]);
scdf->handlers.mark_feasible_successors(scdf, i, block, opline, &ssa->ops[j-1]);
}
}
}
Expand Down
5 changes: 2 additions & 3 deletions ext/opcache/Optimizer/scdf.h
Expand Up @@ -46,9 +46,8 @@ typedef struct _scdf_ctx {
} handlers;
} scdf_ctx;

void scdf_init(scdf_ctx *scdf, zend_op_array *op_array, zend_ssa *ssa);
void scdf_init(zend_optimizer_ctx *ctx, scdf_ctx *scdf, zend_op_array *op_array, zend_ssa *ssa);
void scdf_solve(scdf_ctx *scdf, const char *name);
void scdf_free(scdf_ctx *scdf);

int scdf_remove_unreachable_blocks(scdf_ctx *scdf);

Expand Down Expand Up @@ -95,6 +94,6 @@ static inline zend_bool scdf_is_edge_feasible(scdf_ctx *scdf, int from, int to)
return zend_bitset_in(scdf->feasible_edges, edge);
}

void scdf_mark_edge_feasible(scdf_ctx *ctx, int from, int to);
void scdf_mark_edge_feasible(scdf_ctx *scdf, int from, int to);

#endif
2 changes: 1 addition & 1 deletion ext/opcache/Optimizer/zend_optimizer_internal.h
Expand Up @@ -110,6 +110,6 @@ uint32_t zend_optimizer_classify_function(zend_string *name, uint32_t num_args);
void zend_optimizer_migrate_jump(zend_op_array *op_array, zend_op *new_opline, zend_op *opline);
void zend_optimizer_shift_jump(zend_op_array *op_array, zend_op *opline, uint32_t *shiftlist);
zend_uchar zend_compound_assign_to_binary_op(zend_uchar opcode);
int sccp_optimize_op_array(zend_op_array *op_arrya, zend_ssa *ssa, zend_call_info **call_map);
int sccp_optimize_op_array(zend_optimizer_ctx *ctx, zend_op_array *op_arrya, zend_ssa *ssa, zend_call_info **call_map);

#endif

0 comments on commit 58f7c17

Please sign in to comment.