1
0
mirror of https://github.com/php/php-src.git synced 2026-03-25 16:52:18 +01:00
Files
archived-php-src/ext/opcache/tests
Hao Sun 42bec86a3c Optimizing LONG MUL to SHIFT: refine the trigger condition and add overflow detection
LONG MUL can be optimzied into left shift if either operand is a power
of two. Conditions "IS_SIGNED_32BIT()" and "is_power_of_two()" are used
to filter out invalid candidates. However, there exists one exception,
i.e. -2147483648(that is 0xffff,ffff,8000,0000). See the stand-alone
case[1].

Assume "a = 3; b = -2147483648;". The expected result of "a * b" is one
negative value. However, it would be optimized to "a << 31", which is
positive.

This trigger condition is refined.
1) For x86 implementation, another check for positive numbers is added.
Note that LONG type, i.e. zend_long, is defined as int32_t for x86 arch
and int64_t for x64 arch. This optimization only accepts values which
can be represented by int32_t type as default. See IS_SIGNED_32BIlT(),
2) For AArch64, we employ helper function zend_long_is_power_of_two()
since values of int64_t type are used.

Overflow detection for left shifting is added in this patch as well.

Note 1: bit helper functions are arch-independent and we move them into
zend_jit_internals.h.

Note 2: two test cases are added. Test case mul_003.phpt is used to
check the trigger condition and mul_004.phpt is designed to check
overflow detection.

Note 3: overflow detection for x86 is not implemented yet as I think
anotehr temporay register besides R0 is needed. Hence mul_004.phpt would
fail on x86 machine.
If we can use R1 as tmp_reg, the code can be updated as below.

```
  |	GET_ZVAL_LVAL result_reg, op1_addr
  if (may_overflow) {
    use_ovf_flag = 0;
    /* Compare 'op' and '((op << n) >> n)' for overflow.
     * Flag: jne -> overflow. je -> no overflow.
     */
    tmp_reg = ZREG_R1
    |	mov Ra(tmp_reg), Ra(result_reg)
    |	shl Ra(tmp_reg), floor_log2(Z_LVAL_P(Z_ZV(op2_addr)))
    |	sar Ra(tmp_reg), floor_log2(Z_LVAL_P(Z_ZV(op2_addr)))
    |	cmp Ra(tmp_reg), Ra(result_reg)
  }
  |	shl Ra(result_reg), floor_log2(Z_LVAL_P(Z_ZV(op2_addr)))
```

[1]. https://godbolt.org/z/1vKbfv8oG

Change-Id: Ie90e1d4e7c8b94a0c8f61386dfe650fa2c6879a1
2021-05-18 15:32:30 +03:00
..
2021-04-08 18:24:57 +02:00
2020-02-03 22:52:20 +01:00
2020-02-03 22:52:20 +01:00
2021-04-14 00:21:37 +08:00
2021-05-06 10:46:00 +02:00
2021-05-17 15:46:49 +02:00
2020-02-03 22:52:20 +01:00
2020-02-03 22:52:20 +01:00
2020-02-03 22:52:20 +01:00
2020-02-03 22:52:20 +01:00
2020-02-03 22:52:20 +01:00
2020-02-03 22:52:20 +01:00
2019-07-05 11:00:27 +02:00