Skip to content

Commit d2b54dc

Browse files
committed
Update IR
IR commit: eee484977acfe97b81b338a16390e218a852ec1c
1 parent bb1688d commit d2b54dc

File tree

9 files changed

+252
-27
lines changed

9 files changed

+252
-27
lines changed

ext/opcache/jit/ir/ir.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ void ir_print_const(const ir_ctx *ctx, const ir_insn *insn, FILE *f, bool quoted
267267
#define ir_op_flag_x2 (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | 2 | (2 << IR_OP_FLAG_OPERANDS_SHIFT))
268268
#define ir_op_flag_x3 (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | 3 | (3 << IR_OP_FLAG_OPERANDS_SHIFT))
269269
#define ir_op_flag_xN (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_CALL | IR_OP_FLAG_VAR_INPUTS)
270+
#define ir_op_flag_a1 (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_ALLOC | 1 | (1 << IR_OP_FLAG_OPERANDS_SHIFT))
270271
#define ir_op_flag_a2 (IR_OP_FLAG_CONTROL|IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_ALLOC | 2 | (2 << IR_OP_FLAG_OPERANDS_SHIFT))
271272

272273
#define ir_op_kind____ IR_OPND_UNUSED
@@ -2771,3 +2772,9 @@ ir_ref _ir_VA_ARG(ir_ctx *ctx, ir_type type, ir_ref list)
27712772
IR_ASSERT(ctx->control);
27722773
return ctx->control = ir_emit2(ctx, IR_OPT(IR_VA_ARG, type), ctx->control, list);
27732774
}
2775+
2776+
ir_ref _ir_BLOCK_BEGIN(ir_ctx *ctx)
2777+
{
2778+
IR_ASSERT(ctx->control);
2779+
return ctx->control = ir_emit1(ctx, IR_OPT(IR_BLOCK_BEGIN, IR_ADDR), ctx->control);
2780+
}

ext/opcache/jit/ir/ir.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,8 @@ typedef enum _ir_type {
316316
/* memory reference and load/store ops */ \
317317
_(ALLOCA, a2, src, def, ___) /* alloca(def) */ \
318318
_(AFREE, a2, src, def, ___) /* revert alloca(def) */ \
319+
_(BLOCK_BEGIN, a1, src, ___, ___) /* stacksave */ \
320+
_(BLOCK_END, a2, src, def, ___) /* stackrestore */ \
319321
_(VADDR, d1, var, ___, ___) /* load address of local var */ \
320322
_(VLOAD, l2, src, var, ___) /* load value of local var */ \
321323
_(VSTORE, s3, src, var, def) /* store value to local var */ \

ext/opcache/jit/ir/ir_aarch64.dasc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4063,6 +4063,34 @@ static void ir_emit_afree(ir_ctx *ctx, ir_ref def, ir_insn *insn)
40634063
}
40644064
}
40654065

4066+
static void ir_emit_block_begin(ir_ctx *ctx, ir_ref def, ir_insn *insn)
4067+
{
4068+
ir_backend_data *data = ctx->data;
4069+
dasm_State **Dst = &data->dasm_state;
4070+
ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]);
4071+
4072+
| mov Rx(def_reg), sp
4073+
4074+
if (IR_REG_SPILLED(ctx->regs[def][0])) {
4075+
ir_emit_store(ctx, IR_ADDR, def, def_reg);
4076+
}
4077+
}
4078+
4079+
static void ir_emit_block_end(ir_ctx *ctx, ir_ref def, ir_insn *insn)
4080+
{
4081+
ir_backend_data *data = ctx->data;
4082+
dasm_State **Dst = &data->dasm_state;
4083+
ir_reg op2_reg = ctx->regs[def][2];
4084+
4085+
IR_ASSERT(op2_reg != IR_REG_NONE);
4086+
if (IR_REG_SPILLED(op2_reg)) {
4087+
op2_reg = IR_REG_NUM(op2_reg);
4088+
ir_emit_load(ctx, IR_ADDR, op2_reg, insn->op2);
4089+
}
4090+
4091+
| mov sp, Rx(op2_reg)
4092+
}
4093+
40664094
static void ir_emit_frame_addr(ir_ctx *ctx, ir_ref def)
40674095
{
40684096
ir_backend_data *data = ctx->data;
@@ -5965,6 +5993,12 @@ void *ir_emit_code(ir_ctx *ctx, size_t *size_ptr)
59655993
case IR_AFREE:
59665994
ir_emit_afree(ctx, i, insn);
59675995
break;
5996+
case IR_BLOCK_BEGIN:
5997+
ir_emit_block_begin(ctx, i, insn);
5998+
break;
5999+
case IR_BLOCK_END:
6000+
ir_emit_block_end(ctx, i, insn);
6001+
break;
59686002
case IR_FRAME_ADDR:
59696003
ir_emit_frame_addr(ctx, i);
59706004
break;

ext/opcache/jit/ir/ir_builder.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,9 @@ extern "C" {
577577

578578
#define ir_FRAME_ADDR() ir_fold0(_ir_CTX, IR_OPT(IR_FRAME_ADDR, IR_ADDR))
579579

580+
#define ir_BLOCK_BEGIN() _ir_BLOCK_BEGIN(_ir_CTX)
581+
#define ir_BLOCK_END(_val) do {_ir_CTX->control = ir_emit2(_ir_CTX, IR_BLOCK_END, _ir_CTX->control, (_val));} while (0)
582+
580583
#define ir_VA_START(_list) _ir_VA_START(_ir_CTX, _list)
581584
#define ir_VA_END(_list) _ir_VA_END(_ir_CTX, _list)
582585
#define ir_VA_COPY(_dst, _src) _ir_VA_COPY(_ir_CTX, _dst, _src)
@@ -680,6 +683,7 @@ void _ir_RETURN(ir_ctx *ctx, ir_ref val);
680683
void _ir_IJMP(ir_ctx *ctx, ir_ref addr);
681684
void _ir_GUARD(ir_ctx *ctx, ir_ref condition, ir_ref addr);
682685
void _ir_GUARD_NOT(ir_ctx *ctx, ir_ref condition, ir_ref addr);
686+
ir_ref _ir_BLOCK_BEGIN(ir_ctx *ctx);
683687
ir_ref _ir_SNAPSHOT(ir_ctx *ctx, ir_ref n);
684688
void _ir_SNAPSHOT_SET_OP(ir_ctx *ctx, ir_ref snapshot, ir_ref pos, ir_ref val);
685689
ir_ref _ir_EXITCALL(ir_ctx *ctx, ir_ref func);

ext/opcache/jit/ir/ir_cfg.c

Lines changed: 140 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1511,12 +1511,17 @@ int ir_build_dominators_tree(ir_ctx *ctx)
15111511
}
15121512
#else
15131513
/* A single pass modification of "A Simple, Fast Dominance Algorithm" by
1514-
* Cooper, Harvey and Kennedy, that relays on IR block ordering */
1514+
* Cooper, Harvey and Kennedy, that relays on IR block ordering.
1515+
* It may fallback to the general slow fixed-point algorithm. */
1516+
static int ir_build_dominators_tree_iterative(ir_ctx *ctx);
15151517
int ir_build_dominators_tree(ir_ctx *ctx)
15161518
{
15171519
uint32_t blocks_count, b;
15181520
ir_block *blocks, *bb;
15191521
uint32_t *edges;
1522+
ir_list worklist;
1523+
1524+
ir_list_init(&worklist, ctx->cfg_blocks_count / 2);
15201525

15211526
ctx->flags2 |= IR_NO_LOOPS;
15221527

@@ -1539,6 +1544,9 @@ int ir_build_dominators_tree(ir_ctx *ctx)
15391544
if (UNEXPECTED(idom > b)) {
15401545
/* In rare cases, LOOP_BEGIN.op1 may be a back-edge. Skip back-edges. */
15411546
ctx->flags2 &= ~IR_NO_LOOPS;
1547+
IR_ASSERT(k > 1);
1548+
IR_ASSERT(blocks[idom].successors_count == 1);
1549+
ir_list_push(&worklist, idom);
15421550
while (1) {
15431551
k--;
15441552
p++;
@@ -1547,9 +1555,12 @@ int ir_build_dominators_tree(ir_ctx *ctx)
15471555
break;
15481556
}
15491557
IR_ASSERT(k > 0);
1558+
IR_ASSERT(blocks[idom].successors_count == 1);
1559+
ir_list_push(&worklist, idom);
15501560
}
15511561
}
15521562
IR_ASSERT(blocks[idom].idom > 0);
1563+
IR_ASSERT(k != 0);
15531564

15541565
while (--k > 0) {
15551566
uint32_t pred_b = *(++p);
@@ -1566,6 +1577,9 @@ int ir_build_dominators_tree(ir_ctx *ctx)
15661577
}
15671578
} else {
15681579
ctx->flags2 &= ~IR_NO_LOOPS;
1580+
IR_ASSERT(bb->predecessors_count > 1);
1581+
IR_ASSERT(blocks[pred_b].successors_count == 1);
1582+
ir_list_push(&worklist, pred_b);
15691583
}
15701584
}
15711585
bb->idom = idom;
@@ -1593,6 +1607,131 @@ int ir_build_dominators_tree(ir_ctx *ctx)
15931607

15941608
blocks[1].idom = 0;
15951609

1610+
if (ir_list_len(&worklist) != 0) {
1611+
uint32_t dom_depth;
1612+
uint32_t succ_b;
1613+
bool complete = 1;
1614+
1615+
/* Check if all the back-edges lead to the loop headers */
1616+
do {
1617+
b = ir_list_pop(&worklist);
1618+
bb = &blocks[b];
1619+
IR_ASSERT(bb->successors_count == 1);
1620+
succ_b = ctx->cfg_edges[bb->successors];
1621+
dom_depth = blocks[succ_b].dom_depth;;
1622+
while (bb->dom_depth > dom_depth) {
1623+
b = bb->dom_parent;
1624+
bb = &blocks[b];
1625+
}
1626+
if (UNEXPECTED(b != succ_b)) {
1627+
complete = 0;
1628+
break;
1629+
}
1630+
} while (ir_list_len(&worklist) != 0);
1631+
1632+
if (UNEXPECTED(!complete)) {
1633+
ir_list_free(&worklist);
1634+
return ir_build_dominators_tree_iterative(ctx);
1635+
}
1636+
}
1637+
1638+
ir_list_free(&worklist);
1639+
1640+
return 1;
1641+
}
1642+
1643+
static int ir_build_dominators_tree_iterative(ir_ctx *ctx)
1644+
{
1645+
bool changed;
1646+
uint32_t blocks_count, b;
1647+
ir_block *blocks, *bb;
1648+
uint32_t *edges;
1649+
1650+
/* Find immediate dominators */
1651+
blocks = ctx->cfg_blocks;
1652+
edges = ctx->cfg_edges;
1653+
blocks_count = ctx->cfg_blocks_count;
1654+
1655+
/* Clear the dominators tree, but keep already found dominators */
1656+
for (b = 0, bb = &blocks[0]; b <= blocks_count; b++, bb++) {
1657+
bb->dom_depth = 0;
1658+
bb->dom_child = 0;
1659+
bb->dom_next_child = 0;
1660+
}
1661+
1662+
/* Find immediate dominators by iterative fixed-point algorithm */
1663+
blocks[1].idom = 1;
1664+
do {
1665+
changed = 0;
1666+
1667+
for (b = 2, bb = &blocks[2]; b <= blocks_count; b++, bb++) {
1668+
IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE));
1669+
IR_ASSERT(bb->predecessors_count > 0);
1670+
uint32_t k = bb->predecessors_count;
1671+
uint32_t *p = edges + bb->predecessors;
1672+
uint32_t idom = *p;
1673+
1674+
if (blocks[idom].idom == 0) {
1675+
while (1) {
1676+
k--;
1677+
p++;
1678+
idom = *p;
1679+
if (blocks[idom].idom > 0) {
1680+
break;
1681+
}
1682+
IR_ASSERT(k > 0);
1683+
}
1684+
}
1685+
IR_ASSERT(k != 0);
1686+
while (--k > 0) {
1687+
uint32_t pred_b = *(++p);
1688+
1689+
if (blocks[pred_b].idom > 0) {
1690+
IR_ASSERT(blocks[pred_b].idom > 0);
1691+
while (idom != pred_b) {
1692+
while (pred_b > idom) {
1693+
pred_b = blocks[pred_b].idom;
1694+
}
1695+
while (idom > pred_b) {
1696+
idom = blocks[idom].idom;
1697+
}
1698+
}
1699+
}
1700+
}
1701+
if (bb->idom != idom) {
1702+
bb->idom = idom;
1703+
changed = 1;
1704+
}
1705+
}
1706+
} while (changed);
1707+
1708+
/* Build dominators tree */
1709+
blocks[1].idom = 0;
1710+
blocks[1].dom_depth = 0;
1711+
for (b = 2, bb = &blocks[2]; b <= blocks_count; b++, bb++) {
1712+
uint32_t idom = bb->idom;
1713+
ir_block *idom_bb = &blocks[idom];
1714+
1715+
bb->dom_depth = idom_bb->dom_depth + 1;
1716+
/* Sort by block number to traverse children in pre-order */
1717+
if (idom_bb->dom_child == 0) {
1718+
idom_bb->dom_child = b;
1719+
} else if (b < idom_bb->dom_child) {
1720+
bb->dom_next_child = idom_bb->dom_child;
1721+
idom_bb->dom_child = b;
1722+
} else {
1723+
int child = idom_bb->dom_child;
1724+
ir_block *child_bb = &blocks[child];
1725+
1726+
while (child_bb->dom_next_child > 0 && b > child_bb->dom_next_child) {
1727+
child = child_bb->dom_next_child;
1728+
child_bb = &blocks[child];
1729+
}
1730+
bb->dom_next_child = child_bb->dom_next_child;
1731+
child_bb->dom_next_child = b;
1732+
}
1733+
}
1734+
15961735
return 1;
15971736
}
15981737
#endif

ext/opcache/jit/ir/ir_emit.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -662,14 +662,16 @@ static void ir_emit_dessa_move(ir_ctx *ctx, ir_type type, ir_ref to, ir_ref from
662662
}
663663
}
664664

665-
IR_ALWAYS_INLINE void ir_dessa_resolve_cycle(ir_ctx *ctx, int32_t *pred, int32_t *loc, ir_bitset todo, ir_type type, int32_t to, ir_reg tmp_reg, ir_reg tmp_fp_reg)
665+
IR_ALWAYS_INLINE void ir_dessa_resolve_cycle(ir_ctx *ctx, int32_t *pred, int32_t *loc, int8_t *types, ir_bitset todo, int32_t to, ir_reg tmp_reg, ir_reg tmp_fp_reg)
666666
{
667667
ir_ref from;
668668
ir_mem tmp_spill_slot;
669+
ir_type type;
669670

670671
IR_MEM_VAL(tmp_spill_slot) = 0;
671672
IR_ASSERT(!IR_IS_CONST_REF(to));
672673
from = pred[to];
674+
type = types[from];
673675
IR_ASSERT(!IR_IS_CONST_REF(from));
674676
IR_ASSERT(from != to);
675677
IR_ASSERT(loc[from] == from);
@@ -721,6 +723,7 @@ IR_ALWAYS_INLINE void ir_dessa_resolve_cycle(ir_ctx *ctx, int32_t *pred, int32_t
721723

722724
from = pred[to];
723725
r = loc[from];
726+
type = types[to];
724727

725728
if (from == r && ir_bitset_in(todo, from)) {
726729
/* Memory to memory move inside an isolated or "blocked" cycle requres an additional temporary register */
@@ -743,6 +746,8 @@ IR_ALWAYS_INLINE void ir_dessa_resolve_cycle(ir_ctx *ctx, int32_t *pred, int32_t
743746
break;
744747
}
745748
}
749+
750+
type = types[to];
746751
if (IR_MEM_VAL(tmp_spill_slot)) {
747752
ir_emit_load_mem(ctx, type, IR_IS_TYPE_INT(type) ? tmp_reg : tmp_fp_reg, tmp_spill_slot);
748753
}
@@ -830,11 +835,12 @@ static int ir_dessa_parallel_copy(ir_ctx *ctx, ir_dessa_copy *copies, int count,
830835
to = pred[to];
831836
while (!IR_IS_CONST_REF(to) && ir_bitset_in(ready, to)) {
832837
to = pred[to];
833-
if (!IR_IS_CONST_REF(to) && ir_bitset_in(visited, to)) {
838+
if (IR_IS_CONST_REF(to)) {
839+
break;
840+
} else if (ir_bitset_in(visited, to)) {
834841
/* We found a cycle. Resolve it. */
835842
ir_bitset_incl(visited, to);
836-
type = types[to];
837-
ir_dessa_resolve_cycle(ctx, pred, loc, todo, type, to, tmp_reg, tmp_fp_reg);
843+
ir_dessa_resolve_cycle(ctx, pred, loc, types, todo, to, tmp_reg, tmp_fp_reg);
838844
break;
839845
}
840846
ir_bitset_incl(visited, to);

ext/opcache/jit/ir/ir_ra.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3311,26 +3311,26 @@ static int ir_fix_dessa_tmps(ir_ctx *ctx, uint8_t type, ir_ref from, ir_ref to)
33113311
if (IR_IS_TYPE_INT(type)) {
33123312
tmp_reg.num = 0;
33133313
tmp_reg.type = type;
3314-
tmp_reg.start = IR_DEF_SUB_REF;
3314+
tmp_reg.start = IR_USE_SUB_REF;
33153315
tmp_reg.end = IR_SAVE_SUB_REF;
33163316
} else {
33173317
IR_ASSERT(IR_IS_TYPE_FP(type));
33183318
tmp_reg.num = 1;
33193319
tmp_reg.type = type;
3320-
tmp_reg.start = IR_DEF_SUB_REF;
3320+
tmp_reg.start = IR_USE_SUB_REF;
33213321
tmp_reg.end = IR_SAVE_SUB_REF;
33223322
}
33233323
} else if (from != 0) {
33243324
if (IR_IS_TYPE_INT(type)) {
33253325
tmp_reg.num = 0;
33263326
tmp_reg.type = type;
3327-
tmp_reg.start = IR_DEF_SUB_REF;
3327+
tmp_reg.start = IR_USE_SUB_REF;
33283328
tmp_reg.end = IR_SAVE_SUB_REF;
33293329
} else {
33303330
IR_ASSERT(IR_IS_TYPE_FP(type));
33313331
tmp_reg.num = 1;
33323332
tmp_reg.type = type;
3333-
tmp_reg.start = IR_DEF_SUB_REF;
3333+
tmp_reg.start = IR_USE_SUB_REF;
33343334
tmp_reg.end = IR_SAVE_SUB_REF;
33353335
}
33363336
} else {
@@ -3916,7 +3916,7 @@ static void assign_regs(ir_ctx *ctx)
39163916
} else {
39173917
reg |= IR_REG_SPILL_LOAD;
39183918
}
3919-
if (ctx->ir_base[ref].op != IR_SNAPSHOT) {
3919+
if (ctx->ir_base[ref].op != IR_SNAPSHOT && !(use_pos->flags & IR_PHI_USE)) {
39203920
uint32_t use_b = ctx->cfg_map[ref];
39213921

39223922
if (ir_ival_covers(ival, IR_SAVE_LIVE_POS_FROM_REF(ctx->cfg_blocks[use_b].end))) {

0 commit comments

Comments
 (0)