]> granicus.if.org Git - php/commitdiff
Use cheaper code for overflow +/-1
authorDmitry Stogov <dmitry@zend.com>
Fri, 6 Dec 2019 11:04:58 +0000 (14:04 +0300)
committerDmitry Stogov <dmitry@zend.com>
Fri, 6 Dec 2019 11:04:58 +0000 (14:04 +0300)
ext/opcache/jit/zend_jit_x86.dasc

index ba7075d261d5beec7e155bb7bfe80530fc9b0fb0..ac64668e674787faaaeb163646f06474e0260a8e 100644 (file)
@@ -3036,38 +3036,62 @@ static int zend_jit_math_long_long(dasm_State    **Dst,
        }
        if (may_overflow) {
                |       jo >1
-               |.cold_code
-               |1:
+       }
+
+       |       SET_ZVAL_LVAL res_addr, Ra(result_reg)
+       if (Z_MODE(op1_addr) != IS_MEM_ZVAL || Z_REG(op1_addr) != Z_REG(res_addr) || Z_OFFSET(op1_addr) != Z_OFFSET(res_addr)) {
+               if ((res_use_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != MAY_BE_LONG) {
+                       |       SET_ZVAL_TYPE_INFO res_addr, IS_LONG
+               }
+       }
+
+       if (may_overflow) {
                zend_reg tmp_reg1 = ZREG_XMM0;
                zend_reg tmp_reg2 = ZREG_XMM1;
 
-               |       SSE_GET_ZVAL_LVAL tmp_reg1, op1_addr
-               |       SSE_GET_ZVAL_LVAL tmp_reg2, op2_addr
-               if (zend_jit_x86_flags & ZEND_JIT_CPU_AVX) {
-                       |       AVX_MATH_REG opcode, tmp_reg1, tmp_reg1, tmp_reg2
-               } else {
-                       |       SSE_MATH_REG opcode, tmp_reg1, tmp_reg2
-               }
-               |       SSE_SET_ZVAL_DVAL res_addr, tmp_reg1
+               |.cold_code
+               |1:
+
+               do {
+                       if ((Z_MODE(op1_addr) == IS_CONST_ZVAL && Z_LVAL_P(Z_ZV(op1_addr)) == 1) ||
+                           (Z_MODE(op2_addr) == IS_CONST_ZVAL && Z_LVAL_P(Z_ZV(op2_addr)) == 1)) {
+                               if (opcode == ZEND_ADD) {
+                                       |.if X64
+                                               |       mov64 rax, 0x43e0000000000000
+                                               |       SET_ZVAL_LVAL res_addr, rax
+                                       |.else
+                                               |       SET_ZVAL_LVAL res_addr, 0
+                                               |       SET_ZVAL_W2 res_addr, 0x41e00000
+                                       |.endif
+                                       break;
+                               } else if (opcode == ZEND_SUB) {
+                                       |.if X64
+                                               |       mov64 rax, 0xc3e0000000000000
+                                               |       SET_ZVAL_LVAL res_addr, rax
+                                       |.else
+                                               |       SET_ZVAL_LVAL res_addr, 0x00200000
+                                               |       SET_ZVAL_W2 res_addr, 0xc1e00000
+                                       |.endif
+                                       break;
+                               }
+                       }
+
+                       |       SSE_GET_ZVAL_LVAL tmp_reg1, op1_addr
+                       |       SSE_GET_ZVAL_LVAL tmp_reg2, op2_addr
+                       if (zend_jit_x86_flags & ZEND_JIT_CPU_AVX) {
+                               |       AVX_MATH_REG opcode, tmp_reg1, tmp_reg1, tmp_reg2
+                       } else {
+                               |       SSE_MATH_REG opcode, tmp_reg1, tmp_reg2
+                       }
+                       |       SSE_SET_ZVAL_DVAL res_addr, tmp_reg1
+               } while (0);
+
                if ((res_use_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != MAY_BE_DOUBLE) {
                        |       SET_ZVAL_TYPE_INFO res_addr, IS_DOUBLE
                }
                |       jmp >2
                |.code
-               |       SET_ZVAL_LVAL res_addr, Ra(result_reg)
-               if (Z_MODE(op1_addr) != IS_MEM_ZVAL || Z_REG(op1_addr) != Z_REG(res_addr) || Z_OFFSET(op1_addr) != Z_OFFSET(res_addr)) {
-                       if ((res_use_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != MAY_BE_LONG) {
-                               |       SET_ZVAL_TYPE_INFO res_addr, IS_LONG
-                       }
-               }
                |2:
-       } else if (Z_MODE(res_addr) == IS_MEM_ZVAL) {
-               |       SET_ZVAL_LVAL res_addr, Ra(result_reg)
-               if (Z_MODE(op1_addr) != IS_MEM_ZVAL || Z_REG(op1_addr) != Z_REG(res_addr) || Z_OFFSET(op1_addr) != Z_OFFSET(res_addr)) {
-                       if ((res_use_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != MAY_BE_LONG) {
-                               |       SET_ZVAL_TYPE_INFO res_addr, IS_LONG
-                       }
-               }
        }
 
        return 1;