35 zend_worklist_push(&work, b - cfg->
blocks);
37 while (zend_worklist_len(&work)) {
39 b = cfg->
blocks + zend_worklist_pop(&work);
98 zend_worklist_push(&work, succ - cfg->
blocks);
112 zend_mark_reachable(op_array->
opcodes, cfg, blocks +
start);
117 uint32_t *block_map = cfg->
map;
169 zend_mark_reachable(op_array->
opcodes, cfg, b);
177 zend_mark_reachable(op_array->
opcodes, cfg, b);
185 zend_mark_reachable(op_array->
opcodes, cfg, b);
206 uint32_t *block_map = cfg->
map;
216 if (zend_optimizer_is_loop_var_free(opline)) {
219 uint32_t def_block = block_map[def_opline - op_array->
opcodes];
251 zend_mark_reachable_blocks(op_array, cfg,
start);
257 block->successors = block->successors_storage;
258 block->successors_count = 0;
259 block->predecessors_count = 0;
260 block->predecessor_offset = -1;
262 block->loop_header = -1;
264 block->children = -1;
265 block->next_child = -1;
268#define BB_START(i) do { \
269 if (!block_map[i]) { blocks_count++;} \
280 int blocks_count = 0;
283 bool extra_entry_block = 0;
287 cfg->
map = block_map = zend_arena_calloc(
arena, op_array->
last,
sizeof(uint32_t));
291 for (i = 0; i < op_array->
last; i++) {
304 if (i + 1 < op_array->
last) {
344 if ((fn = zend_hash_find_ptr(
EG(function_table),
Z_STR_P(
zv))) !=
NULL) {
356 if (i + 1 < op_array->
last) {
362 if (i + 1 < op_array->
last) {
435 if (zend_optimizer_is_loop_var_free(opline)
447 && op_array->
last > 0 && block_map[0] > 1) {
448 extra_entry_block = 1;
466 blocks_count += extra_entry_block;
474 if (extra_entry_block) {
475 initialize_block(&blocks[0]);
481 for (i = 0; i < op_array->
last; i++) {
483 if (blocks_count >= 0) {
484 blocks[blocks_count].
len = i - blocks[blocks_count].
start;
487 initialize_block(&blocks[blocks_count]);
488 blocks[blocks_count].
start = i;
490 block_map[i] = blocks_count;
493 blocks[blocks_count].
len = i - blocks[blocks_count].
start;
497 for (
j = 0;
j < blocks_count;
j++) {
500 if (block->len == 0) {
501 block->successors_count = 1;
502 block->successors[0] =
j + 1;
506 opline = op_array->
opcodes + block->start + block->len - 1;
517 block->successors_count = 1;
530 block->successors_count = 2;
532 block->successors[1] =
j + 1;
536 block->successors_count = 2;
538 block->successors[1] =
j + 1;
540 block->successors_count = 1;
541 block->successors[0] =
j + 1;
546 block->successors_count = 2;
548 block->successors[1] =
j + 1;
552 block->successors_count = 2;
554 block->successors[1] =
j + 1;
557 block->successors_count = 2;
559 block->successors[1] =
j + 1;
569 block->successors_count = (opline->
opcode ==
ZEND_MATCH ? 1 : 2) + zend_hash_num_elements(jumptable);
570 block->successors = zend_arena_calloc(
arena, block->successors_count,
sizeof(
int));
578 block->successors[
s++] =
j + 1;
583 block->successors_count = 1;
584 block->successors[0] =
j + 1;
591 zend_mark_reachable_blocks(op_array, cfg, 0);
604 for (b = blocks; b <
end; b++) {
607 for (b = blocks; b <
end; b++) {
620 cfg->
predecessors = predecessors = (
int*)zend_arena_calloc(
arena,
sizeof(
int), edges);
623 for (b = blocks; b <
end; b++) {
638 for (
p = 0;
p <
s;
p++) {
639 if (blocks[
j].successors[
p] == blocks[
j].successors[
s]) {
657static void compute_postnum_recursive(
658 int *postnum,
int *cur,
const zend_cfg *cfg,
int block_num)
662 if (postnum[block_num] != -1) {
666 postnum[block_num] = -2;
667 for (
s = 0;
s < block->successors_count;
s++) {
668 compute_postnum_recursive(postnum, cur, cfg, block->successors[
s]);
670 postnum[block_num] = (*cur)++;
691 compute_postnum_recursive(postnum, &
j, cfg, 0);
698 for (
j = 1;
j < blocks_count;
j++) {
707 if (blocks[pred].idom >= 0) {
711 while (idom != pred) {
712 while (postnum[pred] < postnum[idom]) pred = blocks[pred].
idom;
713 while (postnum[idom] < postnum[pred]) idom = blocks[idom].
idom;
719 if (idom >= 0 && blocks[
j].idom != idom) {
720 blocks[
j].
idom = idom;
727 for (
j = 1;
j < blocks_count;
j++) {
731 if (blocks[
j].idom >= 0) {
733 if (blocks[blocks[
j].idom].children < 0 ||
734 j < blocks[blocks[
j].idom].children) {
739 while (blocks[k].next_child >=0 &&
j > blocks[k].next_child) {
748 for (
j = 0;
j < blocks_count;
j++) {
749 int idom = blocks[
j].
idom, level = 0;
755 if (blocks[idom].level >= 0) {
756 level += blocks[idom].
level;
759 idom = blocks[idom].
idom;
771 while (blocks[b].level > blocks[
a].level) {
783 int *entry_times, *exit_times;
804 zend_worklist_push(&work, 0);
806 while (zend_worklist_len(&work)) {
808 i = zend_worklist_peek(&work);
809 if (entry_times[i] == -1) {
810 entry_times[i] =
time++;
814 if (zend_worklist_push(&work,
j)) {
821 if (blocks[succ].idom == i) {
823 }
else if (zend_worklist_push(&work, succ)) {
827 exit_times[i] =
time++;
828 zend_worklist_pop(&work);
832 sorted_blocks[0] = 0;
840 for (child = blocks[sorted_blocks[i]].children; child >= 0; child = blocks[child].
next_child) {
841 sorted_blocks[
n++] = child;
848 i = sorted_blocks[--
n];
850 if (blocks[i].predecessors_count < 2) {
860 if (blocks[i].idom == pred) {
866 if (dominates(blocks, i, pred)) {
869 if (!zend_worklist_len(&work)) {
872 zend_worklist_push(&work, pred);
876 if (entry_times[pred] > entry_times[i] && exit_times[pred] < exit_times[i]) {
883 while (zend_worklist_len(&work)) {
884 j = zend_worklist_pop(&work);
885 while (blocks[
j].loop_header >= 0) {
889 if (blocks[
j].idom < 0 &&
j != 0) {
memset(ptr, 0, type->size)
unsigned const char * end
zend_basic_block * blocks
zend_try_catch_element * try_catch_array
zend_string * function_name
struct _zend_arena zend_arena
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)
void zend_cfg_remark_reachable_blocks(const zend_op_array *op_array, zend_cfg *cfg)
struct _zend_basic_block zend_basic_block
#define ZEND_CFG_RECV_ENTRY
#define ZEND_BB_FINALLY_END
#define ZEND_BB_IRREDUCIBLE_LOOP
#define ZEND_BB_REACHABLE
#define ZEND_BB_UNREACHABLE_FREE
#define ZEND_CFG_NO_ENTRY_PREDECESSORS
struct _zend_cfg zend_cfg
#define ZEND_CFG_STACKLESS
#define CRT_CONSTANT(node)
#define ZEND_BB_LOOP_HEADER
#define ZEND_BB_RECV_ENTRY
#define ZEND_FETCH_GLOBAL_LOCK
#define ZEND_INTERNAL_FUNCTION
#define ZEND_OFFSET_TO_OPLINE_NUM(op_array, base, offset)
struct _zend_op_array zend_op_array
#define ZEND_THROW_IS_EXPR
#define OP_JMP_ADDR(opline, node)
#define ZEND_FETCH_GLOBAL
union _zend_function zend_function
#define ZEND_FUNC_HAS_CALLS
#define ZEND_FUNC_NO_LOOPS
#define ZEND_FUNC_HAS_EXTENDED_STMT
#define ZEND_FUNC_INDIRECT_VAR_ACCESS
#define ZEND_FUNC_FREE_LOOP_VAR
#define ZEND_FUNC_HAS_EXTENDED_FCALL
#define ZEND_FUNC_IRREDUCIBLE
#define ZEND_HASH_FOREACH_END()
#define ZEND_HASH_FOREACH_VAL(ht, _val)
uint32_t zend_optimizer_classify_function(zend_string *name, uint32_t num_args)
zend_op * zend_optimizer_get_loop_var_def(const zend_op_array *op_array, zend_op *free_opline)
#define ALLOCA_FLAG(name)
#define do_alloca(p, use_heap)
#define free_alloca(p, use_heap)
#define Z_ARRVAL_P(zval_p)
struct _zend_array HashTable
#define ZEND_EXT_FCALL_END
#define ZEND_INCLUDE_OR_EVAL
#define ZEND_GENERATOR_CREATE
#define ZEND_ASSERT_CHECK
#define ZEND_RETURN_BY_REF
#define ZEND_SWITCH_STRING
#define ZEND_EXT_FCALL_BEGIN
#define ZEND_INIT_NS_FCALL_BY_NAME
#define ZEND_ISSET_ISEMPTY_VAR
#define ZEND_BIND_INIT_STATIC_OR_JMP
#define ZEND_GENERATOR_RETURN
#define ZEND_FUNC_GET_ARGS
#define ZEND_JMP_FRAMELESS
#define ZEND_VERIFY_NEVER_TYPE
#define ZEND_DO_FCALL_BY_NAME
#define ZEND_FETCH_FUNC_ARG
#define ZEND_WORKLIST_ALLOCA(w, _len, use_heap)
struct _zend_worklist zend_worklist
#define ZEND_WORKLIST_FREE_ALLOCA(w, use_heap)