Skip to content

Commit 9aaa469

Browse files
committed
Update IR
IR commit: d6d7fc489137aab218b04b59d770b497c5ae3832
1 parent 3524702 commit 9aaa469

File tree

3 files changed

+112
-69
lines changed

3 files changed

+112
-69
lines changed

ext/opcache/jit/ir/ir.c

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,6 +1386,11 @@ bool ir_use_list_add(ir_ctx *ctx, ir_ref to, ir_ref ref)
13861386
if (old_size < new_size) {
13871387
/* Reallocate the whole edges buffer (this is inefficient) */
13881388
ctx->use_edges = ir_mem_realloc(ctx->use_edges, new_size);
1389+
} else if (n == ctx->use_edges_count) {
1390+
ctx->use_edges[n] = ref;
1391+
use_list->count++;
1392+
ctx->use_edges_count++;
1393+
return 0;
13891394
}
13901395
memcpy(ctx->use_edges + ctx->use_edges_count, ctx->use_edges + use_list->refs, use_list->count * sizeof(ir_ref));
13911396
use_list->refs = ctx->use_edges_count;
@@ -1416,20 +1421,39 @@ void ir_use_list_sort(ir_ctx *ctx, ir_ref ref)
14161421

14171422
void ir_replace(ir_ctx *ctx, ir_ref ref, ir_ref new_ref)
14181423
{
1419-
int i, j, n, use;
1424+
int i, j, n, *p, use;
14201425
ir_insn *insn;
1426+
ir_use_list *use_list;
14211427

14221428
IR_ASSERT(ref != new_ref);
1423-
n = ctx->use_lists[ref].count;
1424-
for (i = 0; i < n; i++) {
1425-
use = ctx->use_edges[ctx->use_lists[ref].refs + i];
1426-
IR_ASSERT(use != ref);
1427-
insn = &ctx->ir_base[use];
1428-
j = ir_insn_find_op(insn, ref);
1429-
IR_ASSERT(j > 0);
1430-
ir_insn_set_op(insn, j, new_ref);
1431-
if (!IR_IS_CONST_REF(new_ref)) {
1432-
ir_use_list_add(ctx, new_ref, use);
1429+
use_list = &ctx->use_lists[ref];
1430+
n = use_list->count;
1431+
p = ctx->use_edges + use_list->refs;
1432+
1433+
if (new_ref < 0) {
1434+
/* constant or IR_UNUSED */
1435+
for (; n; p++, n--) {
1436+
use = *p;
1437+
IR_ASSERT(use != ref);
1438+
insn = &ctx->ir_base[use];
1439+
j = ir_insn_find_op(insn, ref);
1440+
IR_ASSERT(j > 0);
1441+
ir_insn_set_op(insn, j, new_ref);
1442+
}
1443+
} else {
1444+
for (i = 0; i < n; p++, i++) {
1445+
use = *p;
1446+
IR_ASSERT(use != ref);
1447+
insn = &ctx->ir_base[use];
1448+
j = ir_insn_find_op(insn, ref);
1449+
IR_ASSERT(j > 0);
1450+
ir_insn_set_op(insn, j, new_ref);
1451+
if (ir_use_list_add(ctx, new_ref, use)) {
1452+
/* restore after reallocation */
1453+
use_list = &ctx->use_lists[ref];
1454+
n = use_list->count;
1455+
p = &ctx->use_edges[use_list->refs + i];
1456+
}
14331457
}
14341458
}
14351459
}

ext/opcache/jit/ir/ir_fold.h

Lines changed: 26 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -323,13 +323,14 @@ IR_FOLD(ADD(C_I16, C_I16))
323323
IR_FOLD(ADD(C_I32, C_I32))
324324
{
325325
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type || (sizeof(void*) == 4 && IR_OPT_TYPE(opt) == IR_ADDR));
326-
IR_FOLD_CONST_I(op1_insn->val.i32 + op2_insn->val.i32);
326+
/* Here and below we use "unsigned math" to prevent undefined signed overflow behavior */
327+
IR_FOLD_CONST_I((int32_t)(op1_insn->val.u32 + op2_insn->val.u32));
327328
}
328329

329330
IR_FOLD(ADD(C_I64, C_I64))
330331
{
331332
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type || (sizeof(void*) == 8 && IR_OPT_TYPE(opt) == IR_ADDR));
332-
IR_FOLD_CONST_I(op1_insn->val.i64 + op2_insn->val.i64);
333+
IR_FOLD_CONST_I(op1_insn->val.u64 + op2_insn->val.u64);
333334
}
334335

335336
IR_FOLD(ADD(C_DOUBLE, C_DOUBLE))
@@ -393,13 +394,13 @@ IR_FOLD(SUB(C_I16, C_I16))
393394
IR_FOLD(SUB(C_I32, C_I32))
394395
{
395396
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
396-
IR_FOLD_CONST_I(op1_insn->val.i32 - op2_insn->val.i32);
397+
IR_FOLD_CONST_I((int32_t)(op1_insn->val.u32 - op2_insn->val.u32));
397398
}
398399

399400
IR_FOLD(SUB(C_I64, C_I64))
400401
{
401402
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
402-
IR_FOLD_CONST_I(op1_insn->val.i64 - op2_insn->val.i64);
403+
IR_FOLD_CONST_I(op1_insn->val.u64 - op2_insn->val.u64);
403404
}
404405

405406
IR_FOLD(SUB(C_DOUBLE, C_DOUBLE))
@@ -463,13 +464,13 @@ IR_FOLD(MUL(C_I16, C_I16))
463464
IR_FOLD(MUL(C_I32, C_I32))
464465
{
465466
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
466-
IR_FOLD_CONST_I(op1_insn->val.i32 * op2_insn->val.i32);
467+
IR_FOLD_CONST_I((int32_t)(op1_insn->val.u32 * op2_insn->val.u32));
467468
}
468469

469470
IR_FOLD(MUL(C_I64, C_I64))
470471
{
471472
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
472-
IR_FOLD_CONST_I(op1_insn->val.i64 * op2_insn->val.i64);
473+
IR_FOLD_CONST_I(op1_insn->val.u64 * op2_insn->val.u64);
473474
}
474475

475476
IR_FOLD(MUL(C_DOUBLE, C_DOUBLE))
@@ -556,7 +557,7 @@ IR_FOLD(NEG(C_I32))
556557
IR_FOLD(NEG(C_I64))
557558
{
558559
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
559-
IR_FOLD_CONST_I(-op1_insn->val.i64);
560+
IR_FOLD_CONST_I(-op1_insn->val.u64);
560561
}
561562

562563
IR_FOLD(NEG(C_DOUBLE))
@@ -580,7 +581,7 @@ IR_FOLD(ABS(C_I64))
580581
if (op1_insn->val.i64 >= 0) {
581582
IR_FOLD_COPY(op1);
582583
} else {
583-
IR_FOLD_CONST_I(-op1_insn->val.i64);
584+
IR_FOLD_CONST_I(-op1_insn->val.u64);
584585
}
585586
}
586587

@@ -680,7 +681,7 @@ IR_FOLD(MUL_OV(C_I64, C_I64))
680681
int64_t min = - max - 1;
681682
int64_t res;
682683
IR_ASSERT(IR_OPT_TYPE(opt) == op1_insn->type);
683-
res = op1_insn->val.i64 * op2_insn->val.i64;
684+
res = op1_insn->val.u64 * op2_insn->val.u64;
684685
if (op1_insn->val.i64 != 0 && res / op1_insn->val.i64 != op2_insn->val.i64 && res >= min && res <= max) {
685686
IR_FOLD_NEXT;
686687
}
@@ -2518,7 +2519,7 @@ IR_FOLD(ADD(ADD, C_I64))
25182519
{
25192520
if (IR_IS_CONST_REF(op1_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op)) {
25202521
/* (x + c1) + c2 => x + (c1 + c2) */
2521-
val.i64 = ctx->ir_base[op1_insn->op2].val.i64 + op2_insn->val.i64;
2522+
val.i64 = ctx->ir_base[op1_insn->op2].val.u64 + op2_insn->val.u64;
25222523
op1 = op1_insn->op1;
25232524
op2 = ir_const(ctx, val, IR_OPT_TYPE(opt));
25242525
IR_FOLD_RESTART;
@@ -2556,8 +2557,8 @@ IR_FOLD(ADD(SUB, C_I64))
25562557
{
25572558
if (IR_IS_CONST_REF(op1_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op)) {
25582559
/* (x - c1) + c2 => x + (c2 - c1) */
2559-
val.i64 = op2_insn->val.i64 - ctx->ir_base[op1_insn->op2].val.i64;
2560-
if (val.i64 < 0 && val.i64 - 1 < 0) {
2560+
val.i64 = op2_insn->val.u64 - ctx->ir_base[op1_insn->op2].val.u64;
2561+
if (val.i64 < 0 && val.i64 != INT64_MIN) {
25612562
val.i64 = -val.i64;
25622563
opt++; /* ADD -> SUB */
25632564
}
@@ -2566,7 +2567,7 @@ IR_FOLD(ADD(SUB, C_I64))
25662567
IR_FOLD_RESTART;
25672568
} else if (IR_IS_CONST_REF(op1_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op1].op)) {
25682569
/* (c1 - x) + c2 => (c1 + c2) - x */
2569-
val.i64 = ctx->ir_base[op1_insn->op1].val.i64 + op2_insn->val.i64;
2570+
val.i64 = ctx->ir_base[op1_insn->op1].val.u64 + op2_insn->val.u64;
25702571
opt++; /* ADD -> SUB */
25712572
op2 = op1_insn->op2;
25722573
op1 = ir_const(ctx, val, IR_OPT_TYPE(opt));
@@ -2599,8 +2600,8 @@ IR_FOLD(SUB(ADD, C_I64))
25992600
{
26002601
if (IR_IS_CONST_REF(op1_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op)) {
26012602
/* (x + c1) - c2 => x + (c1 - c2) */
2602-
val.i64 = ctx->ir_base[op1_insn->op2].val.i64 - op2_insn->val.i64;
2603-
if (val.i64 < 0 && val.i64 - 1 < 0) {
2603+
val.i64 = ctx->ir_base[op1_insn->op2].val.u64 - op2_insn->val.u64;
2604+
if (val.i64 < 0 && val.i64 != INT64_MIN) {
26042605
val.i64 = -val.i64;
26052606
} else {
26062607
opt--; /* SUB -> ADD */
@@ -2635,7 +2636,7 @@ IR_FOLD(SUB(C_I64, ADD))
26352636
{
26362637
if (IR_IS_CONST_REF(op2_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op2_insn->op2].op)) {
26372638
/* c1 - (x + c2) => (c1 - c2) - x */
2638-
val.i64 = op1_insn->val.i64 - ctx->ir_base[op2_insn->op2].val.i64;
2639+
val.i64 = op1_insn->val.u64 - ctx->ir_base[op2_insn->op2].val.u64;
26392640
op2 = op2_insn->op1;
26402641
op1 = ir_const(ctx, val, IR_OPT_TYPE(opt));
26412642
IR_FOLD_RESTART;
@@ -2652,7 +2653,7 @@ IR_FOLD(SUB(SUB, C_ADDR))
26522653
if (IR_IS_CONST_REF(op1_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op)) {
26532654
/* (x - c1) - c2 => x - (c1 + c2) */
26542655
val.u64 = ctx->ir_base[op1_insn->op2].val.u64 + op2_insn->val.u64;
2655-
if (val.i64 < 0 && val.i64 - 1 < 0) {
2656+
if (val.i64 < 0 && val.i64 != INT64_MIN) {
26562657
val.i64 = -val.i64;
26572658
opt--; /* SUB -> ADD */
26582659
}
@@ -2676,8 +2677,8 @@ IR_FOLD(SUB(SUB, C_I64))
26762677
{
26772678
if (IR_IS_CONST_REF(op1_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op)) {
26782679
/* (x - c1) - c2 => x - (c1 + c2) */
2679-
val.i64 = ctx->ir_base[op1_insn->op2].val.i64 + op2_insn->val.i64;
2680-
if (val.i64 < 0 && val.i64 - 1 < 0) {
2680+
val.i64 = ctx->ir_base[op1_insn->op2].val.u64 + op2_insn->val.u64;
2681+
if (val.i64 < 0 && val.i64 != INT64_MIN) {
26812682
val.i64 = -val.i64;
26822683
opt--; /* SUB -> ADD */
26832684
}
@@ -2686,7 +2687,7 @@ IR_FOLD(SUB(SUB, C_I64))
26862687
IR_FOLD_RESTART;
26872688
} else if (IR_IS_CONST_REF(op1_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op1].op)) {
26882689
/* (c1 - x) - c2 => (c1 - c2) - x */
2689-
val.i64 = ctx->ir_base[op1_insn->op1].val.i64 - op2_insn->val.i64;
2690+
val.i64 = ctx->ir_base[op1_insn->op1].val.u64 - op2_insn->val.u64;
26902691
op2 = op1_insn->op2;
26912692
op1 = ir_const(ctx, val, IR_OPT_TYPE(opt));
26922693
IR_FOLD_RESTART;
@@ -2709,7 +2710,7 @@ IR_FOLD(SUB(C_ADDR, SUB))
27092710
} else if (IR_IS_CONST_REF(op2_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op2_insn->op1].op)) {
27102711
/* c1 - (c2 - x) => x + (c1 - c2) */
27112712
val.u64 = op1_insn->val.u64 - ctx->ir_base[op2_insn->op1].val.u64;
2712-
if (val.i64 < 0 && val.i64 - 1 < 0) {
2713+
if (val.i64 < 0 && val.i64 != INT64_MIN) {
27132714
val.i64 = -val.i64;
27142715
opt++; /* ADD -> SUB */
27152716
}
@@ -2727,14 +2728,14 @@ IR_FOLD(SUB(C_I64, SUB))
27272728
{
27282729
if (IR_IS_CONST_REF(op2_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op2_insn->op2].op)) {
27292730
/* c1 - (x - c2) => (c1 + c2) - x */
2730-
val.i64 = op1_insn->val.i64 + ctx->ir_base[op2_insn->op2].val.i64;
2731+
val.i64 = op1_insn->val.u64 + ctx->ir_base[op2_insn->op2].val.u64;
27312732
op2 = op2_insn->op1;
27322733
op1 = ir_const(ctx, val, IR_OPT_TYPE(opt));
27332734
IR_FOLD_RESTART;
27342735
} else if (IR_IS_CONST_REF(op2_insn->op1) && !IR_IS_SYM_CONST(ctx->ir_base[op2_insn->op1].op)) {
27352736
/* c1 - (c2 - x) => x + (c1 - c2) */
2736-
val.i64 = op1_insn->val.i64 - ctx->ir_base[op2_insn->op1].val.i64;
2737-
if (val.i64 < 0 && val.i64 - 1 < 0) {
2737+
val.i64 = op1_insn->val.u64 - ctx->ir_base[op2_insn->op1].val.u64;
2738+
if (val.i64 < 0 && val.i64 != INT64_MIN) {
27382739
val.i64 = -val.i64;
27392740
opt++; /* ADD -> SUB */
27402741
}
@@ -2768,7 +2769,7 @@ IR_FOLD(MUL(MUL, C_I64))
27682769
{
27692770
if (IR_IS_CONST_REF(op1_insn->op2) && !IR_IS_SYM_CONST(ctx->ir_base[op1_insn->op2].op)) {
27702771
/* (x * c1) * c2 => x * (c1 * c2) */
2771-
val.i64 = ctx->ir_base[op1_insn->op2].val.i64 * op2_insn->val.i64;
2772+
val.i64 = ctx->ir_base[op1_insn->op2].val.u64 * op2_insn->val.u64;
27722773
op1 = op1_insn->op1;
27732774
op2 = ir_const(ctx, val, IR_OPT_TYPE(opt));
27742775
IR_FOLD_RESTART;

ext/opcache/jit/ir/ir_sccp.c

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ static void ir_sccp_remove_insn2(ir_ctx *ctx, ir_ref ref, ir_bitqueue *worklist)
385385

386386
static void ir_sccp_replace_insn(ir_ctx *ctx, ir_insn *_values, ir_ref ref, ir_ref new_ref, ir_bitqueue *worklist)
387387
{
388-
ir_ref j, n, *p, use, k, l;
388+
ir_ref j, n, *p, use, i;
389389
ir_insn *insn;
390390
ir_use_list *use_list;
391391

@@ -409,40 +409,48 @@ static void ir_sccp_replace_insn(ir_ctx *ctx, ir_insn *_values, ir_ref ref, ir_r
409409

410410
use_list = &ctx->use_lists[ref];
411411
n = use_list->count;
412-
for (j = 0, p = &ctx->use_edges[use_list->refs]; j < n; j++, p++) {
413-
use = *p;
414-
if (IR_IS_FEASIBLE(use)) {
415-
insn = &ctx->ir_base[use];
416-
l = insn->inputs_count;
417-
for (k = 1; k <= l; k++) {
418-
if (ir_insn_op(insn, k) == ref) {
419-
ir_insn_set_op(insn, k, new_ref);
420-
}
412+
p = &ctx->use_edges[use_list->refs];
413+
if (new_ref <= 0) {
414+
/* constant or IR_UNUSED */
415+
for (; n; p++, n--) {
416+
use = *p;
417+
/* we may skip nodes that are going to be removed by SCCP (TOP, CONST and COPY) */
418+
if (_values[use].op > IR_COPY) {
419+
insn = &ctx->ir_base[use];
420+
i = ir_insn_find_op(insn, ref);
421+
if (!i) continue;
422+
IR_ASSERT(i > 0);
423+
ir_insn_set_op(insn, i, new_ref);
424+
/* schedule folding */
425+
ir_bitqueue_add(worklist, use);
421426
}
422-
#if IR_COMBO_COPY_PROPAGATION
423-
if (new_ref > 0 && IR_IS_BOTTOM(use)) {
427+
}
428+
} else {
429+
for (j = 0; j < n; j++, p++) {
430+
use = *p;
431+
/* we may skip nodes that are going to be removed by SCCP (TOP, CONST and COPY) */
432+
if (_values[use].optx == IR_BOTTOM) {
433+
insn = &ctx->ir_base[use];
434+
i = ir_insn_find_op(insn, ref);
435+
IR_ASSERT(i > 0);
436+
ir_insn_set_op(insn, i, new_ref);
424437
if (ir_use_list_add(ctx, new_ref, use)) {
425438
/* restore after reallocation */
426439
use_list = &ctx->use_lists[ref];
427440
n = use_list->count;
428441
p = &ctx->use_edges[use_list->refs + j];
429442
}
430-
}
431-
#endif
432-
/* we may skip nodes that are going to be removed by SCCP (TOP, CONST and COPY) */
433-
if (worklist && _values[use].op > IR_COPY) {
434443
/* schedule folding */
435444
ir_bitqueue_add(worklist, use);
436445
}
437446
}
438447
}
439-
440448
CLEAR_USES(ref);
441449
}
442450

443451
static void ir_sccp_replace_insn2(ir_ctx *ctx, ir_ref ref, ir_ref new_ref, ir_bitqueue *worklist)
444452
{
445-
ir_ref j, n, *p, use, k, l;
453+
ir_ref i, j, n, *p, use;
446454
ir_insn *insn;
447455
ir_use_list *use_list;
448456

@@ -468,29 +476,37 @@ static void ir_sccp_replace_insn2(ir_ctx *ctx, ir_ref ref, ir_ref new_ref, ir_bi
468476

469477
use_list = &ctx->use_lists[ref];
470478
n = use_list->count;
471-
for (j = 0, p = &ctx->use_edges[use_list->refs]; j < n; j++, p++) {
472-
use = *p;
473-
insn = &ctx->ir_base[use];
474-
l = insn->inputs_count;
475-
for (k = 1; k <= l; k++) {
476-
if (ir_insn_op(insn, k) == ref) {
477-
ir_insn_set_op(insn, k, new_ref);
478-
}
479+
p = &ctx->use_edges[use_list->refs];
480+
if (new_ref <= 0) {
481+
/* constant or IR_UNUSED */
482+
for (; n; p++, n--) {
483+
use = *p;
484+
IR_ASSERT(use != ref);
485+
insn = &ctx->ir_base[use];
486+
i = ir_insn_find_op(insn, ref);
487+
IR_ASSERT(i > 0);
488+
ir_insn_set_op(insn, i, new_ref);
489+
/* schedule folding */
490+
ir_bitqueue_add(worklist, use);
479491
}
480-
#if IR_COMBO_COPY_PROPAGATION
481-
if (new_ref > 0) {
492+
} else {
493+
for (j = 0; j < n; j++, p++) {
494+
use = *p;
495+
IR_ASSERT(use != ref);
496+
insn = &ctx->ir_base[use];
497+
i = ir_insn_find_op(insn, ref);
498+
IR_ASSERT(i > 0);
499+
ir_insn_set_op(insn, i, new_ref);
482500
if (ir_use_list_add(ctx, new_ref, use)) {
483501
/* restore after reallocation */
484502
use_list = &ctx->use_lists[ref];
485503
n = use_list->count;
486504
p = &ctx->use_edges[use_list->refs + j];
487505
}
506+
/* schedule folding */
507+
ir_bitqueue_add(worklist, use);
488508
}
489-
#endif
490-
/* schedule folding */
491-
ir_bitqueue_add(worklist, use);
492509
}
493-
494510
CLEAR_USES(ref);
495511
}
496512

@@ -2483,7 +2499,9 @@ int ir_sccp(ir_ctx *ctx)
24832499
} else if (value->op == IR_TOP) {
24842500
/* remove unreachable instruction */
24852501
insn = &ctx->ir_base[i];
2486-
if (ir_op_flags[insn->op] & (IR_OP_FLAG_DATA|IR_OP_FLAG_MEM)) {
2502+
if (insn->op == IR_NOP) {
2503+
/* already removed */
2504+
} else if (ir_op_flags[insn->op] & (IR_OP_FLAG_DATA|IR_OP_FLAG_MEM)) {
24872505
if (insn->op != IR_PARAM && (insn->op != IR_VAR || _values[insn->op1].op == IR_TOP)) {
24882506
ir_sccp_remove_insn(ctx, _values, i, &worklist2);
24892507
}

0 commit comments

Comments
 (0)