Skip to content

Commit 7e2831f

Browse files
committed
Update IR
IR commit: 94e71e613221e79b033c48b54230e128755c95f9
1 parent 9aee546 commit 7e2831f

File tree

7 files changed

+202
-92
lines changed

7 files changed

+202
-92
lines changed

ext/opcache/jit/ir/ir.c

Lines changed: 80 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1798,7 +1798,9 @@ static ir_alias ir_check_partial_aliasing(const ir_ctx *ctx, ir_ref addr1, ir_re
17981798
if (insn1->op != IR_ADD) {
17991799
base1 = addr1;
18001800
off1 = IR_UNUSED;
1801-
} else if (ctx->ir_base[insn1->op2].op == IR_SYM) {
1801+
} else if (ctx->ir_base[insn1->op2].op == IR_SYM
1802+
|| ctx->ir_base[insn1->op2].op == IR_ALLOCA
1803+
|| ctx->ir_base[insn1->op2].op == IR_VADDR) {
18021804
base1 = insn1->op2;
18031805
off1 = insn1->op1;
18041806
} else {
@@ -1808,7 +1810,9 @@ static ir_alias ir_check_partial_aliasing(const ir_ctx *ctx, ir_ref addr1, ir_re
18081810
if (insn2->op != IR_ADD) {
18091811
base2 = addr2;
18101812
off2 = IR_UNUSED;
1811-
} else if (ctx->ir_base[insn2->op2].op == IR_SYM) {
1813+
} else if (ctx->ir_base[insn2->op2].op == IR_SYM
1814+
|| ctx->ir_base[insn2->op2].op == IR_ALLOCA
1815+
|| ctx->ir_base[insn2->op2].op == IR_VADDR) {
18121816
base2 = insn2->op2;
18131817
off2 = insn2->op1;
18141818
} else {
@@ -1834,17 +1838,41 @@ static ir_alias ir_check_partial_aliasing(const ir_ctx *ctx, ir_ref addr1, ir_re
18341838
}
18351839
if (offset1 == offset2) {
18361840
return IR_MUST_ALIAS;
1837-
} else if (offset1 < offset2) {
1841+
} else if (offset1 < offset2) {
18381842
return offset1 + ir_type_size[type1] <= offset2 ? IR_NO_ALIAS : IR_MUST_ALIAS;
18391843
} else {
18401844
return offset2 + ir_type_size[type2] <= offset1 ? IR_NO_ALIAS : IR_MUST_ALIAS;
18411845
}
18421846
} else {
18431847
insn1 = &ctx->ir_base[base1];
18441848
insn2 = &ctx->ir_base[base2];
1845-
if ((insn1->op == IR_ALLOCA && (insn2->op == IR_ALLOCA || insn2->op == IR_SYM || insn2->op == IR_PARAM))
1846-
|| (insn1->op == IR_SYM && (insn2->op == IR_ALLOCA || insn2->op == IR_SYM))
1847-
|| (insn1->op == IR_PARAM && insn2->op == IR_ALLOCA)) {
1849+
while (insn1->op == IR_ADD) {
1850+
insn1 = &ctx->ir_base[insn1->op2];
1851+
if (insn1->op == IR_SYM
1852+
|| insn1->op == IR_ALLOCA
1853+
|| insn1->op == IR_VADDR) {
1854+
break;
1855+
} else {
1856+
insn1 = &ctx->ir_base[insn1->op1];
1857+
}
1858+
}
1859+
while (insn2->op == IR_ADD) {
1860+
insn2 = &ctx->ir_base[insn2->op2];
1861+
if (insn2->op == IR_SYM
1862+
|| insn2->op == IR_ALLOCA
1863+
|| insn2->op == IR_VADDR) {
1864+
break;
1865+
} else {
1866+
insn2 = &ctx->ir_base[insn2->op1];
1867+
}
1868+
}
1869+
if (insn1 == insn2) {
1870+
return IR_MAY_ALIAS;
1871+
}
1872+
if ((insn1->op == IR_ALLOCA && (insn2->op == IR_ALLOCA || insn2->op == IR_VADDR || insn2->op == IR_SYM || insn2->op == IR_PARAM))
1873+
|| (insn1->op == IR_VADDR && (insn2->op == IR_ALLOCA || insn2->op == IR_VADDR || insn2->op == IR_SYM || insn2->op == IR_PARAM))
1874+
|| (insn1->op == IR_SYM && (insn2->op == IR_ALLOCA || insn2->op == IR_VADDR || insn2->op == IR_SYM))
1875+
|| (insn1->op == IR_PARAM && (insn2->op == IR_ALLOCA || insn2->op == IR_VADDR))) {
18481876
return IR_NO_ALIAS;
18491877
}
18501878
}
@@ -2715,7 +2743,53 @@ ir_ref _ir_VLOAD(ir_ctx *ctx, ir_type type, ir_ref var)
27152743

27162744
void _ir_VSTORE(ir_ctx *ctx, ir_ref var, ir_ref val)
27172745
{
2746+
ir_ref limit = var;
2747+
ir_ref ref = ctx->control;
2748+
ir_ref prev = IR_UNUSED;
2749+
ir_insn *insn;
2750+
bool guarded = 0;
2751+
2752+
if (!IR_IS_CONST_REF(val)) {
2753+
insn = &ctx->ir_base[val];
2754+
if (insn->op == IR_BITCAST
2755+
&& !IR_IS_CONST_REF(insn->op1)
2756+
&& ir_type_size[insn->type] == ir_type_size[ctx->ir_base[insn->op1].type]) {
2757+
/* skip BITCAST */
2758+
val = insn->op1;
2759+
}
2760+
}
2761+
27182762
IR_ASSERT(ctx->control);
2763+
while (ref > limit) {
2764+
insn = &ctx->ir_base[ref];
2765+
if (insn->op == IR_VSTORE) {
2766+
if (insn->op2 == var) {
2767+
if (insn->op3 == val) {
2768+
return;
2769+
} else {
2770+
if (!guarded) {
2771+
if (prev) {
2772+
ctx->ir_base[prev].op1 = insn->op1;
2773+
} else {
2774+
ctx->control = insn->op1;
2775+
}
2776+
MAKE_NOP(insn);
2777+
}
2778+
break;
2779+
}
2780+
}
2781+
} else if (insn->op == IR_VLOAD) {
2782+
if (insn->op2 == var) {
2783+
break;
2784+
}
2785+
} else if (insn->op == IR_GUARD || insn->op == IR_GUARD_NOT) {
2786+
guarded = 1;
2787+
} else if (insn->op >= IR_START || insn->op == IR_CALL || insn->op == IR_LOAD || insn->op == IR_STORE) {
2788+
break;
2789+
}
2790+
prev = ref;
2791+
ref = insn->op1;
2792+
}
27192793
ctx->control = ir_emit3(ctx, IR_VSTORE, ctx->control, var, val);
27202794
}
27212795

ext/opcache/jit/ir/ir_aarch64.dasc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -592,11 +592,11 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co
592592
constraints->tmp_regs[n] = IR_TMP_REG(1, ctx->ir_base[insn->op1].type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
593593
n++;
594594
}
595-
if (IR_IS_CONST_REF(insn->op2)) {
595+
if (IR_IS_CONST_REF(insn->op2) || ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA) {
596596
constraints->tmp_regs[n] = IR_TMP_REG(2, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
597597
n++;
598598
}
599-
if (IR_IS_CONST_REF(insn->op3)) {
599+
if (IR_IS_CONST_REF(insn->op3) || ir_rule(ctx, insn->op3) == IR_STATIC_ALLOCA) {
600600
constraints->tmp_regs[n] = IR_TMP_REG(3, insn->type, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
601601
n++;
602602
}

ext/opcache/jit/ir/ir_emit.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,9 @@ IR_ALWAYS_INLINE void ir_dessa_resolve_cycle(ir_ctx *ctx, int32_t *pred, int32_t
695695
#ifdef IR_HAVE_SWAP_INT
696696
if (pred[from] == to && to < IR_REG_NUM && from < IR_REG_NUM) {
697697
/* a simple cycle from 2 elements */
698+
if (ir_type_size[types[to]] > ir_type_size[type]) {
699+
type = types[to];
700+
}
698701
ir_emit_swap(ctx, type, to, from);
699702
ir_bitset_excl(todo, from);
700703
ir_bitset_excl(todo, to);
@@ -713,7 +716,7 @@ IR_ALWAYS_INLINE void ir_dessa_resolve_cycle(ir_ctx *ctx, int32_t *pred, int32_t
713716
}
714717
} else {
715718
#ifdef IR_HAVE_SWAP_FP
716-
if (pred[from] == to && to < IR_REG_NUM && from < IR_REG_NUM) {
719+
if (pred[from] == to && to < IR_REG_NUM && from < IR_REG_NUM && types[to] == type) {
717720
/* a simple cycle from 2 elements */
718721
ir_emit_swap_fp(ctx, type, to, from);
719722
IR_REGSET_EXCL(todo, from);

ext/opcache/jit/ir/ir_fold.h

Lines changed: 84 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,32 +1557,6 @@ IR_FOLD(SUB_OV(_, C_ADDR))
15571557
IR_FOLD_NEXT;
15581558
}
15591559

1560-
IR_FOLD(ADD(C_U8, _))
1561-
IR_FOLD(ADD(C_U16, _))
1562-
IR_FOLD(ADD(C_U32, _))
1563-
IR_FOLD(ADD(C_U64, _))
1564-
IR_FOLD(ADD(C_I8, _))
1565-
IR_FOLD(ADD(C_I16, _))
1566-
IR_FOLD(ADD(C_I32, _))
1567-
IR_FOLD(ADD(C_I64, _))
1568-
IR_FOLD(ADD(C_ADDR, _))
1569-
IR_FOLD(ADD_OV(C_U8, _))
1570-
IR_FOLD(ADD_OV(C_U16, _))
1571-
IR_FOLD(ADD_OV(C_U32, _))
1572-
IR_FOLD(ADD_OV(C_U64, _))
1573-
IR_FOLD(ADD_OV(C_I8, _))
1574-
IR_FOLD(ADD_OV(C_I16, _))
1575-
IR_FOLD(ADD_OV(C_I32, _))
1576-
IR_FOLD(ADD_OV(C_I64, _))
1577-
IR_FOLD(ADD_OV(C_ADDR, _))
1578-
{
1579-
if (op1_insn->val.u64 == 0) {
1580-
/* 0 + a => a */
1581-
IR_FOLD_COPY(op2);
1582-
}
1583-
IR_FOLD_NEXT;
1584-
}
1585-
15861560
IR_FOLD(SUB(C_I8, _))
15871561
IR_FOLD(SUB(C_I16, _))
15881562
IR_FOLD(SUB(C_I32, _))
@@ -1839,51 +1813,6 @@ IR_FOLD(MUL(_, C_I64))
18391813
IR_FOLD_NEXT;
18401814
}
18411815

1842-
IR_FOLD(MUL(C_U8, _))
1843-
IR_FOLD(MUL(C_U16, _))
1844-
IR_FOLD(MUL(C_U32, _))
1845-
IR_FOLD(MUL(C_U64, _))
1846-
IR_FOLD(MUL(C_ADDR, _))
1847-
{
1848-
if (op1_insn->val.u64 == 0) {
1849-
/* 0 * a => 0 */
1850-
IR_FOLD_COPY(op1);
1851-
} else if (op1_insn->val.u64 == 1) {
1852-
IR_FOLD_COPY(op2);
1853-
} else if (op1_insn->val.u64 == 2 && IR_OPT_TYPE(opt) != IR_ADDR) {
1854-
opt = IR_ADD | (opt & IR_OPT_TYPE_MASK);
1855-
op1 = op2;
1856-
IR_FOLD_RESTART;
1857-
}
1858-
IR_FOLD_NEXT;
1859-
}
1860-
1861-
IR_FOLD(MUL(C_I8, _))
1862-
IR_FOLD(MUL(C_I16, _))
1863-
IR_FOLD(MUL(C_I32, _))
1864-
IR_FOLD(MUL(C_I64, _))
1865-
{
1866-
if (op1_insn->val.i64 == 0) {
1867-
/* 0 * a => 0 */
1868-
IR_FOLD_COPY(op1);
1869-
} else if (op1_insn->val.i64 == 1) {
1870-
/* 1 * a => a */
1871-
IR_FOLD_COPY(op2);
1872-
} else if (op1_insn->val.i64 == 2) {
1873-
/* 2 * a => a + a */
1874-
opt = IR_ADD | (opt & IR_OPT_TYPE_MASK);
1875-
op1 = op2;
1876-
IR_FOLD_RESTART;
1877-
} else if (op1_insn->val.i64 == -1) {
1878-
/* -1 * a => -a */
1879-
opt = IR_NEG | (opt & IR_OPT_TYPE_MASK);
1880-
op1 = op2;
1881-
op2 = IR_UNUSED;
1882-
IR_FOLD_RESTART;
1883-
}
1884-
IR_FOLD_NEXT;
1885-
}
1886-
18871816
IR_FOLD(MUL(_, C_DOUBLE))
18881817
{
18891818
if (op2_insn->val.d == 1.0) {
@@ -2481,6 +2410,50 @@ IR_FOLD(TRUNC(AND))
24812410
IR_FOLD_NEXT;
24822411
}
24832412

2413+
IR_FOLD(AND(SHR, C_I8))
2414+
IR_FOLD(AND(SHR, C_U8))
2415+
{
2416+
if (IR_IS_CONST_REF(op1_insn->op2)) {
2417+
if (((uint8_t)-1) >> ctx->ir_base[op1_insn->op2].val.u8 == op2_insn->val.u8) {
2418+
IR_FOLD_COPY(op1);
2419+
}
2420+
}
2421+
IR_FOLD_NEXT;
2422+
}
2423+
2424+
IR_FOLD(AND(SHR, C_I16))
2425+
IR_FOLD(AND(SHR, C_U16))
2426+
{
2427+
if (IR_IS_CONST_REF(op1_insn->op2)) {
2428+
if (((uint16_t)-1) >> ctx->ir_base[op1_insn->op2].val.u16 == op2_insn->val.u16) {
2429+
IR_FOLD_COPY(op1);
2430+
}
2431+
}
2432+
IR_FOLD_NEXT;
2433+
}
2434+
2435+
IR_FOLD(AND(SHR, C_I32))
2436+
IR_FOLD(AND(SHR, C_U32))
2437+
{
2438+
if (IR_IS_CONST_REF(op1_insn->op2)) {
2439+
if (((uint32_t)-1) >> ctx->ir_base[op1_insn->op2].val.u32 == op2_insn->val.u32) {
2440+
IR_FOLD_COPY(op1);
2441+
}
2442+
}
2443+
IR_FOLD_NEXT;
2444+
}
2445+
2446+
IR_FOLD(AND(SHR, C_I64))
2447+
IR_FOLD(AND(SHR, C_U64))
2448+
{
2449+
if (IR_IS_CONST_REF(op1_insn->op2)) {
2450+
if (((uint64_t)-1) >> ctx->ir_base[op1_insn->op2].val.u64 == op2_insn->val.u64) {
2451+
IR_FOLD_COPY(op1);
2452+
}
2453+
}
2454+
IR_FOLD_NEXT;
2455+
}
2456+
24842457
IR_FOLD(EQ(FP2FP, C_DOUBLE))
24852458
IR_FOLD(NE(FP2FP, C_DOUBLE))
24862459
IR_FOLD(LT(FP2FP, C_DOUBLE))
@@ -2865,6 +2838,46 @@ IR_FOLD(XOR(XOR, _))
28652838
IR_FOLD_NEXT;
28662839
}
28672840

2841+
/* ROL/ROR */
2842+
IR_FOLD(OR(SHL, SHR))
2843+
IR_FOLD(OR(SHR, SHL))
2844+
IR_FOLD(ADD(SHL, SHR))
2845+
IR_FOLD(ADD(SHR, SHL))
2846+
{
2847+
if (op1_insn->op1 == op2_insn->op1) {
2848+
if (IR_IS_CONST_REF(op1_insn->op2) && IR_IS_CONST_REF(op2_insn->op2)) {
2849+
if (ctx->ir_base[op1_insn->op2].val.u64 + ctx->ir_base[op2_insn->op2].val.u64 ==
2850+
ir_type_size[IR_OPT_TYPE(opt)] * 8) {
2851+
/* (x << c) | (x >> (32 - c)) -> ROL(x, c) */
2852+
op1 = op1_insn->op1;
2853+
op2 = op1_insn->op2;
2854+
opt = op1_insn->opt + 3; /* SHL -> ROL, SHR -> ROR */
2855+
IR_FOLD_RESTART;
2856+
}
2857+
} else if (ctx->ir_base[op2_insn->op2].op == IR_SUB
2858+
&& IR_IS_CONST_REF(ctx->ir_base[op2_insn->op2].op1)
2859+
&& ctx->ir_base[op2_insn->op2].op2 == op1_insn->op2
2860+
&& ctx->ir_base[ctx->ir_base[op2_insn->op2].op1].val.u64 == ir_type_size[IR_OPT_TYPE(opt)] * 8) {
2861+
/* (x << y) | (x >> (32 - y)) -> ROL(x, y) */
2862+
op1 = op1_insn->op1;
2863+
op2 = op1_insn->op2;
2864+
opt = op1_insn->opt + 3; /* SHL -> ROL, SHR -> ROR */
2865+
IR_FOLD_RESTART;
2866+
} else if (ctx->ir_base[op1_insn->op2].op == IR_SUB
2867+
&& IR_IS_CONST_REF(ctx->ir_base[op1_insn->op2].op1)
2868+
&& ctx->ir_base[op1_insn->op2].op2 == op2_insn->op2
2869+
&& ctx->ir_base[ctx->ir_base[op1_insn->op2].op1].val.u64 == ir_type_size[IR_OPT_TYPE(opt)] * 8) {
2870+
/* (x << (32 - y)) | (x >> y) -> ROR(x, y) */
2871+
op1 = op2_insn->op1;
2872+
op2 = op2_insn->op2;
2873+
opt = op2_insn->opt + 3; /* SHL -> ROL, SHR -> ROR */
2874+
IR_FOLD_RESTART;
2875+
}
2876+
}
2877+
IR_FOLD_NEXT;
2878+
}
2879+
2880+
28682881
/* Swap operands (move lower ref to op2) for better CSE */
28692882
IR_FOLD(ADD(_, _))
28702883
IR_FOLD(MUL(_, _))

ext/opcache/jit/ir/ir_gcm.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -391,6 +391,13 @@ static bool ir_split_partially_dead_node(ir_ctx *ctx, ir_ref ref, uint32_t b)
391391
n = ctx->use_lists[ref].refs;
392392
for (i = 0; i < clones_count; i++) {
393393
clone = clones[i].ref;
394+
if (clones[i].use_count == 1) {
395+
/* TOTALLY_USEFUL block may be a head of a diamond above the real usage.
396+
* Sink it down to the real usage block.
397+
* Clones with few uses we be sunk into the LCA block.
398+
*/
399+
clones[i].block = uses[clones[i].use].block;
400+
}
394401
ctx->cfg_map[clone] = clones[i].block;
395402
ctx->use_lists[clone].count = clones[i].use_count;
396403
ctx->use_lists[clone].refs = n;
@@ -405,19 +412,29 @@ static bool ir_split_partially_dead_node(ir_ctx *ctx, ir_ref ref, uint32_t b)
405412
ir_insn *insn = &ctx->ir_base[use];
406413
ir_ref k, l = insn->inputs_count;
407414

408-
for (k = 1; k <= l; k++) {
409-
if (ir_insn_op(insn, k) == ref) {
410-
if (insn->op == IR_PHI) {
415+
if (insn->op == IR_PHI) {
416+
for (k = 1; k <= l; k++) {
417+
if (ir_insn_op(insn, k) == ref) {
411418
j = ctx->cfg_map[ir_insn_op(&ctx->ir_base[insn->op1], k - 1)];
412-
while (ir_sparse_set_in(&data->totally_useful, ctx->cfg_blocks[j].idom)) {
413-
j = ctx->cfg_blocks[j].idom;
414-
}
415419
if (j != clones[i].block) {
416-
continue;
420+
uint32_t dom_depth = ctx->cfg_blocks[clones[i].block].dom_depth;
421+
while (ctx->cfg_blocks[j].dom_depth > dom_depth) {
422+
j = ctx->cfg_blocks[j].dom_parent;
423+
}
424+
if (j != clones[i].block) {
425+
continue;
426+
}
417427
}
428+
ir_insn_set_op(insn, k, clone);
429+
break;
430+
}
431+
}
432+
} else {
433+
for (k = 1; k <= l; k++) {
434+
if (ir_insn_op(insn, k) == ref) {
435+
ir_insn_set_op(insn, k, clone);
436+
break;
418437
}
419-
ir_insn_set_op(insn, k, clone);
420-
break;
421438
}
422439
}
423440
}

0 commit comments

Comments
 (0)