From 504dcd7001fcdf4e6dd9ff5e6084432589a115a8 Mon Sep 17 00:00:00 2001 From: Pat Gavlin Date: Mon, 10 Apr 2017 14:17:08 -0700 Subject: Fix VSO bug 405852. This bug was due to a mismatch between the semantics of the FP modulus operator as specified by ECMA-335 and as implemented by value numbering. ECMA-335 requires the following behavior for FP modulus: - If the divisor is 0 or the dividend is not finite, the result is NaN - If the divisor is not finite and is not NaN, the result is the dividend. Value numbering, however, simply used `fmod`, which does not have these semantics. This change implements the required semantics in VN. --- src/jit/valuenum.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/jit/valuenum.cpp b/src/jit/valuenum.cpp index 66b7978674..2de83065b5 100644 --- a/src/jit/valuenum.cpp +++ b/src/jit/valuenum.cpp @@ -206,6 +206,52 @@ T ValueNumStore::EvalOp(VNFunc vnf, T v0, T v1, ValueNum* pExcSet) } } +struct FloatTraits +{ + static float NaN() + { + unsigned bits = 0xFFC00000u; + float result; + static_assert(sizeof(bits) == sizeof(result), "sizeof(unsigned) must equal sizeof(float)"); + memcpy(&result, &bits, sizeof(result)); + return result; + } +}; + +struct DoubleTraits +{ + static double NaN() + { + unsigned long long bits = 0xFFF8000000000000ull; + double result; + static_assert(sizeof(bits) == sizeof(result), "sizeof(unsigned long long) must equal sizeof(double)"); + memcpy(&result, &bits, sizeof(result)); + return result; + } +}; + +template +TFp FpRem(TFp dividend, TFp divisor) +{ + // From the ECMA standard: + // + // If [divisor] is zero or [dividend] is infinity + // the result is NaN. + // If [divisor] is infinity, + // the result is [dividend] + + if (divisor == 0 || !_finite(dividend)) + { + return TFpTraits::NaN(); + } + else if (!_finite(divisor) && !_isnan(divisor)) + { + return dividend; + } + + return (TFp)fmod((double)dividend, (double)divisor); +} + // Specialize for double for floating operations, that doesn't involve unsigned. template <> double ValueNumStore::EvalOp(VNFunc vnf, double v0, double v1, ValueNum* pExcSet) @@ -223,7 +269,7 @@ double ValueNumStore::EvalOp(VNFunc vnf, double v0, double v1, ValueNum* case GT_DIV: return v0 / v1; case GT_MOD: - return fmod(v0, v1); + return FpRem(v0, v1); default: unreached(); @@ -247,7 +293,7 @@ float ValueNumStore::EvalOp(VNFunc vnf, float v0, float v1, ValueNum* pEx case GT_DIV: return v0 / v1; case GT_MOD: - return fmodf(v0, v1); + return FpRem(v0, v1); default: unreached(); -- cgit v1.2.3 From 58aaf6eaea69afb2f32a1503cc189864b0c0ff82 Mon Sep 17 00:00:00 2001 From: Pat Gavlin Date: Mon, 10 Apr 2017 15:13:58 -0700 Subject: Format code. --- src/jit/valuenum.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/jit/valuenum.cpp b/src/jit/valuenum.cpp index 2de83065b5..03bc204070 100644 --- a/src/jit/valuenum.cpp +++ b/src/jit/valuenum.cpp @@ -211,7 +211,7 @@ struct FloatTraits static float NaN() { unsigned bits = 0xFFC00000u; - float result; + float result; static_assert(sizeof(bits) == sizeof(result), "sizeof(unsigned) must equal sizeof(float)"); memcpy(&result, &bits, sizeof(result)); return result; @@ -223,7 +223,7 @@ struct DoubleTraits static double NaN() { unsigned long long bits = 0xFFF8000000000000ull; - double result; + double result; static_assert(sizeof(bits) == sizeof(result), "sizeof(unsigned long long) must equal sizeof(double)"); memcpy(&result, &bits, sizeof(result)); return result; -- cgit v1.2.3