Skip to content

Commit

Permalink
<xcharconv_ryu.h>: Fix __ryu_shiftright128 for ARM64 (#4304)
Browse files Browse the repository at this point in the history
  • Loading branch information
StephanTLavavej authored Jan 11, 2024
1 parent 77036d6 commit 3eac329
Showing 1 changed file with 10 additions and 19 deletions.
29 changes: 10 additions & 19 deletions stl/inc/xcharconv_ryu.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,28 +193,19 @@ _NODISCARD __forceinline uint64_t __ryu_umul128(const uint64_t __a, const uint64
#endif // ^^^ intrinsics unavailable ^^^

_NODISCARD inline uint64_t __ryu_shiftright128(const uint64_t __lo, const uint64_t __hi, const uint32_t __dist) {
#if defined(_M_X64) && !defined(_M_ARM64EC)
// For the __shiftright128 intrinsic, the shift value is always
// modulo 64.
// In the current implementation of the double-precision version
// of Ryu, the shift value is always < 64.
// (The shift value is in the range [49, 58].)
// Check this here in case a future change requires larger shift
// values. In this case this function needs to be adjusted.
// In the current implementation, the shift value is always < 64.
// If larger shift values are ever required, this function will need to be adjusted.
_STL_INTERNAL_CHECK(__dist < 64);

#if defined(_M_X64) && !defined(_M_ARM64EC)
return __shiftright128(__lo, __hi, static_cast<unsigned char>(__dist));
#else // ^^^ defined(_M_X64) && !defined(_M_ARM64EC) / !defined(_M_X64) || defined(_M_ARM64EC) vvv
// We don't need to handle the case __dist >= 64 here (see above).
_STL_INTERNAL_CHECK(__dist < 64);
#if defined(_WIN64) || defined(_M_HYBRID_X86_ARM64)
_STL_INTERNAL_CHECK(__dist > 0);
#else // ^^^ __shiftright128 intrinsic available / __shiftright128 intrinsic unavailable vvv
if (__dist == 0) {
return __lo;
}

return (__hi << (64 - __dist)) | (__lo >> __dist);
#else // ^^^ 64-bit or _M_HYBRID_X86_ARM64 / 32-bit vvv
// Avoid a 64-bit shift by taking advantage of the range of shift values.
_STL_INTERNAL_CHECK(__dist >= 32);
return (__hi << (64 - __dist)) | (static_cast<uint32_t>(__lo >> 32) >> (__dist - 32));
#endif // ^^^ 32-bit ^^^
#endif // defined(_M_X64) && !defined(_M_ARM64EC)
#endif // ^^^ __shiftright128 intrinsic unavailable ^^^
}


Expand Down

0 comments on commit 3eac329

Please sign in to comment.