Skip to content

Commit bffe3c2

Browse files
author
Jay Krell
committed
Much more complete int/int64/float/double punning.
In more central place. Reuse it. Optimize arm32, arm64, and depending on compiler flags 32bit x86.
1 parent 64998e4 commit bffe3c2

File tree

2 files changed

+38
-9
lines changed

2 files changed

+38
-9
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__) || defined(_MSC_VER)
14+
#include <intrin.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_) || _M_IX86_FP >= 2 || defined(__AVX__)
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(x)));
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_) || _M_IX86_FP >= 2 || defined(__AVX__)
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 & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,7 @@ namespace Js
147147

148148
inline Var JavascriptNumber::ToVar(double value)
149149
{
150-
#if defined(_MSC_VER) && defined(_AMD64_)
151-
uint64 val = _mm_cvtsi128_si64(_mm_castpd_si128(_mm_set_sd(value)));
152-
#else
153-
uint64 val = *(uint64*)&value;
154-
#endif
150+
const uint64 val = ToSpecial(value);
155151
AssertMsg(!IsNan(value) || ToSpecial(value) == k_NegativeNan || ToSpecial(value) == 0x7FF8000000000000ull, "We should only produce a NaN with this value");
156152
return reinterpret_cast<Var>(val ^ FloatTag_Value);
157153
}

0 commit comments

Comments
 (0)