diff --git a/ext/opcache/jit/zend_jit_arm64.dasc b/ext/opcache/jit/zend_jit_arm64.dasc index 04d738144a8..40e7a5263db 100644 --- a/ext/opcache/jit/zend_jit_arm64.dasc +++ b/ext/opcache/jit/zend_jit_arm64.dasc @@ -4609,7 +4609,6 @@ static int zend_jit_long_math_helper(dasm_State **Dst, { bool same_ops = zend_jit_same_addr(op1_addr, op2_addr); zend_reg result_reg; - zval tmp; if (op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-MAY_BE_LONG)) { | IF_NOT_ZVAL_TYPE op1_addr, IS_LONG, >6, ZREG_TMP1 @@ -4618,19 +4617,6 @@ static int zend_jit_long_math_helper(dasm_State **Dst, | IF_NOT_ZVAL_TYPE op2_addr, IS_LONG, >6, ZREG_TMP1 } - if (opcode == ZEND_MOD && Z_MODE(op2_addr) == IS_CONST_ZVAL && - op1_range && - op1_range->min >= 0) { - zend_long l = Z_LVAL_P(Z_ZV(op2_addr)); - - if (zend_long_is_power_of_two(l)) { - /* Optimisation for mod of power of 2 */ - opcode = ZEND_BW_AND; - ZVAL_LONG(&tmp, l - 1); - op2_addr = ZEND_ADDR_CONST_ZVAL(&tmp); - } - } - if (Z_MODE(res_addr) == IS_REG) { if ((opline->opcode == ZEND_SL || opline->opcode == ZEND_SR) && opline->op2_type != IS_CONST) { @@ -4742,6 +4728,15 @@ static int zend_jit_long_math_helper(dasm_State **Dst, | b ->mod_by_zero } else if (op2_lval == -1) { | mov Rx(result_reg), xzr + } else if (zend_long_is_power_of_two(op2_lval) && op1_range && op1_range->min >= 0) { + zval tmp; + zend_jit_addr tmp_addr; + + /* Optimisation for mod of power of 2 */ + ZVAL_LONG(&tmp, op2_lval - 1); + tmp_addr = ZEND_ADDR_CONST_ZVAL(&tmp); + | GET_ZVAL_LVAL result_reg, op1_addr, TMP1 + | LONG_MATH ZEND_BW_AND, result_reg, tmp_addr, TMP1 } else { | GET_ZVAL_LVAL ZREG_TMP1, op1_addr, TMP1 | GET_ZVAL_LVAL ZREG_TMP2, op2_addr, TMP2 diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 501ad9349ef..3768325825e 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -5023,7 +5023,6 @@ static int zend_jit_long_math_helper(dasm_State **Dst, { bool same_ops = zend_jit_same_addr(op1_addr, op2_addr); zend_reg result_reg; - zval tmp; if (op1_info & ((MAY_BE_ANY|MAY_BE_UNDEF)-MAY_BE_LONG)) { | IF_NOT_ZVAL_TYPE op1_addr, IS_LONG, >6 @@ -5032,19 +5031,6 @@ static int zend_jit_long_math_helper(dasm_State **Dst, | IF_NOT_ZVAL_TYPE op2_addr, IS_LONG, >6 } - if (opcode == ZEND_MOD && Z_MODE(op2_addr) == IS_CONST_ZVAL && - op1_range && - op1_range->min >= 0) { - zend_long l = Z_LVAL_P(Z_ZV(op2_addr)); - - if (zend_long_is_power_of_two(l)) { - /* Optimisation for mod of power of 2 */ - opcode = ZEND_BW_AND; - ZVAL_LONG(&tmp, l - 1); - op2_addr = ZEND_ADDR_CONST_ZVAL(&tmp); - } - } - if (opcode == ZEND_MOD) { result_reg = ZREG_RAX; if (Z_MODE(res_addr) == IS_MEM_ZVAL && Z_REG(res_addr) == ZREG_RAX) { @@ -5154,6 +5140,15 @@ static int zend_jit_long_math_helper(dasm_State **Dst, if (op2_lval == 0) { | SET_EX_OPLINE opline, r0 | jmp ->mod_by_zero + } else if (zend_long_is_power_of_two(op2_lval) && op1_range && op1_range->min >= 0) { + zval tmp; + zend_jit_addr tmp_addr; + + /* Optimisation for mod of power of 2 */ + ZVAL_LONG(&tmp, op2_lval - 1); + tmp_addr = ZEND_ADDR_CONST_ZVAL(&tmp); + | GET_ZVAL_LVAL result_reg, op1_addr + | LONG_MATH ZEND_BW_AND, result_reg, tmp_addr } else { result_reg = ZREG_RDX; if (op2_lval == -1) { diff --git a/ext/opcache/tests/jit/mul_007.phpt b/ext/opcache/tests/jit/mul_007.phpt new file mode 100644 index 00000000000..a077ac1878c --- /dev/null +++ b/ext/opcache/tests/jit/mul_007.phpt @@ -0,0 +1,21 @@ +--TEST-- +JIT MUL: 007 incorrect optimization +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_update_protection=0 +opcache.jit_buffer_size=1M +opcache.protect_memory=1 +--FILE-- + +DONE +--EXPECTF-- +Deprecated: Implicit conversion from float 1.5 to int loses precision in %smul_007.php on line 3 + +Deprecated: Implicit conversion from float 0.5 to int loses precision in %smul_007.php on line 3 +DONE \ No newline at end of file