mirror of
https://github.com/php/php-src.git
synced 2025-08-15 13:38:49 +02:00
Combined constants substitutaion and dead instruction removing in single pass. This eleminates substitution in dead instructions.
This commit is contained in:
parent
f890375c16
commit
cffee2f7e5
1 changed files with 24 additions and 44 deletions
|
@ -1186,10 +1186,13 @@ static zval *value_from_type_and_range(sccp_ctx *ctx, int var_num, zval *tmp) {
|
|||
* if they have a certain type. */
|
||||
static void replace_constant_operands(sccp_ctx *ctx) {
|
||||
zend_ssa *ssa = ctx->ssa;
|
||||
zend_op_array *op_array = ctx->op_array;
|
||||
int i;
|
||||
zval tmp;
|
||||
|
||||
for (i = 0; i < ssa->vars_count; i++) {
|
||||
/* We iterate the variables backwards, so we can eliminate sequences like INIT_ROPE
|
||||
* and INIT_ARRAY. */
|
||||
for (i = ssa->vars_count - 1; i >= 0; i--) {
|
||||
zend_ssa_var *var = &ssa->vars[i];
|
||||
zval *value;
|
||||
int use;
|
||||
|
@ -1204,7 +1207,7 @@ static void replace_constant_operands(sccp_ctx *ctx) {
|
|||
}
|
||||
|
||||
FOREACH_USE(var, use) {
|
||||
zend_op *opline = &ctx->op_array->opcodes[use];
|
||||
zend_op *opline = &op_array->opcodes[use];
|
||||
zend_ssa_op *ssa_op = &ssa->ops[use];
|
||||
if (try_replace_op1(ctx, opline, ssa_op, i, value)) {
|
||||
ZEND_ASSERT(ssa_op->op1_def == -1);
|
||||
|
@ -1223,8 +1226,6 @@ static void replace_constant_operands(sccp_ctx *ctx) {
|
|||
ssa_op->op2_use_chain = -1;
|
||||
}
|
||||
} FOREACH_USE_END();
|
||||
}
|
||||
}
|
||||
|
||||
/* This is a basic DCE pass we run after SCCP. It only works on those instructions those result
|
||||
* value(s) were determined by SCCP. It removes dead computational instructions and converts
|
||||
|
@ -1237,16 +1238,8 @@ static void replace_constant_operands(sccp_ctx *ctx) {
|
|||
* not. As such doing DCE here will allow us to eliminate more dead code in combination.
|
||||
* c) The ordinary DCE pass cannot collect dead calls. However SCCP can result in dead calls, which
|
||||
* we need to collect. */
|
||||
static void eliminate_dead_instructions(sccp_ctx *ctx) {
|
||||
zend_ssa *ssa = ctx->ssa;
|
||||
zend_op_array *op_array = ctx->op_array;
|
||||
int i;
|
||||
|
||||
/* We iterate the variables backwards, so we can eliminate sequences like INIT_ROPE
|
||||
* and INIT_ARRAY. */
|
||||
for (i = ssa->vars_count - 1; i >= 0; i--) {
|
||||
zend_ssa_var *var = &ssa->vars[i];
|
||||
if (value_known(&ctx->values[i]) && var->definition >= 0) {
|
||||
if (var->definition >= 0 && value_known(&ctx->values[i])) {
|
||||
zend_op *opline = &op_array->opcodes[var->definition];
|
||||
zend_ssa_op *ssa_op = &ssa->ops[var->definition];
|
||||
if (opline->opcode == ZEND_ASSIGN) {
|
||||
|
@ -1254,11 +1247,11 @@ static void eliminate_dead_instructions(sccp_ctx *ctx) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (ssa_op->result_def >= 0
|
||||
if (ssa_op->result_def == i
|
||||
&& ssa_op->op1_def < 0
|
||||
&& ssa_op->op2_def < 0
|
||||
&& ssa->vars[ssa_op->result_def].use_chain < 0
|
||||
&& ssa->vars[ssa_op->result_def].phi_use_chain == NULL) {
|
||||
&& var->use_chain < 0
|
||||
&& var->phi_use_chain == NULL) {
|
||||
if (opline->opcode == ZEND_DO_ICALL) {
|
||||
/* Call instruction -> remove opcodes that are part of the call */
|
||||
zend_call_info *call = ctx->call_map[var->definition];
|
||||
|
@ -1278,10 +1271,8 @@ static void eliminate_dead_instructions(sccp_ctx *ctx) {
|
|||
zend_ssa_remove_result_def(ssa, ssa_op);
|
||||
zend_ssa_remove_instr(ssa, opline, ssa_op);
|
||||
}
|
||||
} else if (ssa_op->op1_def >= 0) {
|
||||
} else if (ssa_op->op1_def == i) {
|
||||
/* Compound assign or incdec -> convert to direct ASSIGN */
|
||||
zval *val = &ctx->values[ssa_op->op1_def];
|
||||
ZEND_ASSERT(value_known(val));
|
||||
|
||||
/* Destroy previous op2 */
|
||||
if (opline->op2_type == IS_CONST) {
|
||||
|
@ -1308,8 +1299,8 @@ static void eliminate_dead_instructions(sccp_ctx *ctx) {
|
|||
/* Convert to ASSIGN */
|
||||
opline->opcode = ZEND_ASSIGN;
|
||||
opline->op2_type = IS_CONST;
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
|
||||
Z_TRY_ADDREF_P(val);
|
||||
opline->op2.constant = zend_optimizer_add_literal(op_array, value);
|
||||
Z_TRY_ADDREF_P(value);
|
||||
}
|
||||
}
|
||||
/*if (var->definition_phi
|
||||
|
@ -1354,17 +1345,6 @@ static void sccp_context_free(sccp_ctx *ctx) {
|
|||
efree(ctx->values);
|
||||
}
|
||||
|
||||
static void sccp_apply_results(sccp_ctx *ctx) {
|
||||
replace_constant_operands(ctx);
|
||||
#if 0
|
||||
zend_dump_op_array(ctx->op_array, ZEND_DUMP_SSA, "SCCP-1", ctx->ssa);
|
||||
#endif
|
||||
eliminate_dead_instructions(ctx);
|
||||
#if 0
|
||||
zend_dump_op_array(ctx->op_array, ZEND_DUMP_SSA, "SCCP-2", ctx->ssa);
|
||||
#endif
|
||||
}
|
||||
|
||||
void sccp_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_call_info **call_map)
|
||||
{
|
||||
scdf_ctx scdf;
|
||||
|
@ -1380,7 +1360,7 @@ void sccp_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_call_in
|
|||
scdf_solve(&scdf, "SCCP");
|
||||
|
||||
scdf_remove_unreachable_blocks(&scdf);
|
||||
sccp_apply_results(&ctx);
|
||||
replace_constant_operands(&ctx);
|
||||
|
||||
scdf_free(&scdf);
|
||||
sccp_context_free(&ctx);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue