Replace RAPIDJSON_CLZLL with internal clzll (#1660)

RAPIDJSON_CLZLL is defined as macro of __builtin_clzll when
using gcc to compile. This introduces two issues:
1. in gcc __builtin_clzll returns int, not uint32_t.
2. __builtin_clzll return is undefined when input x is 0
See: https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html

This patch removes RAPIDJSON_CLZLL, merges __builtin_clzll to
internal clzll with input check and return value explicit cast.

Change-Id: Iac4b355dc5e5b4ed9b3f35a640b6b5537e76f22c
Signed-off-by: Jun He <jun.he@arm.com>

Co-authored-by: Jun He <jun.he@arm.com>
This commit is contained in:
Jun 2020-03-11 15:11:25 +08:00 committed by GitHub
parent 563fe5bbbe
commit 814bb27bf0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 18 additions and 19 deletions

View File

@ -29,10 +29,6 @@
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
namespace internal { namespace internal {
#if (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll)
#define RAPIDJSON_CLZLL __builtin_clzll
#else
inline uint32_t clzll(uint64_t x) { inline uint32_t clzll(uint64_t x) {
// Passing 0 to __builtin_clzll is UB in GCC and results in an // Passing 0 to __builtin_clzll is UB in GCC and results in an
// infinite loop in the software implementation. // infinite loop in the software implementation.
@ -52,7 +48,11 @@ inline uint32_t clzll(uint64_t x) {
#endif // _WIN64 #endif // _WIN64
return 63 - r; return 63 - r;
#elif (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll)
// __builtin_clzll wrapper
return static_cast<uint32_t>(__builtin_clzll(x));
#else #else
// naive version
uint32_t r; uint32_t r;
while (!(x & (static_cast<uint64_t>(1) << 63))) { while (!(x & (static_cast<uint64_t>(1) << 63))) {
x <<= 1; x <<= 1;
@ -64,7 +64,6 @@ inline uint32_t clzll(uint64_t x) {
} }
#define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll #define RAPIDJSON_CLZLL RAPIDJSON_NAMESPACE::internal::clzll
#endif // (defined(__GNUC__) && __GNUC__ >= 4) || RAPIDJSON_HAS_BUILTIN(__builtin_clzll)
} // namespace internal } // namespace internal
RAPIDJSON_NAMESPACE_END RAPIDJSON_NAMESPACE_END

View File

@ -100,7 +100,7 @@ struct DiyFp {
} }
DiyFp Normalize() const { DiyFp Normalize() const {
int s = static_cast<int>(RAPIDJSON_CLZLL(f)); int s = static_cast<int>(clzll(f));
return DiyFp(f << s, e - s); return DiyFp(f << s, e - s);
} }

View File

@ -450,11 +450,11 @@ inline const char *SkipWhitespace_SIMD(const char* p) {
if (low == 0) { if (low == 0) {
if (high != 0) { if (high != 0) {
uint32_t lz = RAPIDJSON_CLZLL(high); uint32_t lz = internal::clzll(high);
return p + 8 + (lz >> 3); return p + 8 + (lz >> 3);
} }
} else { } else {
uint32_t lz = RAPIDJSON_CLZLL(low); uint32_t lz = internal::clzll(low);
return p + (lz >> 3); return p + (lz >> 3);
} }
} }
@ -486,11 +486,11 @@ inline const char *SkipWhitespace_SIMD(const char* p, const char* end) {
if (low == 0) { if (low == 0) {
if (high != 0) { if (high != 0) {
uint32_t lz = RAPIDJSON_CLZLL(high); uint32_t lz = internal::clzll(high);
return p + 8 + (lz >> 3); return p + 8 + (lz >> 3);
} }
} else { } else {
uint32_t lz = RAPIDJSON_CLZLL(low); uint32_t lz = internal::clzll(low);
return p + (lz >> 3); return p + (lz >> 3);
} }
} }
@ -1257,12 +1257,12 @@ private:
bool escaped = false; bool escaped = false;
if (low == 0) { if (low == 0) {
if (high != 0) { if (high != 0) {
uint32_t lz = RAPIDJSON_CLZLL(high); uint32_t lz = internal::clzll(high);
length = 8 + (lz >> 3); length = 8 + (lz >> 3);
escaped = true; escaped = true;
} }
} else { } else {
uint32_t lz = RAPIDJSON_CLZLL(low); uint32_t lz = internal::clzll(low);
length = lz >> 3; length = lz >> 3;
escaped = true; escaped = true;
} }
@ -1327,12 +1327,12 @@ private:
bool escaped = false; bool escaped = false;
if (low == 0) { if (low == 0) {
if (high != 0) { if (high != 0) {
uint32_t lz = RAPIDJSON_CLZLL(high); uint32_t lz = internal::clzll(high);
length = 8 + (lz >> 3); length = 8 + (lz >> 3);
escaped = true; escaped = true;
} }
} else { } else {
uint32_t lz = RAPIDJSON_CLZLL(low); uint32_t lz = internal::clzll(low);
length = lz >> 3; length = lz >> 3;
escaped = true; escaped = true;
} }
@ -1381,12 +1381,12 @@ private:
if (low == 0) { if (low == 0) {
if (high != 0) { if (high != 0) {
uint32_t lz = RAPIDJSON_CLZLL(high); uint32_t lz = internal::clzll(high);
p += 8 + (lz >> 3); p += 8 + (lz >> 3);
break; break;
} }
} else { } else {
uint32_t lz = RAPIDJSON_CLZLL(low); uint32_t lz = internal::clzll(low);
p += lz >> 3; p += lz >> 3;
break; break;
} }

View File

@ -676,12 +676,12 @@ inline bool Writer<StringBuffer>::ScanWriteUnescapedString(StringStream& is, siz
bool escaped = false; bool escaped = false;
if (low == 0) { if (low == 0) {
if (high != 0) { if (high != 0) {
uint32_t lz = RAPIDJSON_CLZLL(high); uint32_t lz = internal::clzll(high);
len = 8 + (lz >> 3); len = 8 + (lz >> 3);
escaped = true; escaped = true;
} }
} else { } else {
uint32_t lz = RAPIDJSON_CLZLL(low); uint32_t lz = internal::clzll(low);
len = lz >> 3; len = lz >> 3;
escaped = true; escaped = true;
} }