11static int ir_remove_unreachable_blocks(
ir_ctx *ctx);
34 for (;
n > 0;
p++,
n--) {
48 if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
49 n = insn->inputs_count;
50 for (
p = insn->ops + 1;
n > 0;
p++,
n--) {
55 }
else if (insn->op != IR_START) {
86 uint32_t bb_init_falgs;
87 uint32_t
count, bb_count = 0;
88 uint32_t edges_count = 0;
90 uint32_t *_blocks, *edges;
111 if (insn->op == IR_NOP) {
160 if (insn->op == IR_NOP) {
176 _blocks[
start] = ref;
194 if (insn->op == IR_NOP) {
215 if (insn->op == IR_START) {
219 bb->
flags = bb_init_falgs;
220 if (insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN) {
221 n = insn->inputs_count;
226 if (insn->op == IR_ENTRY) {
248 for (b = 1; b <= bb_count; b++, bb++) {
252 n = insn->inputs_count;
253 for (
p = insn->ops + 1;
n > 0;
p++, q++,
n--) {
256 ir_ref pred_b = _blocks[ref];
257 ir_block *pred_bb = &blocks[pred_b];
266 ir_ref pred_b = _blocks[ref];
267 ir_block *pred_bb = &blocks[pred_b];
280 uint32_t reachable_count = 0;
302 ir_remove_unreachable_blocks(ctx);
311static void ir_remove_predecessor(
ir_ctx *ctx,
ir_block *bb, uint32_t from)
313 uint32_t i, *
p, *q,
n = 0;
337 IR_ASSERT(insn->op == IR_MERGE || insn->op == IR_LOOP_BEGIN);
338 n = insn->inputs_count;
341 for (
j = 1;
j <=
n;
j++) {
353 for (
j = i + 1;
j <=
n;
j++) {
358 insn->inputs_count = 1;
360 if (use_list->
count > 1) {
365 if (use_insn->op == IR_PHI) {
368 for (
j = 2;
j <=
n;
j++) {
373 }
else if (input > 0) {
377 use_insn->op = IR_COPY;
378 use_insn->inputs_count = 1;
379 for (
j = 2;
j <=
n;
j++) {
393 use_list->
count -= (
p - q);
401 insn->inputs_count = i;
404 if (use_list->
count > 1) {
409 if (use_insn->op == IR_PHI) {
411 for (
j = 2;
j <=
n;
j++) {
420 }
else if (input > 0) {
424 use_insn->inputs_count = i - 1;
425 for (
j = i;
j <=
n;
j++) {
437static int ir_remove_unreachable_blocks(
ir_ctx *ctx)
440 uint32_t unreachable_count = 0;
444 for (b = 1; b <= bb_count; b++, bb++) {
447 do {
if (!unreachable_count)
ir_dump_cfg(ctx, stderr);}
while(0);
454 ir_remove_predecessor(ctx, succ_bb, b);
455 ir_remove_merge_input(ctx, succ_bb->
start, bb->
end);
466 ctx->
ir_base[1].op1 = insn->op3;
483 if (unreachable_count) {
489 for (b = 1; b <= bb_count; b++, bb++) {
506 for (b = 1; b <= bb_count; b++, bb++) {
515 for (
p = insn->ops + 1;
n > 0;
p++, q++,
n--) {
539static void compute_postnum(
const ir_ctx *ctx, uint32_t *cur, uint32_t b)
553 compute_postnum(ctx, cur, *
p);
564 uint32_t blocks_count, b, postnum;
572 compute_postnum(ctx, &postnum, 1);
582 for (b = 2, bb = &blocks[2]; b <= blocks_count; b++, bb++) {
587 if (blocks[pred_b].idom <= 0) {
589 }
else if (bb->
idom != pred_b) {
599 uint32_t pred_b = *
p;
600 ir_block *pred_bb = &blocks[pred_b];
603 if (pred_bb->
idom > 0) {
605 idom_bb = &blocks[idom];
609 pred_bb = &blocks[pred_b];
610 if (pred_bb->
idom > 0) {
611 while (idom != pred_b) {
613 pred_b = pred_bb->
idom;
614 pred_bb = &blocks[pred_b];
617 idom = idom_bb->
idom;
618 idom_bb = &blocks[idom];
624 if (bb->
idom != idom) {
639 for (b = 2, bb = &blocks[2]; b <= blocks_count; b++, bb++) {
648 }
else if (b < idom_bb->dom_child) {
653 ir_block *child_bb = &blocks[child];
657 child_bb = &blocks[child];
671static int ir_build_dominators_tree_iterative(
ir_ctx *ctx);
674 uint32_t blocks_count, b;
691 for (b = 2, bb = &blocks[2]; b <= blocks_count; b++, bb++) {
702 IR_ASSERT(k > 1 &&
"Wrong blocks order: BB is before its single predecessor");
719 uint32_t pred_b = *(++
p);
723 while (idom != pred_b) {
724 while (pred_b > idom) {
725 pred_b = blocks[pred_b].
idom;
727 while (idom > pred_b) {
728 idom = blocks[idom].
idom;
738 idom_bb = &blocks[idom];
744 }
else if (b < idom_bb->dom_child) {
749 ir_block *child_bb = &blocks[child];
753 child_bb = &blocks[child];
794 return ir_build_dominators_tree_iterative(ctx);
803static int ir_build_dominators_tree_iterative(
ir_ctx *ctx)
806 uint32_t blocks_count, b;
816 for (b = 0, bb = &blocks[0]; b <= blocks_count; b++, bb++) {
827 for (b = 2, bb = &blocks[2]; b <= blocks_count; b++, bb++) {
834 if (blocks[idom].idom == 0) {
839 if (blocks[idom].idom > 0) {
847 uint32_t pred_b = *(++
p);
849 if (blocks[pred_b].idom > 0) {
851 while (idom != pred_b) {
852 while (pred_b > idom) {
853 pred_b = blocks[pred_b].
idom;
855 while (idom > pred_b) {
856 idom = blocks[idom].
idom;
861 if (bb->
idom != idom) {
871 for (b = 2, bb = &blocks[2]; b <= blocks_count; b++, bb++) {
872 uint32_t idom = bb->
idom;
879 }
else if (b < idom_bb->dom_child) {
884 ir_block *child_bb = &blocks[child];
888 child_bb = &blocks[child];
899static bool ir_dominates(
const ir_block *blocks, uint32_t b1, uint32_t b2)
901 uint32_t b1_depth = blocks[b1].
dom_depth;
914 uint32_t *entry_times, *exit_times, *sorted_blocks,
time = 1;
939 if (!entry_times[i]) {
940 entry_times[i] =
time++;
957 if (blocks[succ].idom == i) {
964 exit_times[i] =
time++;
969 sorted_blocks[1] = 1;
977 for (child = blocks[sorted_blocks[i]].dom_child; child > 0; child = blocks[child].
dom_next_child) {
978 sorted_blocks[
n++] = child;
986 i = sorted_blocks[--
n];
990 bool irreducible = 0;
999 if (bb->
idom != pred) {
1002 if (ir_dominates(blocks, i, pred)) {
1011 if (entry_times[pred] > entry_times[i] && exit_times[pred] < exit_times[i]) {
1032 while (blocks[
j].loop_header > 0) {
1037 if (bb->
idom == 0 &&
j != 1) {
1058 i = sorted_blocks[
n];
1070 if (loop_depth > 1) {
1095static uint32_t _ir_skip_empty_blocks(
const ir_ctx *ctx, uint32_t b)
1127static int ir_edge_info_cmp(
const void *b1,
const void *b2)
1133 return e1->
freq < e2->
freq ? 1 : -1;
1145 return e1->
to - e2->
to;
1159 }
while (chains[src].
head !=
head);
1169 return ir_chain_head_path_compress(chains, src,
head);
1173static void ir_join_chains(
ir_chain *chains, uint32_t src, uint32_t dst)
1175 uint32_t dst_tail = chains[dst].
tail;
1176 uint32_t src_tail = chains[src].
tail;
1178 chains[dst_tail].
next = src;
1179 chains[dst].
prev = src_tail;
1180 chains[src_tail].
next = dst;
1181 chains[src].
tail = dst_tail;
1182 chains[dst].
head = src;
1185static void ir_insert_chain_before(
ir_chain *chains, uint32_t c, uint32_t before)
1191 if (chains[before].
head != before) {
1192 this->head =
next->head;
1196 this->next = before;
1197 this->prev =
next->prev;
1199 chains[this->prev].
next = c;
1202#ifndef IR_DEBUG_BB_SCHEDULE_GRAPH
1204# define IR_DEBUG_BB_SCHEDULE_GRAPH 1
1206# define IR_DEBUG_BB_SCHEDULE_GRAPH 0
1210#if IR_DEBUG_BB_SCHEDULE_GRAPH
1216 bool is_head, is_empty;
1217 uint32_t max_colors = 12;
1223 if (chains[b].
head == b) {
1224 colors[b] = (i % max_colors) + 1;
1229 fprintf(stderr,
"digraph {\n");
1230 fprintf(stderr,
"\trankdir=TB;\n");
1234 is_head = chains[b].
head == b;
1237 fprintf(stderr,
"\tBB%d [label=\"BB%d: (%d),%0.3f\\n%s\\n%s\",colorscheme=set312,fillcolor=%d%s%s]\n", b, b,
1241 is_head ?
",penwidth=3" :
"",
1242 is_empty ?
",style=\"dotted,filled\"" :
",style=\"filled\"");
1244 fprintf(stderr,
"\tBB%d [label=\"BB%d: (%d),%0.3f\\n%s\\n%s\"%s%s]\n", b, b,
1247 is_head ?
",penwidth=3" :
"",
1248 is_empty ?
",style=\"dotted\"" :
"");
1253 for (i = 0; i < edges_count; i++) {
1254 fprintf(stderr,
"\tBB%d -> BB%d [label=\"%0.3f\"]\n", edges[i].from, edges[i].to, edges[i].freq);
1266 for (i = 0; i < edges_count; i++) {
1267 fprintf(stderr,
"\tBB%d -> BB%d %0.3f\n", edges[i].from, edges[i].to, edges[i].freq);
1273 uint32_t b,
tail, i;
1277 if (chains[b].
head == b) {
1291static int ir_schedule_blocks_bottom_up(
ir_ctx *ctx)
1294 uint32_t edges_count = 0;
1295 uint32_t b, i, loop_depth;
1296 float *bb_freq, freq;
1302 uint32_t *schedule_end,
count;
1331 for (;
n > 0;
p++,
n--) {
1332 uint32_t predecessor = *
p;
1337 if (predecessor < b) {
1361 if (successor > b) {
1362 bb_freq[successor] += bb_freq[b];
1382 uint32_t successor = *
p;
1384 IR_ASSERT(edges_count < max_edges_count);
1386 if (successor > b) {
1388 bb_freq[successor] += freq;
1391 successor = _ir_skip_empty_blocks(ctx, successor);
1392 edges[edges_count].
from = b;
1393 edges[edges_count].
to = successor;
1394 edges[edges_count].
freq = freq;
1396 }
else if (
n == 2 && ctx->
ir_base[bb->
end].op == IR_IF) {
1397 uint32_t successor1 = *
p;
1400 uint32_t successor2 = *(
p + 1);
1403 int prob1, prob2, probN = 100;
1409 probN = prob1 + prob2;
1414 prob2 = 100 - prob1;
1417 }
else if (insn2->op2) {
1422 prob1 = 100 - prob2;
1423 }
else if (successor1_bb->
loop_depth >= loop_depth
1427 }
else if (successor1_bb->
loop_depth < loop_depth
1428 && successor2_bb->
loop_depth >= loop_depth) {
1441 freq = bb_freq[b] * (float)prob1 / (
float)probN;
1442 if (successor1 > b) {
1444 bb_freq[successor1] += freq;
1448 chains[successor1].
head = 0;
1449 *schedule_end = successor1;
1459 uint32_t src = chains[b].
next;
1463 ir_join_chains(chains, src, successor1);
1466 successor1 = _ir_skip_empty_blocks(ctx, successor1);
1467 IR_ASSERT(edges_count < max_edges_count);
1468 edges[edges_count].
from = b;
1469 edges[edges_count].
to = successor1;
1470 edges[edges_count].
freq = freq;
1474 freq = bb_freq[b] * (float)prob2 / (
float)probN;
1475 if (successor2 > b) {
1477 bb_freq[successor2] += freq;
1481 chains[successor2].
head = 0;
1482 *schedule_end = successor2;
1491 uint32_t src = chains[b].
next;
1495 ir_join_chains(chains, src, successor2);
1498 successor2 = _ir_skip_empty_blocks(ctx, successor2);
1499 IR_ASSERT(edges_count < max_edges_count);
1500 edges[edges_count].
from = b;
1501 edges[edges_count].
to = successor2;
1502 edges[edges_count].
freq = freq;
1508 for (;
n > 0;
p++,
n--) {
1509 uint32_t successor = *
p;
1513 if (insn->op == IR_CASE_DEFAULT) {
1518 }
else if (insn->op == IR_CASE_VAL) {
1523 }
else if (insn->op == IR_ENTRY) {
1532 freq = bb_freq[b] * (float)prob / 100.0f;
1533 if (successor > b) {
1535 bb_freq[successor] += freq;
1538 successor = _ir_skip_empty_blocks(ctx, successor);
1539 IR_ASSERT(edges_count < max_edges_count);
1540 edges[edges_count].
from = b;
1541 edges[edges_count].
to = successor;
1542 edges[edges_count].
freq = freq;
1552 qsort(edges, edges_count,
sizeof(
ir_edge_info), ir_edge_info_cmp);
1555 if (ctx->
flags & IR_DEBUG_BB_SCHEDULE) {
1556 ir_dump_edges(ctx, edges_count, edges);
1561 for (e = edges, i = edges_count; i > 0; e++, i--) {
1562 uint32_t dst = chains[e->
to].
head;
1564 uint32_t src = chains[e->
from].
next;
1565 if (chains[src].
head == src) {
1568 ir_join_chains(chains, src, dst);
1572 uint32_t
prev = src;
1582 }
else if (!best || bb_freq[
next] < bb_freq[best]) {
1592 chains[src].
head = best;
1593 chains[best].
head = best;
1596#if !IR_DEBUG_BB_SCHEDULE_GRAPH
1603#if IR_DEBUG_BB_SCHEDULE_GRAPH
1604 if (ctx->
flags & IR_DEBUG_BB_SCHEDULE) {
1605 ir_dump_cfg_freq_graph(ctx, bb_freq, edges_count, edges, chains);
1612 if (ctx->
flags & IR_DEBUG_BB_SCHEDULE) {
1613 ir_dump_chains(ctx, chains);
1622 if (b && chains[b].
head == b && chains[b].
tail == b) {
1633 ir_insert_chain_before(chains, b, successor);
1639 if (ctx->
flags & IR_DEBUG_BB_SCHEDULE) {
1640 ir_dump_chains(ctx, chains);
1647 if (chains[b].
head == b) {
1659 for (e = edges, i = edges_count; i > 0; e++, i--) {
1660#if !IR_DEBUG_BB_SCHEDULE_GRAPH
1661 if (!e->
from)
continue;
1667 ir_join_chains(chains, dst, src);
1669 ir_join_chains(chains, src, dst);
1675 if (ctx->
flags & IR_DEBUG_BB_SCHEDULE) {
1676 ir_dump_chains(ctx, chains);
1683 if (chains[b].
head == b) {
1689 if (i ==
tail)
break;
1707static int ir_schedule_blocks_top_down(
ir_ctx *ctx)
1710 uint32_t b, best_successor, last_non_empty;
1713 uint32_t *list, *schedule_end;
1732 uint32_t predecessor = b - 1;
1736 list[
count] = predecessor;
1747 best_successor_bb =
NULL;
1751 best_successor_bb = &ctx->
cfg_blocks[best_successor];
1754 uint32_t prob, best_successor_prob;
1755 uint32_t *
p, successor;
1763 if (insn->op == IR_IF_TRUE || insn->op == IR_IF_FALSE) {
1771 }
else if (insn->op == IR_CASE_DEFAULT) {
1776 }
else if (insn->op == IR_CASE_VAL) {
1781 }
else if (insn->op == IR_ENTRY) {
1790 if (!best_successor_bb
1792 || prob > best_successor_prob) {
1793 best_successor = successor;
1794 best_successor_bb = successor_bb;
1795 best_successor_prob = prob;
1800 if (!best_successor_bb) {
1821 bb = best_successor_bb;
1846 if (insn->op == IR_UNREACHABLE && ctx->
ir_base[insn->op1].op != IR_TAILCALL) {
1852 if (start_insn->op == IR_IF_TRUE
1853 || start_insn->op == IR_IF_FALSE
1854 || start_insn->op == IR_CASE_DEFAULT) {
1855 if (!start_insn->op2) start_insn->op2 = 1;
1856 }
else if (start_insn->op == IR_CASE_VAL) {
1857 if (!start_insn->op3) start_insn->op3 = 1;
1862 for (;
n > 0;
p++,
n--) {
1866 if (start_insn->op == IR_IF_TRUE
1867 || start_insn->op == IR_IF_FALSE
1868 || start_insn->op == IR_CASE_DEFAULT) {
1869 if (!start_insn->op2) start_insn->op2 = 1;
1870 }
else if (start_insn->op == IR_CASE_VAL) {
1871 if (!start_insn->op3) start_insn->op3 = 1;
1886 return ir_schedule_blocks_top_down(ctx);
1888 return ir_schedule_blocks_bottom_up(ctx);
1895 return _ir_skip_empty_blocks(ctx, b);
1932 uint32_t *
p, use_block;
fprintf($stream, string $format, mixed ... $values)
prev(array|object &$array)
count(Countable|array $value, int $mode=COUNT_NORMAL)
memset(ptr, 0, type->size)
const uint32_t ir_op_flags[IR_LAST_OP]
void ir_use_list_remove_one(ir_ctx *ctx, ir_ref from, ir_ref ref)
void ir_use_list_remove_all(ir_ctx *ctx, ir_ref from, ir_ref ref)
const char * ir_op_name[IR_LAST_OP]
void ir_dump_cfg(ir_ctx *ctx, FILE *f)
IR_ALWAYS_INLINE ir_ref ir_insn_op(const ir_insn *insn, int32_t n)
IR_ALWAYS_INLINE void ir_insn_set_op(ir_insn *insn, int32_t n, ir_ref val)
struct _ir_use_list ir_use_list
#define IR_MERGE_EMPTY_ENTRIES
struct _ir_block ir_block
int ir_schedule_blocks(ir_ctx *ctx)
int ir_find_loops(ir_ctx *ctx)
int ir_build_dominators_tree(ir_ctx *ctx)
int ir_build_cfg(ir_ctx *ctx)
struct _ir_edge_info ir_edge_info
IR_ALWAYS_INLINE void _ir_add_predecessors(const ir_insn *insn, ir_worklist *worklist)
IR_ALWAYS_INLINE void _ir_add_successors(const ir_ctx *ctx, ir_ref ref, ir_worklist *worklist)
struct _ir_chain ir_chain
void ir_reset_cfg(ir_ctx *ctx)
#define IR_DEBUG_BB_SCHEDULE_GRAPH
uint32_t ir_skip_empty_target_blocks(const ir_ctx *ctx, uint32_t b)
uint32_t ir_next_block(const ir_ctx *ctx, uint32_t b)
void ir_get_true_false_blocks(const ir_ctx *ctx, uint32_t b, uint32_t *true_block, uint32_t *false_block)
IR_ALWAYS_INLINE uint32_t ir_chain_head(ir_chain *chains, uint32_t src)
IR_ALWAYS_INLINE uint32_t ir_list_len(const ir_list *l)
ir_bitset_base_t * ir_bitset
IR_ALWAYS_INLINE ir_ref ir_list_pop(ir_list *l)
IR_ALWAYS_INLINE void ir_worklist_free(ir_worklist *w)
IR_ALWAYS_INLINE bool ir_bitset_in(const ir_bitset set, uint32_t n)
IR_ALWAYS_INLINE void ir_bitqueue_del(ir_bitqueue *q, uint32_t n)
IR_ALWAYS_INLINE void ir_bitqueue_add(ir_bitqueue *q, uint32_t n)
IR_ALWAYS_INLINE bool ir_bitqueue_in(const ir_bitqueue *q, uint32_t n)
IR_ALWAYS_INLINE ir_bitset ir_bitset_malloc(uint32_t n)
#define IR_IRREDUCIBLE_CFG
IR_ALWAYS_INLINE bool ir_worklist_push(ir_worklist *w, ir_ref val)
IR_ALWAYS_INLINE ir_ref ir_worklist_peek(const ir_worklist *w)
IR_ALWAYS_INLINE void ir_worklist_clear(ir_worklist *w)
#define IR_BITSET_FOREACH_DIFFERENCE(set1, set2, len, bit)
struct _ir_worklist ir_worklist
IR_ALWAYS_INLINE void ir_bitset_union(ir_bitset set1, const ir_bitset set2, uint32_t len)
IR_ALWAYS_INLINE void ir_bitset_incl(ir_bitset set, uint32_t n)
#define IR_IS_BB_START(op)
IR_ALWAYS_INLINE void ir_worklist_init(ir_worklist *w, uint32_t size)
IR_ALWAYS_INLINE uint32_t ir_worklist_capasity(const ir_worklist *w)
IR_ALWAYS_INLINE void ir_list_free(ir_list *l)
IR_ALWAYS_INLINE uint32_t ir_bitset_len(uint32_t n)
#define IR_BB_IRREDUCIBLE_LOOP
IR_ALWAYS_INLINE void ir_bitqueue_init(ir_bitqueue *q, uint32_t n)
#define IR_BB_LOOP_WITH_ENTRY
#define IR_BB_PREV_EMPTY_ENTRY
IR_ALWAYS_INLINE void ir_list_init(ir_list *l, uint32_t size)
#define IR_OPND_KIND(flags, i)
IR_ALWAYS_INLINE int ir_bitqueue_pop(ir_bitqueue *q)
#define IR_BB_UNREACHABLE
#define IR_BITSET_FOREACH(set, len, bit)
#define IR_BITSET_FOREACH_END()
IR_ALWAYS_INLINE void ir_bitset_clear(ir_bitset set, uint32_t len)
#define IR_OP_FLAG_CONTROL
IR_ALWAYS_INLINE void ir_bitqueue_free(ir_bitqueue *q)
IR_ALWAYS_INLINE void ir_list_push(ir_list *l, ir_ref val)
IR_ALWAYS_INLINE ir_ref ir_next_control(const ir_ctx *ctx, ir_ref ref)
IR_ALWAYS_INLINE ir_ref ir_worklist_pop(ir_worklist *w)
IR_ALWAYS_INLINE uint32_t ir_worklist_len(const ir_worklist *w)
struct _ir_bitqueue ir_bitqueue
#define IR_BB_LOOP_HEADER
#define IR_OP_FLAG_TERMINATOR
unsigned const char * end
struct php_pcntl_pending_signal * head
struct php_pcntl_pending_signal * tail
const phpdbg_color_t * colors[PHPDBG_COLORS]
uint32_t successors_count
uint32_t predecessors_count
uint32_t cfg_blocks_count
#define EXPECTED(condition)
#define UNEXPECTED(condition)