Skip to content

Commit f2e1723

Browse files
committed
[MERGE #5890 @jaykrell] Use intrinsic to get double as int, instead of taking address which challenges the compiler.
Merge pull request #5890 from jaykrell:double-to-int.1
2 parents c2168c6 + 03fca92 commit f2e1723

File tree

3 files changed

+40
-5
lines changed

3 files changed

+40
-5
lines changed

lib/Common/Common/NumberUtilities.inl

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@
77
#define NUMBER_UTIL_INLINE
88
#endif
99

10+
// Attempt to pun int/float without address-taking.
11+
// This helps compilers.
12+
13+
#if defined(_AMD64_) || _M_IX86_FP >= 2 || defined(__AVX__)
14+
#include <immintrin.h>
15+
#endif
16+
1017
#if !defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)
1118
#if defined(_MSC_VER) // WINDOWS
1219

@@ -136,16 +143,18 @@ namespace Js
136143

137144
NUMBER_UTIL_INLINE bool NumberUtilities::IsNan(double value)
138145
{
146+
const uint64 nCompare = ToSpecial(value);
139147
#if defined(TARGET_64)
140148
// NaN is a range of values; all bits on the exponent are 1's
141149
// and some nonzero significant. No distinction on signed NaN's.
142-
uint64 nCompare = ToSpecial(value);
143-
bool isNan = (0 == (~nCompare & 0x7FF0000000000000ull) &&
150+
const bool isNan = (0 == (~nCompare & 0x7FF0000000000000ull) &&
144151
0 != (nCompare & 0x000FFFFFFFFFFFFFull));
145152
return isNan;
146153
#else
147-
return 0 == (~Js::NumberUtilities::LuHiDbl(value) & 0x7FF00000) &&
148-
(0 != Js::NumberUtilities::LuLoDbl(value) || 0 != (Js::NumberUtilities::LuHiDbl(value) & 0x000FFFFF));
154+
const uint32 hi = (uint32)(nCompare >> 32);
155+
const uint32 lo = (uint32)nCompare;
156+
return 0 == (~hi & 0x7FF00000) &&
157+
(0 != lo || 0 != (hi & 0x000FFFFF));
149158
#endif
150159
}
151160

@@ -165,22 +174,46 @@ namespace Js
165174

166175
NUMBER_UTIL_INLINE uint64 NumberUtilities::ToSpecial(double value)
167176
{
177+
#if defined(_AMD64_)
178+
return _mm_cvtsi128_si64(_mm_castpd_si128(_mm_set_sd(value)));
179+
#elif defined(_M_ARM32_OR_ARM64)
180+
return _CopyInt64FromDouble(value);
181+
#else
168182
return *(reinterpret_cast<uint64 *>(&value));
183+
#endif
169184
}
170185

171186
NUMBER_UTIL_INLINE uint32 NumberUtilities::ToSpecial(float value)
172187
{
188+
#if defined(_AMD64_) || _M_IX86_FP >= 2 || defined(__AVX__)
189+
return _mm_cvtsi128_si32(_mm_castps_si128(_mm_set_ss(value)));
190+
#elif defined(_M_ARM32_OR_ARM64)
191+
return _CopyInt32FromFloat(value);
192+
#else
173193
return *(reinterpret_cast<uint32 *>(&value));
194+
#endif
174195
}
175196

176197
NUMBER_UTIL_INLINE float NumberUtilities::ReinterpretBits(int value)
177198
{
199+
#if defined(_AMD64_) || _M_IX86_FP >= 2 || defined(__AVX__)
200+
return _mm_cvtss_f32(_mm_castsi128_ps(_mm_cvtsi32_si128(value)));
201+
#elif defined(_M_ARM32_OR_ARM64)
202+
return _CopyFloatFromInt32(value);
203+
#else
178204
return *(reinterpret_cast<float *>(&value));
205+
#endif
179206
}
180207

181208
NUMBER_UTIL_INLINE double NumberUtilities::ReinterpretBits(int64 value)
182209
{
210+
#if defined(_AMD64_)
211+
return _mm_cvtsd_f64(_mm_castsi128_pd(_mm_cvtsi64_si128(value)));
212+
#elif defined(_M_ARM32_OR_ARM64)
213+
return _CopyDoubleFromInt64(value);
214+
#else
183215
return *(reinterpret_cast<double *>(&value));
216+
#endif
184217
}
185218

186219
NUMBER_UTIL_INLINE bool NumberUtilities::IsFloat32NegZero(float value)

lib/Runtime/Library/JavascriptNumber.inl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ namespace Js
147147

148148
inline Var JavascriptNumber::ToVar(double value)
149149
{
150-
uint64 val = *(uint64*)&value;
150+
const uint64 val = ToSpecial(value);
151151
AssertMsg(!IsNan(value) || ToSpecial(value) == k_NegativeNan || ToSpecial(value) == 0x7FF8000000000000ull, "We should only produce a NaN with this value");
152152
return reinterpret_cast<Var>(val ^ FloatTag_Value);
153153
}

lib/Runtime/Math/WasmMath.inl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,8 @@ DstType WasmMath::ConvertFloatToInt(SrcType srcVal, _In_ Js::ScriptContext * scr
155155
return 0;
156156
}
157157

158+
// TODO NumberUtilities::ToSpecial
159+
158160
ReinterpretType val = *reinterpret_cast<ReinterpretType*> (&srcVal);
159161
if (MaxCmp(val, Max) || (val >= NegZero && NegOneCmp(val, NegOne)))
160162
{

0 commit comments

Comments
 (0)