Fix Frexp() for subnormal arguments under DAZ
Previously only an all-zero exponent and mantissa field was considered
equal to zero. When denormals-are-zero mode (DAZ) is enabled, currently
the default, we should treat subnormals as zero as well. This is
accomplished using a floating- point compare operation instead of
integer comparison.
Note that, just like the previous implementation, this still does not
handle subnormals correctly when DAZ mode is not enabled. To return a
significand in the range [0.5, 1.0) it will have to support returning
an exponent smaller than -126.
Bug: b/243791551
Bug: b/169904252
Change-Id: I67b7a5a8e971a0290aa5cedb55acae6e70f9485c
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/67828
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/ShaderCore.cpp b/src/Pipeline/ShaderCore.cpp
index 780f4f8..66eaf79 100644
--- a/src/Pipeline/ShaderCore.cpp
+++ b/src/Pipeline/ShaderCore.cpp
@@ -516,11 +516,12 @@
std::pair<SIMD::Float, SIMD::Int> Frexp(RValue<SIMD::Float> val)
{
// Assumes IEEE 754
- auto v = As<SIMD::UInt>(val);
- auto isNotZero = CmpNEQ(v & 0x7FFFFFFF, 0);
+ auto isNotZero = CmpNEQ(val, 0.0f);
+ auto v = As<SIMD::Int>(val);
auto zeroSign = v & 0x80000000 & ~isNotZero;
auto significand = As<SIMD::Float>((((v & 0x807FFFFF) | 0x3F000000) & isNotZero) | zeroSign);
- auto exponent = Exponent(val) & SIMD::Int(isNotZero);
+
+ auto exponent = Exponent(val) & isNotZero;
return std::make_pair(significand, exponent);
}