Skip to content

Commit 109fb3e

Browse files
committed
Copy optimization for (BINARY_OP/ACCIGN + SEND_VAL)
1 parent b0e7706 commit 109fb3e

File tree

3 files changed

+135
-65
lines changed

3 files changed

+135
-65
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 45 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2299,7 +2299,9 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
22992299
|| !(op2_info & MAY_BE_LONG)) {
23002300
break;
23012301
}
2302-
if (opline->result_type == IS_TMP_VAR
2302+
res_addr = RES_REG_ADDR();
2303+
if (Z_MODE(res_addr) != IS_REG
2304+
&& opline->result_type == IS_TMP_VAR
23032305
&& (i + 1) <= end
23042306
&& (opline+1)->opcode == ZEND_SEND_VAL
23052307
&& (opline+1)->op1_type == IS_TMP_VAR
@@ -2312,7 +2314,6 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
23122314
}
23132315
} else {
23142316
res_use_info = RES_USE_INFO();
2315-
res_addr = RES_REG_ADDR();
23162317
}
23172318
if (!zend_jit_long_math(&dasm_state, opline,
23182319
op1_info, OP1_RANGE(), OP1_REG_ADDR(),
@@ -2337,16 +2338,14 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
23372338
if (opline->opcode == ZEND_ADD &&
23382339
(op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY &&
23392340
(op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) {
2340-
if (!zend_jit_add_arrays(&dasm_state, opline, op1_info, op2_info)) {
2341-
goto jit_failure;
2342-
}
2343-
goto done;
2344-
}
2345-
if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) ||
2341+
/* pass */
2342+
} else if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) ||
23462343
!(op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
23472344
break;
23482345
}
2349-
if (opline->result_type == IS_TMP_VAR
2346+
res_addr = RES_REG_ADDR();
2347+
if (Z_MODE(res_addr) != IS_REG
2348+
&& opline->result_type == IS_TMP_VAR
23502349
&& (i + 1) <= end
23512350
&& (opline+1)->opcode == ZEND_SEND_VAL
23522351
&& (opline+1)->op1_type == IS_TMP_VAR
@@ -2359,16 +2358,23 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
23592358
}
23602359
} else {
23612360
res_use_info = RES_USE_INFO();
2362-
res_addr = RES_REG_ADDR();
23632361
}
23642362
res_info = RES_INFO();
2365-
if (!zend_jit_math(&dasm_state, opline,
2366-
op1_info, OP1_REG_ADDR(),
2367-
op2_info, OP2_REG_ADDR(),
2368-
res_use_info, res_info, res_addr,
2369-
(op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (res_info & MAY_BE_DOUBLE) && zend_may_overflow(opline, ssa_op, op_array, ssa),
2370-
zend_may_throw(opline, ssa_op, op_array, ssa))) {
2371-
goto jit_failure;
2363+
if (opline->opcode == ZEND_ADD &&
2364+
(op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY &&
2365+
(op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) {
2366+
if (!zend_jit_add_arrays(&dasm_state, opline, op1_info, op2_info, res_addr)) {
2367+
goto jit_failure;
2368+
}
2369+
} else {
2370+
if (!zend_jit_math(&dasm_state, opline,
2371+
op1_info, OP1_REG_ADDR(),
2372+
op2_info, OP2_REG_ADDR(),
2373+
res_use_info, res_info, res_addr,
2374+
(op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (res_info & MAY_BE_DOUBLE) && zend_may_overflow(opline, ssa_op, op_array, ssa),
2375+
zend_may_throw(opline, ssa_op, op_array, ssa))) {
2376+
goto jit_failure;
2377+
}
23722378
}
23732379
goto done;
23742380
case ZEND_CONCAT:
@@ -2385,7 +2391,9 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
23852391
!(op2_info & MAY_BE_STRING)) {
23862392
break;
23872393
}
2388-
if (opline->result_type == IS_TMP_VAR
2394+
res_addr = RES_REG_ADDR();
2395+
if (Z_MODE(res_addr) != IS_REG
2396+
&& opline->result_type == IS_TMP_VAR
23892397
&& (i + 1) <= end
23902398
&& (opline+1)->opcode == ZEND_SEND_VAL
23912399
&& (opline+1)->op1_type == IS_TMP_VAR
@@ -2395,8 +2403,6 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
23952403
if (!zend_jit_reuse_ip(&dasm_state)) {
23962404
goto jit_failure;
23972405
}
2398-
} else {
2399-
res_addr = RES_REG_ADDR();
24002406
}
24012407
if (!zend_jit_concat(&dasm_state, opline,
24022408
op1_info, op2_info, res_addr,
@@ -2624,13 +2630,6 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
26242630
if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
26252631
break;
26262632
}
2627-
if (opline->result_type == IS_UNUSED) {
2628-
res_addr = 0;
2629-
res_info = -1;
2630-
} else {
2631-
res_addr = RES_REG_ADDR();
2632-
res_info = RES_INFO();
2633-
}
26342633
op2_addr = OP2_REG_ADDR();
26352634
if (ra
26362635
&& ssa->ops[opline - op_array->opcodes].op2_def >= 0
@@ -2639,6 +2638,25 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
26392638
} else {
26402639
op2_def_addr = op2_addr;
26412640
}
2641+
if (opline->result_type == IS_UNUSED) {
2642+
res_addr = 0;
2643+
res_info = -1;
2644+
} else {
2645+
res_addr = RES_REG_ADDR();
2646+
res_info = RES_INFO();
2647+
if (Z_MODE(res_addr) != IS_REG
2648+
&& opline->result_type == IS_TMP_VAR
2649+
&& (i + 1) <= end
2650+
&& (opline+1)->opcode == ZEND_SEND_VAL
2651+
&& (opline+1)->op1_type == IS_TMP_VAR
2652+
&& (opline+1)->op1.var == opline->result.var) {
2653+
i++;
2654+
res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var);
2655+
if (!zend_jit_reuse_ip(&dasm_state)) {
2656+
goto jit_failure;
2657+
}
2658+
}
2659+
}
26422660
if (!zend_jit_assign(&dasm_state, opline,
26432661
OP1_INFO(), OP1_REG_ADDR(),
26442662
OP1_DEF_INFO(), OP1_DEF_REG_ADDR(),

ext/opcache/jit/zend_jit_trace.c

Lines changed: 89 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -3502,10 +3502,17 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
35023502
|| !(op2_info & MAY_BE_LONG)) {
35033503
break;
35043504
}
3505-
if (opline->result_type == IS_TMP_VAR
3505+
res_addr = RES_REG_ADDR();
3506+
if (Z_MODE(res_addr) != IS_REG
3507+
&& opline->result_type == IS_TMP_VAR
35063508
&& (p+1)->op == ZEND_JIT_TRACE_VM
35073509
&& (p+1)->opline == opline + 1
3508-
&& (opline+1)->opcode == ZEND_SEND_VAL
3510+
&& ((opline+1)->opcode == ZEND_SEND_VAL
3511+
|| ((opline+1)->opcode == ZEND_SEND_VAL_EX
3512+
&& frame
3513+
&& frame->call
3514+
&& frame->call->func
3515+
&& !ARG_MUST_BE_SENT_BY_REF(frame->call->func, (opline+1)->op2.num)))
35093516
&& (opline+1)->op1_type == IS_TMP_VAR
35103517
&& (opline+1)->op1.var == opline->result.var) {
35113518
p++;
@@ -3529,7 +3536,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
35293536
goto jit_failure;
35303537
}
35313538
} else {
3532-
send_result = 0;
35333539
if (opline->result_type == IS_CV) {
35343540
res_use_info = RES_USE_INFO();
35353541
} else {
@@ -3539,7 +3545,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
35393545
res_use_info = -1;
35403546
#endif
35413547
}
3542-
res_addr = RES_REG_ADDR();
35433548
}
35443549
res_info = RES_INFO();
35453550
if (!zend_jit_long_math(&dasm_state, opline,
@@ -3564,19 +3569,22 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
35643569
if (opline->opcode == ZEND_ADD &&
35653570
(op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY &&
35663571
(op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) {
3567-
if (!zend_jit_add_arrays(&dasm_state, opline, op1_info, op2_info)) {
3568-
goto jit_failure;
3569-
}
3570-
goto done;
3571-
}
3572-
if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) ||
3572+
/* pass */
3573+
} else if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) ||
35733574
!(op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
35743575
break;
35753576
}
3576-
if (opline->result_type == IS_TMP_VAR
3577+
res_addr = RES_REG_ADDR();
3578+
if (Z_MODE(res_addr) != IS_REG
3579+
&& opline->result_type == IS_TMP_VAR
35773580
&& (p+1)->op == ZEND_JIT_TRACE_VM
35783581
&& (p+1)->opline == opline + 1
3579-
&& (opline+1)->opcode == ZEND_SEND_VAL
3582+
&& ((opline+1)->opcode == ZEND_SEND_VAL
3583+
|| ((opline+1)->opcode == ZEND_SEND_VAL_EX
3584+
&& frame
3585+
&& frame->call
3586+
&& frame->call->func
3587+
&& !ARG_MUST_BE_SENT_BY_REF(frame->call->func, (opline+1)->op2.num)))
35803588
&& (opline+1)->op1_type == IS_TMP_VAR
35813589
&& (opline+1)->op1.var == opline->result.var) {
35823590
p++;
@@ -3602,7 +3610,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
36023610
goto jit_failure;
36033611
}
36043612
} else {
3605-
send_result = 0;
36063613
if (opline->result_type == IS_CV) {
36073614
res_use_info = RES_USE_INFO();
36083615
} else {
@@ -3612,19 +3619,27 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
36123619
res_use_info = -1;
36133620
#endif
36143621
}
3615-
res_addr = RES_REG_ADDR();
36163622
}
36173623
res_info = RES_INFO();
3618-
if (!zend_jit_math(&dasm_state, opline,
3619-
op1_info, OP1_REG_ADDR(),
3620-
op2_info, OP2_REG_ADDR(),
3621-
res_use_info, res_info, res_addr,
3622-
(op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (res_info & (MAY_BE_DOUBLE|MAY_BE_GUARD)) && zend_may_overflow(opline, ssa_op, op_array, ssa),
3623-
zend_may_throw(opline, ssa_op, op_array, ssa))) {
3624-
goto jit_failure;
3625-
}
3626-
if ((res_info & (MAY_BE_ANY|MAY_BE_GUARD)) == (MAY_BE_LONG|MAY_BE_GUARD)) {
3627-
ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
3624+
if (opline->opcode == ZEND_ADD &&
3625+
(op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY &&
3626+
(op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) {
3627+
if (!zend_jit_add_arrays(&dasm_state, opline, op1_info, op2_info, res_addr)) {
3628+
goto jit_failure;
3629+
}
3630+
} else {
3631+
if (!zend_jit_math(&dasm_state, opline,
3632+
op1_info, OP1_REG_ADDR(),
3633+
op2_info, OP2_REG_ADDR(),
3634+
res_use_info, res_info, res_addr,
3635+
(op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (res_info & (MAY_BE_DOUBLE|MAY_BE_GUARD)) && zend_may_overflow(opline, ssa_op, op_array, ssa),
3636+
zend_may_throw(opline, ssa_op, op_array, ssa))) {
3637+
goto jit_failure;
3638+
}
3639+
if ((res_info & (MAY_BE_ANY|MAY_BE_GUARD)) == (MAY_BE_LONG|MAY_BE_GUARD)
3640+
|| (res_info & (MAY_BE_ANY|MAY_BE_GUARD)) == (MAY_BE_DOUBLE|MAY_BE_GUARD)) {
3641+
ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
3642+
}
36283643
}
36293644
goto done;
36303645
case ZEND_CONCAT:
@@ -3640,10 +3655,17 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
36403655
!(op2_info & MAY_BE_STRING)) {
36413656
break;
36423657
}
3643-
if (opline->result_type == IS_TMP_VAR
3658+
res_addr = RES_REG_ADDR();
3659+
if (Z_MODE(res_addr) != IS_REG
3660+
&& opline->result_type == IS_TMP_VAR
36443661
&& (p+1)->op == ZEND_JIT_TRACE_VM
36453662
&& (p+1)->opline == opline + 1
3646-
&& (opline+1)->opcode == ZEND_SEND_VAL
3663+
&& ((opline+1)->opcode == ZEND_SEND_VAL
3664+
|| ((opline+1)->opcode == ZEND_SEND_VAL_EX
3665+
&& frame
3666+
&& frame->call
3667+
&& frame->call->func
3668+
&& !ARG_MUST_BE_SENT_BY_REF(frame->call->func, (opline+1)->op2.num)))
36473669
&& (opline+1)->op1_type == IS_TMP_VAR
36483670
&& (opline+1)->op1.var == opline->result.var) {
36493671
p++;
@@ -3667,9 +3689,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
36673689
if (!zend_jit_reuse_ip(&dasm_state)) {
36683690
goto jit_failure;
36693691
}
3670-
} else {
3671-
send_result = 0;
3672-
res_addr = RES_REG_ADDR();
36733692
}
36743693
if (!zend_jit_concat(&dasm_state, opline,
36753694
op1_info, op2_info, res_addr,
@@ -4028,13 +4047,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
40284047
if (opline->op1_type != IS_CV) {
40294048
break;
40304049
}
4031-
if (opline->result_type == IS_UNUSED) {
4032-
res_addr = 0;
4033-
res_info = -1;
4034-
} else {
4035-
res_addr = RES_REG_ADDR();
4036-
res_info = RES_INFO();
4037-
}
40384050
op2_addr = OP2_REG_ADDR();
40394051
if (ra
40404052
&& ssa_op->op2_def >= 0
@@ -4072,6 +4084,47 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
40724084
op1_def_info &= ~MAY_BE_REF;
40734085
}
40744086
}
4087+
if (opline->result_type == IS_UNUSED) {
4088+
res_addr = 0;
4089+
res_info = -1;
4090+
} else {
4091+
res_addr = RES_REG_ADDR();
4092+
res_info = RES_INFO();
4093+
if (Z_MODE(res_addr) != IS_REG
4094+
&& opline->result_type == IS_TMP_VAR
4095+
&& (p+1)->op == ZEND_JIT_TRACE_VM
4096+
&& (p+1)->opline == opline + 1
4097+
&& ((opline+1)->opcode == ZEND_SEND_VAL
4098+
|| ((opline+1)->opcode == ZEND_SEND_VAL_EX
4099+
&& frame
4100+
&& frame->call
4101+
&& frame->call->func
4102+
&& !ARG_MUST_BE_SENT_BY_REF(frame->call->func, (opline+1)->op2.num)))
4103+
&& (opline+1)->op1_type == IS_TMP_VAR
4104+
&& (opline+1)->op1.var == opline->result.var) {
4105+
p++;
4106+
if (frame->call
4107+
&& frame->call->func
4108+
&& frame->call->func->type == ZEND_USER_FUNCTION) {
4109+
uint8_t res_type = p->op1_type;
4110+
if (res_type & IS_TRACE_REFERENCE) {
4111+
res_type = IS_UNKNOWN;
4112+
}
4113+
if (res_type != IS_UNKNOWN) {
4114+
zend_jit_trace_send_type(opline+1, frame->call, res_type);
4115+
}
4116+
}
4117+
while ((p+1)->op == ZEND_JIT_TRACE_OP1_TYPE ||
4118+
(p+1)->op == ZEND_JIT_TRACE_OP2_TYPE) {
4119+
p++;
4120+
}
4121+
send_result = 1;
4122+
res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var);
4123+
if (!zend_jit_reuse_ip(&dasm_state)) {
4124+
goto jit_failure;
4125+
}
4126+
}
4127+
}
40754128
if (!zend_jit_assign(&dasm_state, opline,
40764129
op1_info, op1_addr,
40774130
op1_def_info, op1_def_addr,

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4749,11 +4749,10 @@ static int zend_jit_math(dasm_State **Dst, const zend_op *opline, uint32_t op1_i
47494749
return 1;
47504750
}
47514751

4752-
static int zend_jit_add_arrays(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, uint32_t op2_info)
4752+
static int zend_jit_add_arrays(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, uint32_t op2_info, zend_jit_addr res_addr)
47534753
{
47544754
zend_jit_addr op1_addr = OP1_ADDR();
47554755
zend_jit_addr op2_addr = OP2_ADDR();
4756-
zend_jit_addr res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
47574756

47584757
| GET_ZVAL_LVAL ZREG_FCARG1a, op1_addr
47594758
| GET_ZVAL_LVAL ZREG_FCARG2a, op2_addr

0 commit comments

Comments
 (0)