From bf4dab016341070d36606f4d1cf3ac068082c9e2 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 9 Jan 2019 09:26:49 +0100 Subject: [PATCH] Make operator swapping depend on IGNORE_OVERLOADING flag Add MUL back to the list and instead make the entire optimization depend on IGNORE_OVERLOADING, which is there exactly so we can make these kinds of assumptions. --- ext/opcache/Optimizer/pass3.c | 13 ++++++++----- ext/opcache/Optimizer/zend_optimizer.c | 2 +- ext/opcache/Optimizer/zend_optimizer_internal.h | 2 +- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/ext/opcache/Optimizer/pass3.c b/ext/opcache/Optimizer/pass3.c index 9f391408ec..d382d37e11 100644 --- a/ext/opcache/Optimizer/pass3.c +++ b/ext/opcache/Optimizer/pass3.c @@ -50,7 +50,7 @@ } \ jmp_hitlist[jmp_hitlist_count++] = ZEND_OP2_JMP_ADDR(target); -void zend_optimizer_pass3(zend_op_array *op_array) +void zend_optimizer_pass3(zend_op_array *op_array, zend_optimizer_ctx *ctx) { zend_op *opline; zend_op *end = op_array->opcodes + op_array->last; @@ -90,15 +90,17 @@ void zend_optimizer_pass3(zend_op_array *op_array) break; } - if ((opline->op2_type & (IS_VAR | IS_CV)) + /* change $i=expr+$i to $i=$i+expr so that the following optimization + * works on it. Only do this if we are ignoring operator overloading, + * as operand order might be significant otherwise. */ + if ((ctx->optimization_level & ZEND_OPTIMIZER_IGNORE_OVERLOADING) + && (opline->op2_type & (IS_VAR | IS_CV)) && opline->op2.var == next_opline->op1.var && (opline->opcode == ZEND_ADD || + opline->opcode == ZEND_MUL || opline->opcode == ZEND_BW_OR || opline->opcode == ZEND_BW_AND || opline->opcode == ZEND_BW_XOR)) { - /* change $i=expr+$i to $i=$i+expr so that the next - * optimization works on it - */ zend_uchar tmp_type = opline->op1_type; znode_op tmp = opline->op1; @@ -110,6 +112,7 @@ void zend_optimizer_pass3(zend_op_array *op_array) COPY_NODE(opline->op2, tmp); } } + if ((opline->op1_type & (IS_VAR | IS_CV)) && opline->op1.var == next_opline->op1.var && opline->op1_type == next_opline->op1_type) { diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index cb6cdf61d9..4bbc342952 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -1131,7 +1131,7 @@ static void zend_optimize(zend_op_array *op_array, * - change $i++ to ++$i where possible */ if (ZEND_OPTIMIZER_PASS_3 & ctx->optimization_level) { - zend_optimizer_pass3(op_array); + zend_optimizer_pass3(op_array, ctx); if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_3) { zend_dump_op_array(op_array, 0, "after pass 3", NULL); } diff --git a/ext/opcache/Optimizer/zend_optimizer_internal.h b/ext/opcache/Optimizer/zend_optimizer_internal.h index 7bb5144ff4..6c12a0d828 100644 --- a/ext/opcache/Optimizer/zend_optimizer_internal.h +++ b/ext/opcache/Optimizer/zend_optimizer_internal.h @@ -95,7 +95,7 @@ void zend_optimizer_remove_live_range(zend_op_array *op_array, uint32_t var); void zend_optimizer_remove_live_range_ex(zend_op_array *op_array, uint32_t var, uint32_t start); void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx); void zend_optimizer_pass2(zend_op_array *op_array); -void zend_optimizer_pass3(zend_op_array *op_array); +void zend_optimizer_pass3(zend_op_array *op_array, zend_optimizer_ctx *ctx); void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx); void zend_optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx); void zend_optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx); -- 2.40.0