]> granicus.if.org Git - php/commitdiff
Copy optimization for (BINARY_OP/ACCIGN + SEND_VAL)
authorDmitry Stogov <dmitry@zend.com>
Fri, 2 Oct 2020 09:06:02 +0000 (12:06 +0300)
committerDmitry Stogov <dmitry@zend.com>
Fri, 2 Oct 2020 09:06:02 +0000 (12:06 +0300)
ext/opcache/jit/zend_jit.c
ext/opcache/jit/zend_jit_trace.c
ext/opcache/jit/zend_jit_x86.dasc

index 91f1a5d458bdc130fdfec28e3cbfa9a27bbbd9b2..7c9a8bb7cff2e00f84a95d9f319b7b242c7086f0 100644 (file)
@@ -2299,7 +2299,9 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
                                                 || !(op2_info & MAY_BE_LONG)) {
                                                        break;
                                                }
-                                               if (opline->result_type == IS_TMP_VAR
+                                               res_addr = RES_REG_ADDR();
+                                               if (Z_MODE(res_addr) != IS_REG
+                                                && opline->result_type == IS_TMP_VAR
                                                 && (i + 1) <= end
                                                 && (opline+1)->opcode == ZEND_SEND_VAL
                                                 && (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
                                                        }
                                                } else {
                                                        res_use_info = RES_USE_INFO();
-                                                       res_addr = RES_REG_ADDR();
                                                }
                                                if (!zend_jit_long_math(&dasm_state, opline,
                                                                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
                                                if (opline->opcode == ZEND_ADD &&
                                                    (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY &&
                                                    (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) {
-                                                       if (!zend_jit_add_arrays(&dasm_state, opline, op1_info, op2_info)) {
-                                                               goto jit_failure;
-                                                       }
-                                                       goto done;
-                                               }
-                                               if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) ||
+                                                       /* pass */
+                                               } else if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) ||
                                                    !(op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
                                                        break;
                                                }
-                                               if (opline->result_type == IS_TMP_VAR
+                                               res_addr = RES_REG_ADDR();
+                                               if (Z_MODE(res_addr) != IS_REG
+                                                && opline->result_type == IS_TMP_VAR
                                                 && (i + 1) <= end
                                                 && (opline+1)->opcode == ZEND_SEND_VAL
                                                 && (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
                                                        }
                                                } else {
                                                        res_use_info = RES_USE_INFO();
-                                                       res_addr = RES_REG_ADDR();
                                                }
                                                res_info = RES_INFO();
-                                               if (!zend_jit_math(&dasm_state, opline,
-                                                               op1_info, OP1_REG_ADDR(),
-                                                               op2_info, OP2_REG_ADDR(),
-                                                               res_use_info, res_info, res_addr,
-                                                               (op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (res_info & MAY_BE_DOUBLE) && zend_may_overflow(opline, ssa_op, op_array, ssa),
-                                                               zend_may_throw(opline, ssa_op, op_array, ssa))) {
-                                                       goto jit_failure;
+                                               if (opline->opcode == ZEND_ADD &&
+                                                   (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY &&
+                                                   (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) {
+                                                       if (!zend_jit_add_arrays(&dasm_state, opline, op1_info, op2_info, res_addr)) {
+                                                               goto jit_failure;
+                                                       }
+                                               } else {
+                                                       if (!zend_jit_math(&dasm_state, opline,
+                                                                       op1_info, OP1_REG_ADDR(),
+                                                                       op2_info, OP2_REG_ADDR(),
+                                                                       res_use_info, res_info, res_addr,
+                                                                       (op1_info & MAY_BE_LONG) && (op2_info & MAY_BE_LONG) && (res_info & MAY_BE_DOUBLE) && zend_may_overflow(opline, ssa_op, op_array, ssa),
+                                                                       zend_may_throw(opline, ssa_op, op_array, ssa))) {
+                                                               goto jit_failure;
+                                                       }
                                                }
                                                goto done;
                                        case ZEND_CONCAT:
@@ -2385,7 +2391,9 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
                                                    !(op2_info & MAY_BE_STRING)) {
                                                        break;
                                                }
-                                               if (opline->result_type == IS_TMP_VAR
+                                               res_addr = RES_REG_ADDR();
+                                               if (Z_MODE(res_addr) != IS_REG
+                                                && opline->result_type == IS_TMP_VAR
                                                 && (i + 1) <= end
                                                 && (opline+1)->opcode == ZEND_SEND_VAL
                                                 && (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
                                                        if (!zend_jit_reuse_ip(&dasm_state)) {
                                                                goto jit_failure;
                                                        }
-                                               } else {
-                                                       res_addr = RES_REG_ADDR();
                                                }
                                                if (!zend_jit_concat(&dasm_state, opline,
                                                                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
                                                if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {
                                                        break;
                                                }
-                                               if (opline->result_type == IS_UNUSED) {
-                                                       res_addr = 0;
-                                                       res_info = -1;
-                                               } else {
-                                                       res_addr = RES_REG_ADDR();
-                                                       res_info = RES_INFO();
-                                               }
                                                op2_addr = OP2_REG_ADDR();
                                                if (ra
                                                 && 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
                                                } else {
                                                        op2_def_addr = op2_addr;
                                                }
+                                               if (opline->result_type == IS_UNUSED) {
+                                                       res_addr = 0;
+                                                       res_info = -1;
+                                               } else {
+                                                       res_addr = RES_REG_ADDR();
+                                                       res_info = RES_INFO();
+                                                       if (Z_MODE(res_addr) != IS_REG
+                                                        && opline->result_type == IS_TMP_VAR
+                                                        && (i + 1) <= end
+                                                        && (opline+1)->opcode == ZEND_SEND_VAL
+                                                        && (opline+1)->op1_type == IS_TMP_VAR
+                                                        && (opline+1)->op1.var == opline->result.var) {
+                                                               i++;
+                                                               res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var);
+                                                               if (!zend_jit_reuse_ip(&dasm_state)) {
+                                                                       goto jit_failure;
+                                                               }
+                                                       }
+                                               }
                                                if (!zend_jit_assign(&dasm_state, opline,
                                                                OP1_INFO(), OP1_REG_ADDR(),
                                                                OP1_DEF_INFO(), OP1_DEF_REG_ADDR(),
index 27ff183ba487e2bd64037a63fba63d9e8e19b5e9..0d691f8c2da8f9e4265db823a2f9f9d3680d9850 100644 (file)
@@ -3502,10 +3502,17 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                 || !(op2_info & MAY_BE_LONG)) {
                                                        break;
                                                }
-                                               if (opline->result_type == IS_TMP_VAR
+                                               res_addr = RES_REG_ADDR();
+                                               if (Z_MODE(res_addr) != IS_REG
+                                                && opline->result_type == IS_TMP_VAR
                                                 && (p+1)->op == ZEND_JIT_TRACE_VM
                                                 && (p+1)->opline == opline + 1
-                                                && (opline+1)->opcode == ZEND_SEND_VAL
+                                                && ((opline+1)->opcode == ZEND_SEND_VAL
+                                                 || ((opline+1)->opcode == ZEND_SEND_VAL_EX
+                                                  && frame
+                                                  && frame->call
+                                                  && frame->call->func
+                                                  && !ARG_MUST_BE_SENT_BY_REF(frame->call->func, (opline+1)->op2.num)))
                                                 && (opline+1)->op1_type == IS_TMP_VAR
                                                 && (opline+1)->op1.var == opline->result.var) {
                                                        p++;
@@ -3529,7 +3536,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                                goto jit_failure;
                                                        }
                                                } else {
-                                                       send_result = 0;
                                                        if (opline->result_type == IS_CV) {
                                                                res_use_info = RES_USE_INFO();
                                                        } else {
@@ -3539,7 +3545,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                                res_use_info = -1;
 #endif
                                                        }
-                                                       res_addr = RES_REG_ADDR();
                                                }
                                                res_info = RES_INFO();
                                                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
                                                if (opline->opcode == ZEND_ADD &&
                                                    (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY &&
                                                    (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) {
-                                                       if (!zend_jit_add_arrays(&dasm_state, opline, op1_info, op2_info)) {
-                                                               goto jit_failure;
-                                                       }
-                                                       goto done;
-                                               }
-                                               if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) ||
+                                                       /* pass */
+                                               } else if (!(op1_info & (MAY_BE_LONG|MAY_BE_DOUBLE)) ||
                                                    !(op2_info & (MAY_BE_LONG|MAY_BE_DOUBLE))) {
                                                        break;
                                                }
-                                               if (opline->result_type == IS_TMP_VAR
+                                               res_addr = RES_REG_ADDR();
+                                               if (Z_MODE(res_addr) != IS_REG
+                                                && opline->result_type == IS_TMP_VAR
                                                 && (p+1)->op == ZEND_JIT_TRACE_VM
                                                 && (p+1)->opline == opline + 1
-                                                && (opline+1)->opcode == ZEND_SEND_VAL
+                                                && ((opline+1)->opcode == ZEND_SEND_VAL
+                                                 || ((opline+1)->opcode == ZEND_SEND_VAL_EX
+                                                  && frame
+                                                  && frame->call
+                                                  && frame->call->func
+                                                  && !ARG_MUST_BE_SENT_BY_REF(frame->call->func, (opline+1)->op2.num)))
                                                 && (opline+1)->op1_type == IS_TMP_VAR
                                                 && (opline+1)->op1.var == opline->result.var) {
                                                        p++;
@@ -3602,7 +3610,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                                goto jit_failure;
                                                        }
                                                } else {
-                                                       send_result = 0;
                                                        if (opline->result_type == IS_CV) {
                                                                res_use_info = RES_USE_INFO();
                                                        } else {
@@ -3612,19 +3619,27 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                                res_use_info = -1;
 #endif
                                                        }
-                                                       res_addr = RES_REG_ADDR();
                                                }
                                                res_info = RES_INFO();
-                                               if (!zend_jit_math(&dasm_state, opline,
-                                                               op1_info, OP1_REG_ADDR(),
-                                                               op2_info, OP2_REG_ADDR(),
-                                                               res_use_info, res_info, res_addr,
-                                                               (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),
-                                                               zend_may_throw(opline, ssa_op, op_array, ssa))) {
-                                                       goto jit_failure;
-                                               }
-                                               if ((res_info & (MAY_BE_ANY|MAY_BE_GUARD)) == (MAY_BE_LONG|MAY_BE_GUARD)) {
-                                                       ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
+                                               if (opline->opcode == ZEND_ADD &&
+                                                   (op1_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY &&
+                                                   (op2_info & (MAY_BE_ANY|MAY_BE_UNDEF)) == MAY_BE_ARRAY) {
+                                                       if (!zend_jit_add_arrays(&dasm_state, opline, op1_info, op2_info, res_addr)) {
+                                                               goto jit_failure;
+                                                       }
+                                               } else {
+                                                       if (!zend_jit_math(&dasm_state, opline,
+                                                                       op1_info, OP1_REG_ADDR(),
+                                                                       op2_info, OP2_REG_ADDR(),
+                                                                       res_use_info, res_info, res_addr,
+                                                                       (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),
+                                                                       zend_may_throw(opline, ssa_op, op_array, ssa))) {
+                                                               goto jit_failure;
+                                                       }
+                                                       if ((res_info & (MAY_BE_ANY|MAY_BE_GUARD)) == (MAY_BE_LONG|MAY_BE_GUARD)
+                                                        || (res_info & (MAY_BE_ANY|MAY_BE_GUARD)) == (MAY_BE_DOUBLE|MAY_BE_GUARD)) {
+                                                               ssa->var_info[ssa_op->result_def].type &= ~MAY_BE_GUARD;
+                                                       }
                                                }
                                                goto done;
                                        case ZEND_CONCAT:
@@ -3640,10 +3655,17 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                    !(op2_info & MAY_BE_STRING)) {
                                                        break;
                                                }
-                                               if (opline->result_type == IS_TMP_VAR
+                                               res_addr = RES_REG_ADDR();
+                                               if (Z_MODE(res_addr) != IS_REG
+                                                && opline->result_type == IS_TMP_VAR
                                                 && (p+1)->op == ZEND_JIT_TRACE_VM
                                                 && (p+1)->opline == opline + 1
-                                                && (opline+1)->opcode == ZEND_SEND_VAL
+                                                && ((opline+1)->opcode == ZEND_SEND_VAL
+                                                 || ((opline+1)->opcode == ZEND_SEND_VAL_EX
+                                                  && frame
+                                                  && frame->call
+                                                  && frame->call->func
+                                                  && !ARG_MUST_BE_SENT_BY_REF(frame->call->func, (opline+1)->op2.num)))
                                                 && (opline+1)->op1_type == IS_TMP_VAR
                                                 && (opline+1)->op1.var == opline->result.var) {
                                                        p++;
@@ -3667,9 +3689,6 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                        if (!zend_jit_reuse_ip(&dasm_state)) {
                                                                goto jit_failure;
                                                        }
-                                               } else {
-                                                       send_result = 0;
-                                                       res_addr = RES_REG_ADDR();
                                                }
                                                if (!zend_jit_concat(&dasm_state, opline,
                                                                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
                                                if (opline->op1_type != IS_CV) {
                                                        break;
                                                }
-                                               if (opline->result_type == IS_UNUSED) {
-                                                       res_addr = 0;
-                                                       res_info = -1;
-                                               } else {
-                                                       res_addr = RES_REG_ADDR();
-                                                       res_info = RES_INFO();
-                                               }
                                                op2_addr = OP2_REG_ADDR();
                                                if (ra
                                                 && ssa_op->op2_def >= 0
@@ -4072,6 +4084,47 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
                                                                op1_def_info &= ~MAY_BE_REF;
                                                        }
                                                }
+                                               if (opline->result_type == IS_UNUSED) {
+                                                       res_addr = 0;
+                                                       res_info = -1;
+                                               } else {
+                                                       res_addr = RES_REG_ADDR();
+                                                       res_info = RES_INFO();
+                                                       if (Z_MODE(res_addr) != IS_REG
+                                                        && opline->result_type == IS_TMP_VAR
+                                                        && (p+1)->op == ZEND_JIT_TRACE_VM
+                                                        && (p+1)->opline == opline + 1
+                                                        && ((opline+1)->opcode == ZEND_SEND_VAL
+                                                         || ((opline+1)->opcode == ZEND_SEND_VAL_EX
+                                                          && frame
+                                                          && frame->call
+                                                          && frame->call->func
+                                                          && !ARG_MUST_BE_SENT_BY_REF(frame->call->func, (opline+1)->op2.num)))
+                                                        && (opline+1)->op1_type == IS_TMP_VAR
+                                                        && (opline+1)->op1.var == opline->result.var) {
+                                                               p++;
+                                                               if (frame->call
+                                                                && frame->call->func
+                                                                && frame->call->func->type == ZEND_USER_FUNCTION) {
+                                                                       uint8_t res_type = p->op1_type;
+                                                                       if (res_type & IS_TRACE_REFERENCE) {
+                                                                               res_type = IS_UNKNOWN;
+                                                                       }
+                                                                       if (res_type != IS_UNKNOWN) {
+                                                                               zend_jit_trace_send_type(opline+1, frame->call, res_type);
+                                                                       }
+                                                               }
+                                                               while ((p+1)->op == ZEND_JIT_TRACE_OP1_TYPE ||
+                                                                     (p+1)->op == ZEND_JIT_TRACE_OP2_TYPE) {
+                                                                       p++;
+                                                               }
+                                                               send_result = 1;
+                                                               res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_RX, (opline+1)->result.var);
+                                                               if (!zend_jit_reuse_ip(&dasm_state)) {
+                                                                       goto jit_failure;
+                                                               }
+                                                       }
+                                               }
                                                if (!zend_jit_assign(&dasm_state, opline,
                                                                op1_info, op1_addr,
                                                                op1_def_info, op1_def_addr,
index 532bdb97f81588781f9cbed92d8bfa3d15870549..5e097e27e73c67a49410fe2fb437b0d0a6a0ddbc 100644 (file)
@@ -4749,11 +4749,10 @@ static int zend_jit_math(dasm_State **Dst, const zend_op *opline, uint32_t op1_i
        return 1;
 }
 
-static int zend_jit_add_arrays(dasm_State **Dst, const zend_op *opline, uint32_t op1_info, uint32_t op2_info)
+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)
 {
        zend_jit_addr op1_addr = OP1_ADDR();
        zend_jit_addr op2_addr = OP2_ADDR();
-       zend_jit_addr res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
 
        |       GET_ZVAL_LVAL ZREG_FCARG1a, op1_addr
        |       GET_ZVAL_LVAL ZREG_FCARG2a, op2_addr