Skip to content

Commit 5c05e6c

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: Update IR
2 parents c10f5ce + 6fca900 commit 5c05e6c

File tree

5 files changed

+152
-23
lines changed

5 files changed

+152
-23
lines changed

ext/opcache/jit/ir/ir.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1110,11 +1110,13 @@ ir_ref ir_get_op(ir_ctx *ctx, ir_ref ref, int32_t n)
11101110

11111111
ir_ref ir_param(ir_ctx *ctx, ir_type type, ir_ref region, const char *name, int pos)
11121112
{
1113+
IR_ASSERT(ctx->ir_base[region].op == IR_START);
11131114
return ir_emit(ctx, IR_OPT(IR_PARAM, type), region, ir_str(ctx, name), pos);
11141115
}
11151116

11161117
ir_ref ir_var(ir_ctx *ctx, ir_type type, ir_ref region, const char *name)
11171118
{
1119+
IR_ASSERT(IR_IS_BB_START(ctx->ir_base[region].op));
11181120
return ir_emit(ctx, IR_OPT(IR_VAR, type), region, ir_str(ctx, name), IR_UNUSED);
11191121
}
11201122

@@ -1963,7 +1965,7 @@ ir_ref _ir_VAR(ir_ctx *ctx, ir_type type, const char* name)
19631965
ir_ref ref = ctx->control;
19641966

19651967
while (1) {
1966-
IR_ASSERT(ctx->control);
1968+
IR_ASSERT(ref);
19671969
if (IR_IS_BB_START(ctx->ir_base[ref].op)) {
19681970
break;
19691971
}

ext/opcache/jit/ir/ir_aarch64.dasc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3731,6 +3731,10 @@ static void ir_emit_vload(ir_ctx *ctx, ir_ref def, ir_insn *insn)
37313731
int32_t offset;
37323732
ir_mem mem;
37333733

3734+
if (ctx->use_lists[def].count == 1) {
3735+
/* dead load */
3736+
return;
3737+
}
37343738
IR_ASSERT(var_insn->op == IR_VAR);
37353739
fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER;
37363740
offset = IR_SPILL_POS_TO_OFFSET(var_insn->op3);
@@ -4128,6 +4132,10 @@ static void ir_emit_block_begin(ir_ctx *ctx, ir_ref def, ir_insn *insn)
41284132
dasm_State **Dst = &data->dasm_state;
41294133
ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]);
41304134

4135+
if (ctx->use_lists[def].count == 1) {
4136+
/* dead load */
4137+
return;
4138+
}
41314139
| mov Rx(def_reg), sp
41324140

41334141
if (IR_REG_SPILLED(ctx->regs[def][0])) {

ext/opcache/jit/ir/ir_gcm.c

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -890,9 +890,11 @@ int ir_schedule(ir_ctx *ctx)
890890

891891
/* Topological sort according dependencies inside each basic block */
892892
for (b = 1, bb = ctx->cfg_blocks + 1; b <= ctx->cfg_blocks_count; b++, bb++) {
893+
ir_ref start;
894+
893895
IR_ASSERT(!(bb->flags & IR_BB_UNREACHABLE));
894896
/* Schedule BB start */
895-
i = bb->start;
897+
start = i = bb->start;
896898
_xlat[i] = bb->start = insns_count;
897899
insn = &ctx->ir_base[i];
898900
if (insn->op == IR_CASE_VAL) {
@@ -904,12 +906,15 @@ int ir_schedule(ir_ctx *ctx)
904906
i = _next[i];
905907
insn = &ctx->ir_base[i];
906908
if (bb->flags & (IR_BB_HAS_PHI|IR_BB_HAS_PI|IR_BB_HAS_PARAM|IR_BB_HAS_VAR)) {
909+
int count = 0;
910+
907911
/* Schedule PARAM, VAR, PI */
908912
while (insn->op == IR_PARAM || insn->op == IR_VAR || insn->op == IR_PI) {
909913
_xlat[i] = insns_count;
910914
insns_count += 1;
911915
i = _next[i];
912916
insn = &ctx->ir_base[i];
917+
count++;
913918
}
914919
/* Schedule PHIs */
915920
while (insn->op == IR_PHI) {
@@ -926,6 +931,52 @@ int ir_schedule(ir_ctx *ctx)
926931
}
927932
i = _next[i];
928933
insn = &ctx->ir_base[i];
934+
count++;
935+
}
936+
/* Schedule remaining PHIs */
937+
if (UNEXPECTED(count < ctx->use_lists[start].count - 1)) {
938+
ir_use_list *use_list = &ctx->use_lists[start];
939+
ir_ref *p, count = use_list->count;
940+
ir_ref phis = _prev[i];
941+
942+
for (p = &ctx->use_edges[use_list->refs]; count > 0; p++, count--) {
943+
ir_ref use = *p;
944+
if (!_xlat[use]) {
945+
ir_insn *use_insn = &ctx->ir_base[use];
946+
if (use_insn->op == IR_PARAM
947+
|| use_insn->op == IR_VAR
948+
|| use_insn->op == IR_PI
949+
|| use_insn->op == IR_PHI) {
950+
if (_prev[use] != phis) {
951+
/* remove "use" */
952+
_prev[_next[use]] = _prev[use];
953+
_next[_prev[use]] = _next[use];
954+
/* insert "use" after "phis" */
955+
_prev[use] = phis;
956+
_next[use] = _next[phis];
957+
_prev[_next[phis]] = use;
958+
_next[phis] = use;
959+
}
960+
phis = use;
961+
_xlat[use] = insns_count;
962+
if (use_insn->op == IR_PHI) {
963+
ir_ref *q;
964+
/* Reuse "n" from MERGE and skip first input */
965+
insns_count += ir_insn_inputs_to_len(n + 1);
966+
for (j = n, q = use_insn->ops + 2; j > 0; q++, j--) {
967+
ir_ref input = *q;
968+
if (input < IR_TRUE) {
969+
consts_count += ir_count_constant(_xlat, input);
970+
}
971+
}
972+
} else {
973+
insns_count += 1;
974+
}
975+
}
976+
}
977+
}
978+
i = _next[phis];
979+
insn = &ctx->ir_base[i];
929980
}
930981
}
931982
if (bb->successors_count > 1) {

ext/opcache/jit/ir/ir_sccp.c

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ static bool ir_is_dead_load_ex(ir_ctx *ctx, ir_ref ref, uint32_t flags, ir_insn
255255
{
256256
if ((flags & (IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_MASK)) == (IR_OP_FLAG_MEM|IR_OP_FLAG_MEM_LOAD)) {
257257
return ctx->use_lists[ref].count == 1;
258-
} else if (insn->op == IR_ALLOCA) {
258+
} else if (insn->op == IR_ALLOCA || insn->op == IR_BLOCK_BEGIN) {
259259
return ctx->use_lists[ref].count == 1;
260260
}
261261
return 0;
@@ -644,8 +644,13 @@ static void ir_sccp_remove_unfeasible_merge_inputs(ir_ctx *ctx, ir_insn *_values
644644
next_insn = use_insn;
645645
} else if (use_insn->op != IR_NOP) {
646646
IR_ASSERT(use_insn->op1 == ref);
647-
use_insn->op1 = prev;
648-
ir_use_list_add(ctx, prev, use);
647+
IR_ASSERT(use_insn->op == IR_VAR);
648+
ir_ref region = prev;
649+
while (!IR_IS_BB_START(ctx->ir_base[region].op)) {
650+
region = ctx->ir_base[region].op1;
651+
}
652+
use_insn->op1 = region;
653+
ir_use_list_add(ctx, region, use);
649654
p = &ctx->use_edges[use_list->refs + k];
650655
}
651656
}
@@ -1240,6 +1245,22 @@ static void ir_merge_blocks(ir_ctx *ctx, ir_ref end, ir_ref begin, ir_bitqueue *
12401245
}
12411246
}
12421247

1248+
static void ir_remove_unused_vars(ir_ctx *ctx, ir_ref start, ir_ref end)
1249+
{
1250+
ir_use_list *use_list = &ctx->use_lists[start];
1251+
ir_ref *p, use, n = use_list->count;
1252+
1253+
for (p = &ctx->use_edges[use_list->refs]; n > 0; p++, n--) {
1254+
use = *p;
1255+
if (use != end) {
1256+
ir_insn *use_insn = &ctx->ir_base[use];
1257+
IR_ASSERT(use_insn->op == IR_VAR);
1258+
IR_ASSERT(ctx->use_lists[use].count == 0);
1259+
MAKE_NOP(use_insn);
1260+
}
1261+
}
1262+
}
1263+
12431264
static bool ir_try_remove_empty_diamond(ir_ctx *ctx, ir_ref ref, ir_insn *insn, ir_bitqueue *worklist)
12441265
{
12451266
if (insn->inputs_count == 2) {
@@ -1289,8 +1310,12 @@ static bool ir_try_remove_empty_diamond(ir_ctx *ctx, ir_ref ref, ir_insn *insn,
12891310
ir_ref next_ref = ctx->use_edges[ctx->use_lists[ref].refs];
12901311
ir_insn *next = &ctx->ir_base[next_ref];
12911312

1292-
IR_ASSERT(ctx->use_lists[start1_ref].count == 1);
1293-
IR_ASSERT(ctx->use_lists[start2_ref].count == 1);
1313+
if (ctx->use_lists[start1_ref].count != 1) {
1314+
ir_remove_unused_vars(ctx, start1_ref, end1_ref);
1315+
}
1316+
if (ctx->use_lists[start2_ref].count != 1) {
1317+
ir_remove_unused_vars(ctx, start2_ref, end2_ref);
1318+
}
12941319

12951320
next->op1 = root->op1;
12961321
ir_use_list_replace_one(ctx, root->op1, root_ref, next_ref);
@@ -1331,7 +1356,9 @@ static bool ir_try_remove_empty_diamond(ir_ctx *ctx, ir_ref ref, ir_insn *insn,
13311356
if (start->op != IR_CASE_VAL && start->op != IR_CASE_DEFAULT) {
13321357
return 0;
13331358
}
1334-
IR_ASSERT(ctx->use_lists[start_ref].count == 1);
1359+
if (ctx->use_lists[start_ref].count != 1) {
1360+
ir_remove_unused_vars(ctx, start_ref, end_ref);
1361+
}
13351362
if (!root_ref) {
13361363
root_ref = start->op1;
13371364
if (ctx->use_lists[root_ref].count != count) {
@@ -1454,8 +1481,12 @@ static bool ir_optimize_phi(ir_ctx *ctx, ir_ref merge_ref, ir_insn *merge, ir_re
14541481
}
14551482
next = &ctx->ir_base[next_ref];
14561483

1457-
IR_ASSERT(ctx->use_lists[start1_ref].count == 1);
1458-
IR_ASSERT(ctx->use_lists[start2_ref].count == 1);
1484+
if (ctx->use_lists[start1_ref].count != 1) {
1485+
ir_remove_unused_vars(ctx, start1_ref, end1_ref);
1486+
}
1487+
if (ctx->use_lists[start2_ref].count != 1) {
1488+
ir_remove_unused_vars(ctx, start2_ref, end2_ref);
1489+
}
14591490

14601491
insn->op = (
14611492
(is_less ? cond->op1 : cond->op2)
@@ -1540,8 +1571,12 @@ static bool ir_optimize_phi(ir_ctx *ctx, ir_ref merge_ref, ir_insn *merge, ir_re
15401571
}
15411572
next = &ctx->ir_base[next_ref];
15421573

1543-
IR_ASSERT(ctx->use_lists[start1_ref].count == 1);
1544-
IR_ASSERT(ctx->use_lists[start2_ref].count == 1);
1574+
if (ctx->use_lists[start1_ref].count != 1) {
1575+
ir_remove_unused_vars(ctx, start1_ref, end1_ref);
1576+
}
1577+
if (ctx->use_lists[start2_ref].count != 1) {
1578+
ir_remove_unused_vars(ctx, start2_ref, end2_ref);
1579+
}
15451580

15461581
insn->op = IR_ABS;
15471582
insn->inputs_count = 1;
@@ -1605,8 +1640,12 @@ static bool ir_optimize_phi(ir_ctx *ctx, ir_ref merge_ref, ir_insn *merge, ir_re
16051640
}
16061641
next = &ctx->ir_base[next_ref];
16071642

1608-
IR_ASSERT(ctx->use_lists[start1_ref].count == 1);
1609-
IR_ASSERT(ctx->use_lists[start2_ref].count == 1);
1643+
if (ctx->use_lists[start1_ref].count != 1) {
1644+
ir_remove_unused_vars(ctx, start1_ref, end1_ref);
1645+
}
1646+
if (ctx->use_lists[start2_ref].count != 1) {
1647+
ir_remove_unused_vars(ctx, start2_ref, end2_ref);
1648+
}
16101649

16111650
insn->op = IR_COND;
16121651
insn->inputs_count = 3;
@@ -2126,9 +2165,13 @@ static void ir_optimize_merge(ir_ctx *ctx, ir_ref merge_ref, ir_insn *merge, ir_
21262165

21272166
ir_ref next_ref = ctx->use_edges[use_list->refs + 1];
21282167
ir_insn *next = &ctx->ir_base[next_ref];
2129-
IR_ASSERT(next->op != IR_PHI);
21302168

2131-
if (phi->op == IR_PHI) {
2169+
if (next->op == IR_PHI) {
2170+
SWAP_REFS(phi_ref, next_ref);
2171+
SWAP_INSNS(phi, next);
2172+
}
2173+
2174+
if (phi->op == IR_PHI && next->op != IR_PHI) {
21322175
if (next->op == IR_IF && next->op1 == merge_ref && ctx->use_lists[phi_ref].count == 1) {
21332176
if (next->op2 == phi_ref) {
21342177
if (ir_try_split_if(ctx, next_ref, next, worklist)) {

ext/opcache/jit/ir/ir_x86.dasc

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,8 +1149,10 @@ int ir_get_target_constraints(ir_ctx *ctx, ir_ref ref, ir_target_constraints *co
11491149
} else {
11501150
flags = IR_DEF_REUSES_OP1_REG | IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG | IR_OP2_SHOULD_BE_IN_REG;
11511151
}
1152-
if (IR_IS_CONST_REF(insn->op2) && insn->op1 != insn->op2) {
1153-
n = ir_add_const_tmp_reg(ctx, insn->op2, 2, n, constraints);
1152+
if (IR_IS_CONST_REF(insn->op2)) {
1153+
if (insn->op1 != insn->op2) {
1154+
n = ir_add_const_tmp_reg(ctx, insn->op2, 2, n, constraints);
1155+
}
11541156
} else if (ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA) {
11551157
constraints->tmp_regs[n] = IR_TMP_REG(2, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
11561158
n++;
@@ -1223,9 +1225,11 @@ op2_const:
12231225
} else if (ir_rule(ctx, insn->op1) & IR_FUSED) {
12241226
flags = IR_USE_MUST_BE_IN_REG | IR_OP2_MUST_BE_IN_REG;
12251227
}
1226-
if (IR_IS_CONST_REF(insn->op2) && insn->op1 != insn->op2) {
1227-
flags = IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
1228-
n = ir_add_const_tmp_reg(ctx, insn->op2, 2, n, constraints);
1228+
if (IR_IS_CONST_REF(insn->op2)) {
1229+
if (insn->op1 != insn->op2) {
1230+
flags = IR_USE_MUST_BE_IN_REG | IR_OP1_SHOULD_BE_IN_REG;
1231+
n = ir_add_const_tmp_reg(ctx, insn->op2, 2, n, constraints);
1232+
}
12291233
} else if (ir_rule(ctx, insn->op2) == IR_STATIC_ALLOCA) {
12301234
constraints->tmp_regs[n] = IR_TMP_REG(2, IR_ADDR, IR_LOAD_SUB_REF, IR_DEF_SUB_REF);
12311235
n++;
@@ -3360,10 +3364,23 @@ static ir_mem ir_fuse_addr(ir_ctx *ctx, ir_ref root, ir_ref ref)
33603364
offset_insn = insn;
33613365
break;
33623366
case IR_LEA_IB_O:
3363-
base_reg_ref = insn->op1 * sizeof(ir_ref) + 1;
3364-
index_reg_ref = insn->op1 * sizeof(ir_ref) + 2;
3367+
op1_insn = &ctx->ir_base[insn->op1];
33653368
offset_insn = insn;
33663369
scale = 1;
3370+
if (ir_rule(ctx, op1_insn->op2) == IR_STATIC_ALLOCA) {
3371+
offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[op1_insn->op2].op3);
3372+
base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER;
3373+
base_reg_ref = IR_UNUSED;
3374+
index_reg_ref = insn->op1 * sizeof(ir_ref) + 1;
3375+
} else if (ir_rule(ctx, op1_insn->op1) == IR_STATIC_ALLOCA) {
3376+
offset = IR_SPILL_POS_TO_OFFSET(ctx->ir_base[op1_insn->op1].op3);
3377+
base_reg = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER;
3378+
base_reg_ref = IR_UNUSED;
3379+
index_reg_ref = insn->op1 * sizeof(ir_ref) + 2;
3380+
} else {
3381+
base_reg_ref = insn->op1 * sizeof(ir_ref) + 1;
3382+
index_reg_ref = insn->op1 * sizeof(ir_ref) + 2;
3383+
}
33673384
break;
33683385
case IR_LEA_OB_SI:
33693386
index_reg_ref = insn->op2 * sizeof(ir_ref) + 1;
@@ -7463,6 +7480,10 @@ static void ir_emit_vload(ir_ctx *ctx, ir_ref def, ir_insn *insn)
74637480
ir_reg fp;
74647481
ir_mem mem;
74657482

7483+
if (ctx->use_lists[def].count == 1) {
7484+
/* dead load */
7485+
return;
7486+
}
74667487
IR_ASSERT(var_insn->op == IR_VAR);
74677488
fp = (ctx->flags & IR_USE_FRAME_POINTER) ? IR_REG_FRAME_POINTER : IR_REG_STACK_POINTER;
74687489
mem = IR_MEM_BO(fp, IR_SPILL_POS_TO_OFFSET(var_insn->op3));
@@ -7909,6 +7930,10 @@ static void ir_emit_block_begin(ir_ctx *ctx, ir_ref def, ir_insn *insn)
79097930
dasm_State **Dst = &data->dasm_state;
79107931
ir_reg def_reg = IR_REG_NUM(ctx->regs[def][0]);
79117932

7933+
if (ctx->use_lists[def].count == 1) {
7934+
/* dead load */
7935+
return;
7936+
}
79127937
| mov Ra(def_reg), Ra(IR_REG_RSP)
79137938

79147939
if (IR_REG_SPILLED(ctx->regs[def][0])) {

0 commit comments

Comments
 (0)