You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Comparison between LONG and DOUBLE is (partially) supported in a similar
way to comparison between two LONG values. See the updates in function
zend_jit_cmp().
Key difference lies in handling NaN.
1. Instruction 'fcmp' is used to substitue 'ucomisd' in x86
implementation. Both of them raise invalid operation exception only when
either source operand is an SNaN.[1][2]
2. Parity flag is used in x86 to check whether either operand is NaN.[3]
I think this is QNaN case. As for AArch64, we use instruction 'bvs'.[4]
It's worthing noting that condition codes have different meanings for
floating-point comparions(e.g. 'fcmp')[4] compared to the
general-purpose comparisons(e.g. 'cmp').[5] For instance, 'b.hs' after
'fcmp' can check not only the cases "greater than, equal to" but also
the case "unordered"(that is NaN). We may simply treat it as a
combination of 'jae' and 'jp' in x86.
3. Instruction 'SETcc' is used in x86 for the case of ">=" or ">".
Note that flag "swap" is set in implementation, and it falls into cases
ZEND_IS_SMALLER or ZEND_IS_SMALLER_OR_EQUAL. We can use 'cset' in
AArch64.
However, it's weird that the NaN check is missing in x86. I suppose it
might be a bug. Take the case ">=" as an example. The two operands can
be either DOUBLE + LONG or DOUBLE + DOUBLE. See the relevant code where
flag "swap" is set(i.e. function zend_jit_cmp_double_long() and function
zend_jit_cmp_double_double()). For the case "NaN >= 1.0", the expected
result should be FALSE, however, JIT/x86 would produce TRUE due to the
following "setae al". Unfortunately I haven't constructed one test case
to trigger that.
In our implementation, we choose to follow the case of "<" or "<=", and
I believe our implementation is safe anyway..
4. Temporary FP register is also needed and we reserve v16. See the
updates in file zend_jit_arm64.h.
5. Macro SET_ZVAL_TYPE_INFO_FROM_REG is misused in function
zend_jit_zval_copy_deref(). The second argument should be 32-bit long
and we fix it.
Note that simple test cases involving NaN are tested locally. I believe
it would get deeper testing by cmp_003.phpt(we will support it later).
[1]
https://developer.arm.com/documentation/dui0204/f/vector-floating-point-programming/vfp-instructions/fcmp?lang=en
[2] https://www.felixcloutier.com/x86/ucomisd
[3] https://en.wikipedia.org/wiki/Parity_flag
[4]
https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/condition-codes-4-floating-point-comparisons-using-vfp
[5]
https://community.arm.com/developer/ip-products/processors/b/processors-ip-blog/posts/condition-codes-1-condition-flags-and-codes
0 commit comments