34# define ZEND_DEBUG_DFA ZEND_DEBUG
125 shiftlist = (uint32_t *)
do_alloca(
sizeof(uint32_t) * op_array->
last, use_heap);
126 memset(shiftlist, 0,
sizeof(uint32_t) * op_array->
last);
132 if ((*call_info)->caller_init_opline->opcode ==
ZEND_NOP) {
140 for (b = blocks; b < blocks_end; b++) {
143 uint32_t new_start, old_end;
144 while (i < b->
start) {
145 shiftlist[i] = i - target;
158 while (i < old_end) {
159 shiftlist[i] = i - target;
163 ssa->
ops[target] = ssa->
ops[i];
164 ssa->
cfg.
map[target] = b - blocks;
170 b->
start = new_start;
171 if (target != old_end) {
176 opline = op_array->
opcodes + old_end - 1;
181 new_opline = op_array->
opcodes + target - 1;
193 if (target != op_array->
last) {
195 for (i = target; i < op_array->
last; i++) {
208 for (i = 0; i < op_array->
last; i++) {
221 for (b = blocks; b < blocks_end; b++) {
252 op_array->
last = target;
265 return instanceof_function(ce1, ce2);
268static inline bool can_elide_list_type(
279 return can_elide_list_type(script, op_array, use_info, *single_type);
284 zend_string_release(
lcname);
285 bool result = ce && safe_instanceof(use_info->
ce, ce);
286 if (
result == !is_intersection) {
291 return is_intersection;
294static inline bool can_elide_return_type_check(
309 if (!disallowed_types) {
315 return can_elide_list_type(script, op_array, use_info, arg_info->
type);
321static bool opline_supports_assign_contraction(
331 if ((opline + 1)->op1_type ==
IS_CV && (opline + 1)->
op1.var == cv_var)
return 0;
375 && opline->
op1.
var == cv_var
383static bool variable_defined_or_used_in_range(
zend_ssa *ssa,
int var,
int start,
int end)
406 if (func_info->callee_info) {
484 if (block->successors_count == 2) {
485 if (block->successors[1] != block->successors[0]) {
488 block->successors_count = 1;
494 if (block->successors_count == 2) {
495 if (block->successors[1] != block->successors[0]) {
497 block->successors[0] = block->successors[1];
499 block->successors_count = 1;
507 for (i = 0; i < block->successors_count; i++) {
508 if (block->successors[i] != target_block) {
512 block->successors[0] = target_block;
513 block->successors_count = 1;
518 while (block->len > 0) {
519 zend_op *opline = &op_array->
opcodes[block->start + block->len - 1];
529static void replace_predecessor(
zend_ssa *ssa,
int block_id,
int old_pred,
int new_pred) {
535 int old_pred_idx = -1;
536 int new_pred_idx = -1;
537 for (i = 0; i < block->predecessors_count; i++) {
538 if (predecessors[i] == old_pred) {
541 if (predecessors[i] == new_pred) {
547 if (new_pred_idx == -1) {
549 predecessors[old_pred_idx] = new_pred;
554 predecessors + old_pred_idx,
555 predecessors + old_pred_idx + 1,
556 sizeof(
int) * (block->predecessors_count - old_pred_idx - 1)
562 if (phi->
pi == old_pred || phi->
pi == new_pred) {
570 phi->
sources + old_pred_idx + 1,
571 sizeof(
int) * (block->predecessors_count - old_pred_idx - 1)
576 block->predecessors_count--;
580static void zend_ssa_replace_control_link(
zend_op_array *op_array,
zend_ssa *ssa,
int from,
int to,
int new_to)
650 replace_predecessor(ssa, new_to, to, from);
655 if (block->predecessors_count == 1 && ssa->
blocks[block_num].
phis ==
NULL) {
656 int *predecessors, i;
661 if (block->predecessors_count == 1 && (block->flags &
ZEND_BB_FOLLOW)) {
668 fe_fetch_block = pred_block;
672 for (i = 0; i < block->predecessors_count; i++) {
673 zend_ssa_replace_control_link(op_array, ssa, predecessors[i], block_num, block->successors[0]);
697 compress_block(op_array, block);
698 if (block->len == 0) {
699 zend_ssa_unlink_block(op_array, ssa, block, block_num);
704 while (block_num < ssa->cfg.blocks_count
708 while (block_num < ssa->cfg.blocks_count) {
709 int next_block_num = block_num + 1;
716 while (next_block_num < ssa->cfg.blocks_count
725 op_num = block->start + block->len - 1;
726 opline = op_array->
opcodes + op_num;
727 ssa_op = ssa->
ops + op_num;
732 if (block->successors[0] == next_block_num && can_follow) {
744 take_successor_1(ssa, block_num, block);
749 take_successor_0(ssa, block_num, block);
753 if (block->successors[0] == next_block_num && can_follow) {
754 take_successor_0(ssa, block_num, block);
775 take_successor_0(ssa, block_num, block);
780 take_successor_1(ssa, block_num, block);
783 }
else if (block->successors_count == 2) {
784 if (block->successors[0] == next_block_num && can_follow) {
785 take_successor_0(ssa, block_num, block);
805 zend_ssa_remove_result_def(ssa, ssa_op);
810 take_successor_1(ssa, block_num, block);
819 zend_ssa_remove_result_def(ssa, ssa_op);
824 take_successor_1(ssa, block_num, block);
833 zend_ssa_remove_result_def(ssa, ssa_op);
839 take_successor_1(ssa, block_num, block);
840 zend_ssa_remove_result_def(ssa, ssa_op);
851 zend_ssa_remove_result_def(ssa, ssa_op);
854 take_successor_1(ssa, block_num, block);
859 zend_ssa_remove_result_def(ssa, ssa_op);
861 take_successor_0(ssa, block_num, block);
875 zend_ssa_remove_result_def(ssa, ssa_op);
877 take_successor_0(ssa, block_num, block);
880 zend_ssa_remove_result_def(ssa, ssa_op);
883 take_successor_1(ssa, block_num, block);
908 take_successor_ex(ssa, block_num, block, block->successors[block->successors_count - 1]);
933 take_successor_ex(ssa, block_num, block, ssa->
cfg.
map[target]);
939 compress_block(op_array, block);
940 if (block->len == 0) {
942 zend_ssa_unlink_block(op_array, ssa, block, block_num);
946 }
while (block_num >= 0
948 if (block_num >= 0) {
959 block_num = next_block_num;
965static bool zend_dfa_try_to_replace_result(
zend_op_array *op_array,
zend_ssa *ssa,
int def,
int cv_var)
978 && zend_ssa_next_use(ssa->
ops, result_var, use) < 0
1013 }
else if (ssa->
ops[use].
op2_use == result_var) {
1046 int remove_nops = 0;
1060 if (zend_dfa_optimize_jmps(op_array, ssa)) {
1084 if (zend_dfa_optimize_jmps(op_array, ssa)) {
1103 opline = op_array->
opcodes + op_1;
1104 ssa_op = &ssa->
ops[op_1];
1255 && can_elide_return_type_check(ctx->
script, op_array, ssa, &ssa->
ops[op_1])) {
1278 && can_elide_return_type_check(ctx->
script, op_array, ssa, &ssa->
ops[op_1])) {
1317 && opline_supports_assign_contraction(
1330 if (orig_var >= 0) {
1423 zend_dfa_try_to_replace_result(op_array, ssa, op_1,
v);
1433 && zend_dfa_try_to_replace_result(op_array, ssa, op_1,
v)) {
1447 && zend_dfa_try_to_replace_result(op_array, ssa, op_1,
v)) {
1477 && opline_supports_assign_contraction(
1479 src_var, opline->
op1.
var)
1653 zend_ssa_remove_nops(op_array, ssa, ctx);
1667 void *checkpoint = zend_arena_checkpoint(ctx->
arena);
1671 zend_arena_release(&ctx->
arena, checkpoint);
1678 zend_arena_release(&ctx->
arena, checkpoint);
if(function_exists("date_default_timezone_set")) simple()
int dce_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *optimizer_ctx, zend_ssa *ssa, bool reorder_dtor_effects)
void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, zend_ssa *ssa, zend_call_info **call_map)
int zend_dfa_optimize_calls(zend_op_array *op_array, zend_ssa *ssa)
zend_result zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, zend_ssa *ssa)
void zend_optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx)
zend_result zend_ssa_escape_analysis(const zend_script *script, zend_op_array *op_array, zend_ssa *ssa)
memset(ptr, 0, type->size)
unsigned const char * end
int sccp_optimize_op_array(zend_optimizer_ctx *ctx, zend_op_array *op_array, zend_ssa *ssa, zend_call_info **call_map)
void ssa_verify_integrity(zend_op_array *op_array, zend_ssa *ssa, const char *extra)
zend_basic_block * blocks
zend_try_catch_element * try_catch_array
zend_long optimization_level
zend_ssa_phi * sym_use_chain
zend_ssa_phi * phi_use_chain
zend_ssa_var_info * var_info
ZEND_API void zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, 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)
struct _zend_basic_block zend_basic_block
#define ZEND_SSA_DEBUG_LIVENESS
#define ZEND_BB_REACHABLE
#define ZEND_BB_UNREACHABLE_FREE
#define ZEND_CFG_NO_ENTRY_PREDECESSORS
#define RETURN_VALUE_USED(opline)
#define ZEND_SSA_DEBUG_PHI_PLACEMENT
#define ZEND_SET_OP_JMP_ADDR(opline, node, val)
#define ZEND_OFFSET_TO_OPLINE_NUM(op_array, base, offset)
struct _zend_op_array zend_op_array
struct _zend_arg_info zend_arg_info
#define CT_CONSTANT_EX(op_array, num)
#define ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline_num)
void zend_dump_ssa_variables(const zend_op_array *op_array, const zend_ssa *ssa, uint32_t dump_flags)
ZEND_API void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, const char *msg, const void *data)
void zend_dump_dominators(const zend_op_array *op_array, const zend_cfg *cfg)
struct _zend_call_info zend_call_info
#define ZEND_FUNC_INDIRECT_VAR_ACCESS
#define ZEND_FUNC_INFO(op_array)
struct _zend_func_info zend_func_info
ZEND_API zval *ZEND_FASTCALL zend_hash_index_add(HashTable *ht, zend_ulong h, zval *pData)
ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
ZEND_API zval *ZEND_FASTCALL zend_hash_find(const HashTable *ht, zend_string *key)
ZEND_API zval *ZEND_FASTCALL zend_hash_add(HashTable *ht, zend_string *key, zval *pData)
ZEND_API zval *ZEND_FASTCALL zend_hash_index_find(const HashTable *ht, zend_ulong h)
#define zend_new_array(size)
#define ZEND_HANDLE_NUMERIC(key, idx)
#define ZEND_HASH_FOREACH_END()
#define ZEND_HASH_FOREACH_VAL(ht, _val)
ZEND_API bool zend_may_throw(const zend_op *opline, const zend_ssa_op *ssa_op, const zend_op_array *op_array, const zend_ssa *ssa)
ZEND_API void zend_ssa_find_false_dependencies(const zend_op_array *op_array, zend_ssa *ssa)
ZEND_API void zend_ssa_find_sccs(const zend_op_array *op_array, zend_ssa *ssa)
ZEND_API zend_result zend_ssa_inference(zend_arena **arena, const zend_op_array *op_array, const zend_script *script, zend_ssa *ssa, zend_long optimization_level)
struct _zend_string zend_string
ZEND_API bool ZEND_FASTCALL zend_is_true(const zval *op)
zend_class_entry * zend_optimizer_get_class_entry(const zend_script *script, const zend_op_array *op_array, zend_string *lcname)
int zend_optimizer_add_literal(zend_op_array *op_array, const zval *zv)
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)
#define ZEND_DUMP_DFA_PHI
#define ZEND_OPTIMIZER_PASS_14
struct _zend_script zend_script
#define ZEND_DUMP_DFA_LIVENESS
#define ZEND_DUMP_AFTER_DFA_PASS
#define ZEND_DUMP_DFA_DOMINATORS
#define ZEND_DUMP_DFA_SSA_VARS
#define ZEND_DUMP_DFA_CFG
#define ZEND_OPTIMIZER_PASS_8
#define ZEND_DUMP_AFTER_PASS_14
#define ZEND_DUMP_BEFORE_DFA_PASS
#define ZEND_DUMP_AFTER_PASS_8
#define ZEND_DUMP_DFA_SSA
#define ZEND_OP1_JMP_ADDR(opline)
#define ZEND_OP2_LITERAL(opline)
#define ZEND_OP2_JMP_ADDR(opline)
struct _zend_optimizer_ctx zend_optimizer_ctx
#define COPY_NODE(target, src)
#define ALLOCA_FLAG(name)
#define EXPECTED(condition)
#define do_alloca(p, use_heap)
#define zend_always_inline
#define free_alloca(p, use_heap)
struct _zend_class_entry zend_class_entry
void zend_ssa_remove_uses_of_var(zend_ssa *ssa, int var_num)
void zend_ssa_remove_instr(zend_ssa *ssa, zend_op *opline, zend_ssa_op *ssa_op)
void zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var)
void zend_ssa_replace_use_chain(zend_ssa *ssa, int op, int new_op, int var)
void zend_ssa_remove_phi(zend_ssa *ssa, zend_ssa_phi *phi)
void zend_ssa_rename_var_uses(zend_ssa *ssa, int old, int new, bool update_types)
void zend_ssa_remove_predecessor(zend_ssa *ssa, int from, int to)
ZEND_API zend_result zend_build_ssa(zend_arena **arena, const zend_script *script, const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa)
ZEND_API void zend_ssa_compute_use_def_chains(zend_arena **arena, const zend_op_array *op_array, zend_ssa *ssa)
void zend_ssa_remove_block(zend_op_array *op_array, zend_ssa *ssa, int i)
struct _zend_ssa zend_ssa
struct _zend_ssa_var zend_ssa_var
struct _zend_ssa_phi zend_ssa_phi
struct _zend_ssa_op zend_ssa_op
struct _zend_ssa_var_info zend_ssa_var_info
#define zend_string_equals_literal_ci(str, c)
#define ZEND_TYPE_PURE_MASK(t)
#define ZEND_TYPE_NAME(t)
#define Z_ARRVAL_P(zval_p)
#define ZEND_TYPE_IS_INTERSECTION(t)
struct _zend_array HashTable
#define ZEND_TYPE_HAS_NAME(t)
#define Z_TYPE_INFO_P(zval_p)
#define ZEND_TYPE_FOREACH(type, type_ptr)
#define ZEND_TYPE_HAS_LIST(t)
#define ZEND_TYPE_FOREACH_END()
#define ZVAL_DOUBLE(z, d)
ZEND_RESULT_CODE zend_result
#define ZEND_TYPE_IS_COMPLEX(t)
#define ZEND_ASSIGN_DIM_OP
#define ZEND_VERIFY_RETURN_TYPE
#define ZEND_ASSERT_CHECK
#define ZEND_SWITCH_STRING
#define ZEND_FRAMELESS_ICALL_1
#define ZEND_IS_NOT_EQUAL
#define ZEND_FRAMELESS_ICALL_3
#define ZEND_IS_SMALLER_OR_EQUAL
#define ZEND_FRAMELESS_ICALL_2
#define ZEND_BIND_INIT_STATIC_OR_JMP
#define ZEND_JMP_FRAMELESS
#define ZEND_ASSIGN_OBJ_OP
#define ZEND_DO_FCALL_BY_NAME