Skip to content

Commit 6a01549

Browse files
committed
Merge branch 'PHP-8.4'
* PHP-8.4: Update IR
2 parents fb2443a + 33c12e0 commit 6a01549

File tree

8 files changed

+170
-43
lines changed

8 files changed

+170
-43
lines changed

ext/opcache/jit/ir/ir.c

+9-2
Original file line numberDiff line numberDiff line change
@@ -330,6 +330,7 @@ static ir_ref ir_next_const(ir_ctx *ctx)
330330

331331
static void ir_grow_top(ir_ctx *ctx)
332332
{
333+
ir_ref old_insns_limit = ctx->insns_limit;
333334
ir_insn *buf = ctx->ir_base - ctx->consts_limit;
334335

335336
if (ctx->insns_limit < 1024 * 4) {
@@ -341,6 +342,12 @@ static void ir_grow_top(ir_ctx *ctx)
341342
}
342343
buf = ir_mem_realloc(buf, (ctx->consts_limit + ctx->insns_limit) * sizeof(ir_insn));
343344
ctx->ir_base = buf + ctx->consts_limit;
345+
346+
if (ctx->use_lists) {
347+
ctx->use_lists = ir_mem_realloc(ctx->use_lists, ctx->insns_limit * sizeof(ir_use_list));
348+
memset(ctx->use_lists + old_insns_limit, 0,
349+
(ctx->insns_limit - old_insns_limit) * sizeof(ir_use_list));
350+
}
344351
}
345352

346353
static ir_ref ir_next_insn(ir_ctx *ctx)
@@ -1152,7 +1159,7 @@ void ir_build_def_use_lists(ir_ctx *ctx)
11521159
ir_ref n, i, j, *p, def;
11531160
ir_insn *insn;
11541161
uint32_t edges_count;
1155-
ir_use_list *lists = ir_mem_calloc(ctx->insns_count, sizeof(ir_use_list));
1162+
ir_use_list *lists = ir_mem_calloc(ctx->insns_limit, sizeof(ir_use_list));
11561163
ir_ref *edges;
11571164
ir_use_list *use_list;
11581165

@@ -1207,7 +1214,7 @@ void ir_build_def_use_lists(ir_ctx *ctx)
12071214
ir_ref n, i, j, *p, def;
12081215
ir_insn *insn;
12091216
size_t linked_lists_size, linked_lists_top = 0, edges_count = 0;
1210-
ir_use_list *lists = ir_mem_calloc(ctx->insns_count, sizeof(ir_use_list));
1217+
ir_use_list *lists = ir_mem_calloc(ctx->insns_limit, sizeof(ir_use_list));
12111218
ir_ref *edges;
12121219
ir_use_list *use_list;
12131220
ir_ref *linked_lists;

ext/opcache/jit/ir/ir.h

+31-13
Original file line numberDiff line numberDiff line change
@@ -528,11 +528,12 @@ void ir_strtab_free(ir_strtab *strtab);
528528
#define IR_OPT_INLINE (1<<16)
529529
#define IR_OPT_FOLDING (1<<17)
530530
#define IR_OPT_CFG (1<<18) /* merge BBs, by remove END->BEGIN nodes during CFG construction */
531-
#define IR_OPT_CODEGEN (1<<19)
532-
#define IR_GEN_NATIVE (1<<20)
533-
#define IR_GEN_CODE (1<<21) /* C or LLVM */
531+
#define IR_OPT_MEM2SSA (1<<19)
532+
#define IR_OPT_CODEGEN (1<<20)
533+
#define IR_GEN_NATIVE (1<<21)
534+
#define IR_GEN_CODE (1<<22) /* C or LLVM */
534535

535-
#define IR_GEN_CACHE_DEMOTE (1<<22) /* Demote the generated code from closest CPU caches */
536+
#define IR_GEN_CACHE_DEMOTE (1<<23) /* Demote the generated code from closest CPU caches */
536537

537538
/* debug related */
538539
#ifdef IR_DEBUG
@@ -751,13 +752,15 @@ ir_ref ir_binding_find(const ir_ctx *ctx, ir_ref ref);
751752
/* Def -> Use lists */
752753
void ir_build_def_use_lists(ir_ctx *ctx);
753754

755+
/* SSA Construction */
756+
int ir_mem2ssa(ir_ctx *ctx);
757+
754758
/* CFG - Control Flow Graph (implementation in ir_cfg.c) */
755759
int ir_build_cfg(ir_ctx *ctx);
756-
int ir_remove_unreachable_blocks(ir_ctx *ctx);
757760
int ir_build_dominators_tree(ir_ctx *ctx);
758761
int ir_find_loops(ir_ctx *ctx);
759762
int ir_schedule_blocks(ir_ctx *ctx);
760-
void ir_build_prev_refs(ir_ctx *ctx);
763+
void ir_reset_cfg(ir_ctx *ctx);
761764

762765
/* SCCP - Sparse Conditional Constant Propagation (implementation in ir_sccp.c) */
763766
int ir_sccp(ir_ctx *ctx);
@@ -929,7 +932,7 @@ IR_ALWAYS_INLINE void *ir_jit_compile(ir_ctx *ctx, int opt_level, size_t *size)
929932
}
930933

931934
return ir_emit_code(ctx, size);
932-
} else if (opt_level == 1 || opt_level == 2) {
935+
} else if (opt_level > 0) {
933936
if (!(ctx->flags & IR_OPT_FOLDING)) {
934937
// IR_ASSERT(0 && "IR_OPT_FOLDING must be set in ir_init() for -O1 and -O2");
935938
return NULL;
@@ -938,14 +941,29 @@ IR_ALWAYS_INLINE void *ir_jit_compile(ir_ctx *ctx, int opt_level, size_t *size)
938941

939942
ir_build_def_use_lists(ctx);
940943

941-
if (opt_level == 2
942-
&& !ir_sccp(ctx)) {
943-
return NULL;
944+
if (ctx->flags & IR_OPT_MEM2SSA) {
945+
if (!ir_build_cfg(ctx)
946+
|| !ir_build_dominators_tree(ctx)
947+
|| !ir_mem2ssa(ctx)) {
948+
return NULL;
949+
}
944950
}
945951

946-
if (!ir_build_cfg(ctx)
947-
|| !ir_build_dominators_tree(ctx)
948-
|| !ir_find_loops(ctx)
952+
if (opt_level > 1) {
953+
ir_reset_cfg(ctx);
954+
if (!ir_sccp(ctx)) {
955+
return NULL;
956+
}
957+
}
958+
959+
if (!ctx->cfg_blocks) {
960+
if (!ir_build_cfg(ctx)
961+
|| !ir_build_dominators_tree(ctx)) {
962+
return NULL;
963+
}
964+
}
965+
966+
if (!ir_find_loops(ctx)
949967
|| !ir_gcm(ctx)
950968
|| !ir_schedule(ctx)
951969
|| !ir_match(ctx)

ext/opcache/jit/ir/ir_aarch64.dasc

+5-2
Original file line numberDiff line numberDiff line change
@@ -1095,6 +1095,8 @@ binop_fp:
10951095
}
10961096
}
10971097
return IR_SKIPPED | IR_NOP;
1098+
case IR_NOP:
1099+
return IR_SKIPPED | IR_NOP;
10981100
default:
10991101
break;
11001102
}
@@ -5603,7 +5605,8 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx)
56035605
} else if (def_flags & IR_USE_MUST_BE_IN_REG) {
56045606
if (insn->op == IR_VLOAD
56055607
&& ctx->live_intervals[ctx->vregs[i]]
5606-
&& ctx->live_intervals[ctx->vregs[i]]->stack_spill_pos != -1) {
5608+
&& ctx->live_intervals[ctx->vregs[i]]->stack_spill_pos != -1
5609+
&& ir_is_same_mem_var(ctx, i, ctx->ir_base[insn->op2].op3)) {
56075610
/* pass */
56085611
} else if (insn->op != IR_PARAM) {
56095612
reg = ir_get_free_reg(insn->type, available);
@@ -5704,7 +5707,7 @@ static void ir_allocate_unique_spill_slots(ir_ctx *ctx)
57045707
if (reg != IR_REG_NONE && IR_REGSET_IN(available, reg)) {
57055708
IR_REGSET_EXCL(available, reg);
57065709
ctx->regs[i][j] = reg | IR_REG_SPILL_LOAD;
5707-
} else if (j > 1 && input == insn->op1 && ctx->regs[i][1] != IR_REG_NONE) {
5710+
} else if (IR_IS_FOLDABLE_OP(insn->op) && j > 1 && input == insn->op1 && ctx->regs[i][1] != IR_REG_NONE) {
57085711
ctx->regs[i][j] = ctx->regs[i][1];
57095712
} else if (use_flags & IR_USE_MUST_BE_IN_REG) {
57105713
reg = ir_get_free_reg(ctx->ir_base[input].type, available);

ext/opcache/jit/ir/ir_cfg.c

+36-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
#include "ir.h"
99
#include "ir_private.h"
1010

11+
static int ir_remove_unreachable_blocks(ir_ctx *ctx);
12+
1113
IR_ALWAYS_INLINE void _ir_add_successors(const ir_ctx *ctx, ir_ref ref, ir_worklist *worklist)
1214
{
1315
ir_use_list *use_list = &ctx->use_lists[ref];
@@ -57,6 +59,24 @@ IR_ALWAYS_INLINE void _ir_add_predecessors(const ir_insn *insn, ir_worklist *wor
5759
}
5860
}
5961

62+
void ir_reset_cfg(ir_ctx *ctx)
63+
{
64+
ctx->cfg_blocks_count = 0;
65+
ctx->cfg_edges_count = 0;
66+
if (ctx->cfg_blocks) {
67+
ir_mem_free(ctx->cfg_blocks);
68+
ctx->cfg_blocks = NULL;
69+
if (ctx->cfg_edges) {
70+
ir_mem_free(ctx->cfg_edges);
71+
ctx->cfg_edges = NULL;
72+
}
73+
if (ctx->cfg_map) {
74+
ir_mem_free(ctx->cfg_map);
75+
ctx->cfg_map = NULL;
76+
}
77+
}
78+
}
79+
6080
int ir_build_cfg(ir_ctx *ctx)
6181
{
6282
ir_ref n, *p, ref, start, end;
@@ -330,11 +350,15 @@ static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from)
330350
}
331351
}
332352
i--;
353+
for (j = i + 1; j <= n; j++) {
354+
ir_insn_set_op(insn, j, IR_UNUSED);
355+
}
333356
if (i == 1) {
334357
insn->op = IR_BEGIN;
335358
insn->inputs_count = 1;
336359
use_list = &ctx->use_lists[merge];
337360
if (use_list->count > 1) {
361+
n++;
338362
for (k = 0, p = &ctx->use_edges[use_list->refs]; k < use_list->count; k++, p++) {
339363
use = *p;
340364
use_insn = &ctx->ir_base[use];
@@ -347,22 +371,24 @@ static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from)
347371
if (ir_bitset_in(life_inputs, j - 1)) {
348372
use_insn->op1 = ir_insn_op(use_insn, j);
349373
} else if (input > 0) {
350-
ir_use_list_remove_all(ctx, input, use);
374+
ir_use_list_remove_one(ctx, input, use);
351375
}
352376
}
353377
use_insn->op = IR_COPY;
354-
use_insn->op2 = IR_UNUSED;
355-
use_insn->op3 = IR_UNUSED;
378+
use_insn->inputs_count = 1;
379+
for (j = 2; j <= n; j++) {
380+
ir_insn_set_op(use_insn, j, IR_UNUSED);
381+
}
356382
ir_use_list_remove_all(ctx, merge, use);
357383
}
358384
}
359385
}
360386
} else {
361387
insn->inputs_count = i;
362388

363-
n++;
364389
use_list = &ctx->use_lists[merge];
365390
if (use_list->count > 1) {
391+
n++;
366392
for (k = 0, p = &ctx->use_edges[use_list->refs]; k < use_list->count; k++, p++) {
367393
use = *p;
368394
use_insn = &ctx->ir_base[use];
@@ -378,9 +404,13 @@ static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from)
378404
}
379405
i++;
380406
} else if (input > 0) {
381-
ir_use_list_remove_all(ctx, input, use);
407+
ir_use_list_remove_one(ctx, input, use);
382408
}
383409
}
410+
use_insn->inputs_count = i - 1;
411+
for (j = i; j <= n; j++) {
412+
ir_insn_set_op(use_insn, j, IR_UNUSED);
413+
}
384414
}
385415
}
386416
}
@@ -390,7 +420,7 @@ static void ir_remove_merge_input(ir_ctx *ctx, ir_ref merge, ir_ref from)
390420
}
391421

392422
/* CFG constructed after SCCP pass doesn't have unreachable BBs, otherwise they should be removed */
393-
int ir_remove_unreachable_blocks(ir_ctx *ctx)
423+
static int ir_remove_unreachable_blocks(ir_ctx *ctx)
394424
{
395425
uint32_t b, *p, i;
396426
uint32_t unreachable_count = 0;

ext/opcache/jit/ir/ir_check.c

+4
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,10 @@ bool ir_check(const ir_ctx *ctx)
362362
break;
363363
}
364364
}
365+
if (count == 0 && (insn->op == IR_END || insn->op == IR_LOOP_END)) {
366+
/* Dead block */
367+
break;
368+
}
365369
fprintf(stderr, "ir_base[%d].op (%s) must have 1 successor (%d)\n",
366370
i, ir_op_name[insn->op], count);
367371
ok = 0;

ext/opcache/jit/ir/ir_gcm.c

+8-5
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,11 @@ static bool ir_split_partially_dead_node(ir_ctx *ctx, ir_ref ref, uint32_t b)
356356
}
357357
} else {
358358
j = i = ctx->cfg_map[use];
359-
IR_ASSERT(i > 0);
360-
while (ir_sparse_set_in(&data->totally_useful, ctx->cfg_blocks[j].idom)) {
361-
j = ctx->cfg_blocks[j].idom;
359+
if (i) {
360+
IR_ASSERT(i > 0);
361+
while (ir_sparse_set_in(&data->totally_useful, ctx->cfg_blocks[j].idom)) {
362+
j = ctx->cfg_blocks[j].idom;
363+
}
362364
}
363365
clone = ir_hashtab_find(&hash, j);
364366
if (clone == IR_INVALID_VAL) {
@@ -941,8 +943,9 @@ int ir_schedule(ir_ctx *ctx)
941943

942944
for (p = &ctx->use_edges[use_list->refs]; count > 0; p++, count--) {
943945
ir_ref use = *p;
944-
if (!_xlat[use]) {
945-
ir_insn *use_insn = &ctx->ir_base[use];
946+
ir_insn *use_insn = &ctx->ir_base[use];
947+
if (!_xlat[use] && (_blocks[use] || use_insn->op == IR_PARAM)) {
948+
IR_ASSERT(_blocks[use] == b || use_insn->op == IR_PARAM);
946949
if (use_insn->op == IR_PARAM
947950
|| use_insn->op == IR_VAR
948951
|| use_insn->op == IR_PI

ext/opcache/jit/ir/ir_private.h

+1
Original file line numberDiff line numberDiff line change
@@ -1120,6 +1120,7 @@ struct _ir_block {
11201120
uint32_t loop_depth;
11211121
};
11221122

1123+
void ir_build_prev_refs(ir_ctx *ctx);
11231124
uint32_t ir_skip_empty_target_blocks(const ir_ctx *ctx, uint32_t b);
11241125
uint32_t ir_next_block(const ir_ctx *ctx, uint32_t b);
11251126
void ir_get_true_false_blocks(const ir_ctx *ctx, uint32_t b, uint32_t *true_block, uint32_t *false_block);

0 commit comments

Comments
 (0)