Skip to content
Draft
6 changes: 3 additions & 3 deletions Zend/Optimizer/block_pass.c
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ static void strip_nops(const zend_op_array *op_array, zend_basic_block *b)
}

static uint32_t get_const_switch_target(const zend_cfg *cfg, const zend_op_array *op_array, const zend_basic_block *block, zend_op *opline, const zval *val) {
HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline));
const HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline));
zval *zv;
if ((opline->opcode == ZEND_SWITCH_LONG && Z_TYPE_P(val) != IS_LONG)
|| (opline->opcode == ZEND_SWITCH_STRING && Z_TYPE_P(val) != IS_STRING)) {
Expand Down Expand Up @@ -471,7 +471,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
break;
case ZEND_TYPE_CHECK:
optimize_type_check:
if (opline->extended_value == (1 << IS_TRUE) || opline->extended_value == (1 << IS_FALSE)) {
if (opline->extended_value == MAY_BE_TRUE || opline->extended_value == MAY_BE_FALSE) {
if (opline->op1_type == IS_TMP_VAR &&
!zend_bitset_in(used_ext, VAR_NUM(opline->op1.var))) {
src = VAR_SOURCE(opline->op1);
Expand All @@ -486,7 +486,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array
* T = BOOL_NOT(X) + TYPE_CHECK(T, FALSE) -> BOOL(X), NOP
*/
src->opcode =
((src->opcode == ZEND_BOOL) == (opline->extended_value == (1 << IS_TRUE))) ?
((src->opcode == ZEND_BOOL) == (opline->extended_value == MAY_BE_TRUE)) ?
ZEND_BOOL : ZEND_BOOL_NOT;
COPY_NODE(src->result, opline->result);
SET_VAR_SOURCE(src);
Expand Down
6 changes: 3 additions & 3 deletions Zend/Optimizer/compact_literals.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ static uint32_t add_static_slot(
uint32_t *cache_size
) {
uint32_t ret;
const zval *class_name = &op_array->literals[op1];
const zval *prop_name = &op_array->literals[op2];
const zend_string *class_name = Z_STR(op_array->literals[op1]);
const zend_string *prop_name = Z_STR(op_array->literals[op2]);

zend_string *key = zend_create_member_string(Z_STR_P(class_name), Z_STR_P(prop_name));
zend_string *key = zend_create_member_string(class_name, prop_name);
ZSTR_H(key) = zend_string_hash_func(key);
ZSTR_H(key) += kind;

Expand Down
36 changes: 17 additions & 19 deletions Zend/Optimizer/dfa_pass.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
# include "ssa_integrity.c"
#endif

zend_result zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, zend_ssa *ssa)
zend_result zend_dfa_analyze_op_array(const zend_op_array *op_array, zend_optimizer_ctx *ctx, zend_ssa *ssa)
{
uint32_t build_flags;

Expand Down Expand Up @@ -111,7 +111,7 @@ zend_result zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ct
static void zend_ssa_remove_nops(zend_op_array *op_array, const zend_ssa *ssa, zend_optimizer_ctx *ctx)
{
zend_basic_block *blocks = ssa->cfg.blocks;
zend_basic_block *blocks_end = blocks + ssa->cfg.blocks_count;
const zend_basic_block *blocks_end = blocks + ssa->cfg.blocks_count;
zend_basic_block *b;
zend_func_info *func_info;
int j;
Expand Down Expand Up @@ -475,9 +475,9 @@ static uint32_t zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa)
* instances of a PFA. */
uint32_t const_args = 0;
for (uint32_t i = 0, l = MIN(sizeof(const_args)*CHAR_BIT, call_info->num_args); i < l; i++) {
zend_op *send_opline = call_info->arg_info[i].opline;
const zend_op *send_opline = call_info->arg_info[i].opline;
if (send_opline->op1_type == IS_CONST) {
zval *value = CT_CONSTANT_EX(op_array, send_opline->op1.constant);
const zval *value = CT_CONSTANT_EX(op_array, send_opline->op1.constant);
if (Z_TYPE_P(value) == IS_CONSTANT_AST) {
/* Const exprs can evaluate to non-const zvals (e.g. objects), and are not idempotent */
continue;
Expand Down Expand Up @@ -536,10 +536,10 @@ static zend_always_inline void take_successor_ex(zend_ssa *ssa, uint32_t block_n
block->successors_count = 1;
}

static void compress_block(zend_op_array *op_array, zend_basic_block *block)
static void compress_block(const zend_op_array *op_array, zend_basic_block *block)
{
while (block->len > 0) {
zend_op *opline = &op_array->opcodes[block->start + block->len - 1];
const zend_op *opline = &op_array->opcodes[block->start + block->len - 1];

if (opline->opcode == ZEND_NOP) {
block->len--;
Expand All @@ -552,7 +552,6 @@ static void compress_block(zend_op_array *op_array, zend_basic_block *block)
static void replace_predecessor(zend_ssa *ssa, int block_id, int old_pred, int new_pred) {
zend_basic_block *block = &ssa->cfg.blocks[block_id];
int *predecessors = &ssa->cfg.predecessors[block->predecessor_offset];
zend_ssa_phi *phi;

int old_pred_idx = -1;
int new_pred_idx = -1;
Expand All @@ -579,7 +578,7 @@ static void replace_predecessor(zend_ssa *ssa, int block_id, int old_pred, int n
);

/* Also remove the corresponding phi node entries */
for (phi = ssa->blocks[block_id].phis; phi; phi = phi->next) {
for (zend_ssa_phi *phi = ssa->blocks[block_id].phis; phi; phi = phi->next) {
if (phi->pi >= 0) {
if (phi->pi == old_pred || phi->pi == new_pred) {
zend_ssa_rename_var_uses(
Expand All @@ -604,7 +603,6 @@ static void zend_ssa_replace_control_link(const zend_op_array *op_array, zend_ss
const zend_basic_block *src = &ssa->cfg.blocks[from];
const zend_basic_block *old = &ssa->cfg.blocks[to];
const zend_basic_block *dst = &ssa->cfg.blocks[new_to];
zend_op *opline;

for (uint32_t i = 0; i < src->successors_count; i++) {
if (src->successors[i] == to) {
Expand All @@ -613,7 +611,7 @@ static void zend_ssa_replace_control_link(const zend_op_array *op_array, zend_ss
}

if (src->len > 0) {
opline = op_array->opcodes + src->start + src->len - 1;
zend_op *opline = op_array->opcodes + src->start + src->len - 1;
switch (opline->opcode) {
case ZEND_JMP:
case ZEND_FAST_CALL:
Expand Down Expand Up @@ -653,7 +651,7 @@ static void zend_ssa_replace_control_link(const zend_op_array *op_array, zend_ss
case ZEND_SWITCH_STRING:
case ZEND_MATCH:
{
HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline));
const HashTable *jumptable = Z_ARRVAL(ZEND_OP2_LITERAL(opline));
zval *zv;
ZEND_HASH_FOREACH_VAL(jumptable, zv) {
if (ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, Z_LVAL_P(zv)) == old->start) {
Expand All @@ -675,12 +673,12 @@ static void zend_ssa_unlink_block(const zend_op_array *op_array, zend_ssa *ssa,
{
if (block->predecessors_count == 1 && ssa->blocks[block_num].phis == NULL) {
int *predecessors;
zend_basic_block *fe_fetch_block = NULL;
const zend_basic_block *fe_fetch_block = NULL;

ZEND_ASSERT(block->successors_count == 1);
predecessors = &ssa->cfg.predecessors[block->predecessor_offset];
if (block->predecessors_count == 1 && (block->flags & ZEND_BB_FOLLOW)) {
zend_basic_block *pred_block = &ssa->cfg.blocks[predecessors[0]];
const zend_basic_block *pred_block = &ssa->cfg.blocks[predecessors[0]];

if (pred_block->len > 0 && (pred_block->flags & ZEND_BB_REACHABLE)) {
if ((op_array->opcodes[pred_block->start + pred_block->len - 1].opcode == ZEND_FE_FETCH_R
Expand All @@ -704,7 +702,7 @@ static void zend_ssa_unlink_block(const zend_op_array *op_array, zend_ssa *ssa,
}
}

static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
static int zend_dfa_optimize_jmps(const zend_op_array *op_array, zend_ssa *ssa)
{
int removed_ops = 0;
uint32_t block_num = 0;
Expand Down Expand Up @@ -911,7 +909,7 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
case ZEND_SWITCH_STRING:
case ZEND_MATCH:
if (opline->op1_type == IS_CONST) {
zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
const zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
uint8_t type = Z_TYPE_P(zv);
bool correct_type =
(opline->opcode == ZEND_SWITCH_LONG && type == IS_LONG)
Expand Down Expand Up @@ -1136,7 +1134,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx

// op_1: ASSIGN ? -> #v [use_as_double], long(?) => ASSIGN ? -> #v, double(?)

zval *zv = CT_CONSTANT_EX(op_array, opline->op2.constant);
const zval *zv = CT_CONSTANT_EX(op_array, opline->op2.constant);
ZEND_ASSERT(Z_TYPE_INFO_P(zv) == IS_LONG);
ZVAL_DOUBLE(&tmp, zval_get_double(zv));
opline->op2.constant = zend_optimizer_add_literal(op_array, &tmp);
Expand All @@ -1147,7 +1145,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx

// op_1: QM_ASSIGN #v [use_as_double], long(?) => QM_ASSIGN #v, double(?)

zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
const zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
ZEND_ASSERT(Z_TYPE_INFO_P(zv) == IS_LONG);
ZVAL_DOUBLE(&tmp, zval_get_double(zv));
opline->op1.constant = zend_optimizer_add_literal(op_array, &tmp);
Expand All @@ -1164,7 +1162,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
) {

if (opline->op1_type == IS_CONST && opline->op2_type != IS_CONST) {
zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
const zval *zv = CT_CONSTANT_EX(op_array, opline->op1.constant);

if ((OP2_INFO() & MAY_BE_ANY) == MAY_BE_DOUBLE
&& Z_TYPE_INFO_P(zv) == IS_LONG) {
Expand Down Expand Up @@ -1217,7 +1215,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx
}
}
} else if (opline->op1_type != IS_CONST && opline->op2_type == IS_CONST) {
zval *zv = CT_CONSTANT_EX(op_array, opline->op2.constant);
const zval *zv = CT_CONSTANT_EX(op_array, opline->op2.constant);

if ((OP1_INFO() & MAY_BE_ANY) == MAY_BE_DOUBLE
&& Z_TYPE_INFO_P(CT_CONSTANT_EX(op_array, opline->op2.constant)) == IS_LONG) {
Expand Down
20 changes: 8 additions & 12 deletions Zend/Optimizer/sccp.c
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ static inline zend_result fetch_array_elem(zval **result, const zval *op1, const
}
}

static inline zend_result ct_eval_fetch_dim(zval *result, const zval *op1, const zval *op2, int support_strings) {
static inline zend_result ct_eval_fetch_dim(zval *result, const zval *op1, const zval *op2, bool support_strings) {
if (Z_TYPE_P(op1) == IS_ARRAY || IS_PARTIAL_ARRAY(op1)) {
zval *value;
if (fetch_array_elem(&value, op1, op2) == SUCCESS && value && !IS_BOT(value)) {
Expand Down Expand Up @@ -587,20 +587,19 @@ static inline zend_result ct_eval_assign_dim(zval *result, zval *value, const zv
}
}

static inline zend_result fetch_obj_prop(zval **result, const zval *op1, const zval *op2) {
static inline zval* fetch_obj_prop(const zval *op1, const zval *op2) {
switch (Z_TYPE_P(op2)) {
case IS_STRING:
*result = zend_symtable_find(Z_ARR_P(op1), Z_STR_P(op2));
return SUCCESS;
return zend_symtable_find(Z_ARR_P(op1), Z_STR_P(op2));
default:
return FAILURE;
return NULL;
}
}

static inline zend_result ct_eval_fetch_obj(zval *result, const zval *op1, const zval *op2) {
if (IS_PARTIAL_OBJECT(op1)) {
zval *value;
if (fetch_obj_prop(&value, op1, op2) == SUCCESS && value && !IS_BOT(value)) {
const zval *value = fetch_obj_prop(op1, op2);
if (value && !IS_BOT(value)) {
ZVAL_COPY(result, value);
return SUCCESS;
}
Expand All @@ -610,10 +609,7 @@ static inline zend_result ct_eval_fetch_obj(zval *result, const zval *op1, const

static inline zend_result ct_eval_isset_obj(zval *result, uint32_t extended_value, const zval *op1, const zval *op2) {
if (IS_PARTIAL_OBJECT(op1)) {
zval *value;
if (fetch_obj_prop(&value, op1, op2) == FAILURE) {
return FAILURE;
}
zval *value = fetch_obj_prop(op1, op2);
if (!value || IS_BOT(value)) {
return FAILURE;
}
Expand Down Expand Up @@ -1301,7 +1297,7 @@ static void sccp_visit_instr(scdf_ctx *scdf, zend_op *opline, zend_ssa_op *ssa_o

SKIP_IF_TOP(data);

if (ct_eval_fetch_dim(&tmp, op1, op2, 0) == SUCCESS) {
if (ct_eval_fetch_dim(&tmp, op1, op2, false) == SUCCESS) {
if (IS_BOT(data)) {
dup_partial_array(&zv, op1);
ct_eval_del_array_elem(&zv, op2);
Expand Down
26 changes: 12 additions & 14 deletions Zend/Optimizer/zend_cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include "zend_optimizer_internal.h"
#include "zend_sort.h"

static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_block *b) /* {{{ */
static void zend_mark_reachable(const zend_op *opcodes, const zend_cfg *cfg, zend_basic_block *b) /* {{{ */
{
zend_basic_block *blocks = cfg->blocks;

Expand Down Expand Up @@ -101,17 +101,16 @@ static void zend_mark_reachable(zend_op *opcodes, zend_cfg *cfg, zend_basic_bloc
}
/* }}} */

static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg *cfg, uint32_t start) /* {{{ */
static void zend_mark_reachable_blocks(const zend_op_array *op_array, const zend_cfg *cfg, uint32_t start) /* {{{ */
{
zend_basic_block *blocks = cfg->blocks;

blocks[start].flags = ZEND_BB_START;
zend_mark_reachable(op_array->opcodes, cfg, blocks + start);

if (op_array->last_try_catch) {
zend_basic_block *b;
int changed;
uint32_t *block_map = cfg->map;
const uint32_t *block_map = cfg->map;

do {
changed = 0;
Expand All @@ -120,7 +119,7 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg *
for (uint32_t j = 0; j < op_array->last_try_catch; j++) {

/* check for jumps into the middle of try block */
b = blocks + block_map[op_array->try_catch_array[j].try_op];
zend_basic_block *b = blocks + block_map[op_array->try_catch_array[j].try_op];
if (!(b->flags & ZEND_BB_REACHABLE)) {
zend_basic_block *end;

Expand Down Expand Up @@ -198,19 +197,18 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg *
}

if (cfg->flags & ZEND_FUNC_FREE_LOOP_VAR) {
zend_basic_block *b;
uint32_t *block_map = cfg->map;
const uint32_t *block_map = cfg->map;

/* Mark blocks that are unreachable, but free a loop var created in a reachable block. */
for (b = blocks; b < blocks + cfg->blocks_count; b++) {
for (zend_basic_block *b = blocks; b < blocks + cfg->blocks_count; b++) {
if (b->flags & ZEND_BB_REACHABLE) {
continue;
}

for (uint32_t j = b->start; j < b->start + b->len; j++) {
zend_op *opline = &op_array->opcodes[j];
if (zend_optimizer_is_loop_var_free(opline)) {
zend_op *def_opline = zend_optimizer_get_loop_var_def(op_array, opline);
const zend_op *def_opline = zend_optimizer_get_loop_var_def(op_array, opline);
if (def_opline) {
uint32_t def_block = block_map[def_opline - op_array->opcodes];
if (blocks[def_block].flags & ZEND_BB_REACHABLE) {
Expand All @@ -225,7 +223,7 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg *
}
/* }}} */

void zend_cfg_remark_reachable_blocks(const zend_op_array *op_array, zend_cfg *cfg) /* {{{ */
void zend_cfg_remark_reachable_blocks(const zend_op_array *op_array, const zend_cfg *cfg) /* {{{ */
{
zend_basic_block *blocks = cfg->blocks;
uint32_t i;
Expand Down Expand Up @@ -557,7 +555,7 @@ ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array,
case ZEND_SWITCH_STRING:
case ZEND_MATCH:
{
HashTable *jumptable = Z_ARRVAL_P(CRT_CONSTANT(opline->op2));
const HashTable *jumptable = Z_ARRVAL_P(CRT_CONSTANT(opline->op2));
zval *zv;
uint32_t s = 0;

Expand Down Expand Up @@ -591,7 +589,7 @@ ZEND_API void zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg) /*
{
zend_basic_block *b;
zend_basic_block *blocks = cfg->blocks;
zend_basic_block *end = blocks + cfg->blocks_count;
const zend_basic_block *end = blocks + cfg->blocks_count;
uint32_t edges = 0;
int *predecessors;

Expand Down Expand Up @@ -650,7 +648,7 @@ ZEND_API void zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg) /*
static void compute_postnum_recursive(
int *postnum, uint32_t *cur, const zend_cfg *cfg, int block_num) /* {{{ */
{
zend_basic_block *block = &cfg->blocks[block_num];
const zend_basic_block *block = &cfg->blocks[block_num];
if (postnum[block_num] != -1) {
return;
}
Expand Down Expand Up @@ -759,7 +757,7 @@ ZEND_API void zend_cfg_compute_dominators_tree(const zend_op_array *op_array, ze
}
/* }}} */

static bool dominates(zend_basic_block *blocks, int a, int b) /* {{{ */
static bool dominates(const zend_basic_block *blocks, int a, int b) /* {{{ */
{
while (blocks[b].level > blocks[a].level) {
b = blocks[b].idom;
Expand Down
2 changes: 1 addition & 1 deletion Zend/Optimizer/zend_cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ typedef struct _zend_cfg {
BEGIN_EXTERN_C()

ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_cfg *cfg);
void zend_cfg_remark_reachable_blocks(const zend_op_array *op_array, zend_cfg *cfg);
void zend_cfg_remark_reachable_blocks(const zend_op_array *op_array, const zend_cfg *cfg);
ZEND_API void zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg);
ZEND_API void zend_cfg_compute_dominators_tree(const zend_op_array *op_array, zend_cfg *cfg);
ZEND_API void zend_cfg_identify_loops(const zend_op_array *op_array, zend_cfg *cfg);
Expand Down
7 changes: 3 additions & 4 deletions Zend/Optimizer/zend_inference.c
Original file line number Diff line number Diff line change
Expand Up @@ -1829,7 +1829,7 @@ static void zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* {
int *scc_var;
zend_ssa_phi *p;
zend_ssa_range tmp;
int scc, j;
int j;
ALLOCA_FLAG(use_heap);

worklist = do_alloca(
Expand All @@ -1850,7 +1850,7 @@ static void zend_infer_ranges(const zend_op_array *op_array, zend_ssa *ssa) /* {
}
}

for (scc = 0; scc < ssa->sccs; scc++) {
for (int scc = 0; scc < ssa->sccs; scc++) {
j = scc_var[scc];
if (next_scc_var[j] < 0) {
/* SCC with a single element */
Expand Down Expand Up @@ -2037,10 +2037,9 @@ static void add_usages(const zend_op_array *op_array, const zend_ssa *ssa, zend_
}
if (ssa->vars[var].use_chain >= 0) {
int use = ssa->vars[var].use_chain;
const zend_ssa_op *op;

do {
op = ssa->ops + use;
const zend_ssa_op *op = ssa->ops + use;
if (op->result_def >= 0) {
zend_bitset_incl(worklist, op->result_def);
}
Expand Down
Loading
Loading