1 | #ifndef SIMDJSON_HASWELL_BITMANIPULATION_H |
2 | #define SIMDJSON_HASWELL_BITMANIPULATION_H |
3 | |
4 | #include "simdjson/common_defs.h" |
5 | |
6 | #ifdef IS_X86_64 |
7 | #include "haswell/intrinsics.h" |
8 | |
9 | TARGET_HASWELL |
10 | namespace simdjson::haswell { |
11 | |
12 | #ifndef _MSC_VER |
13 | // We sometimes call trailing_zero on inputs that are zero, |
14 | // but the algorithms do not end up using the returned value. |
15 | // Sadly, sanitizers are not smart enough to figure it out. |
16 | __attribute__((no_sanitize("undefined" ))) // this is deliberate |
17 | #endif |
18 | really_inline int trailing_zeroes(uint64_t input_num) { |
19 | #ifdef _MSC_VER |
20 | return (int)_tzcnt_u64(input_num); |
21 | #else |
22 | //////// |
23 | // You might expect the next line to be equivalent to |
24 | // return (int)_tzcnt_u64(input_num); |
25 | // but the generated code differs and might be less efficient? |
26 | //////// |
27 | return __builtin_ctzll(input_num); |
28 | #endif// _MSC_VER |
29 | } |
30 | |
31 | /* result might be undefined when input_num is zero */ |
32 | really_inline uint64_t clear_lowest_bit(uint64_t input_num) { |
33 | return _blsr_u64(input_num); |
34 | } |
35 | |
36 | /* result might be undefined when input_num is zero */ |
37 | really_inline int leading_zeroes(uint64_t input_num) { |
38 | return static_cast<int>(_lzcnt_u64(input_num)); |
39 | } |
40 | |
41 | really_inline int hamming(uint64_t input_num) { |
42 | #ifdef _MSC_VER |
43 | // note: we do not support legacy 32-bit Windows |
44 | return __popcnt64(input_num);// Visual Studio wants two underscores |
45 | #else |
46 | return _popcnt64(input_num); |
47 | #endif |
48 | } |
49 | |
50 | really_inline bool add_overflow(uint64_t value1, uint64_t value2, |
51 | uint64_t *result) { |
52 | #ifdef _MSC_VER |
53 | return _addcarry_u64(0, value1, value2, |
54 | reinterpret_cast<unsigned __int64 *>(result)); |
55 | #else |
56 | return __builtin_uaddll_overflow(value1, value2, |
57 | (unsigned long long *)result); |
58 | #endif |
59 | } |
60 | |
61 | #ifdef _MSC_VER |
62 | #pragma intrinsic(_umul128) |
63 | #endif |
64 | really_inline bool mul_overflow(uint64_t value1, uint64_t value2, |
65 | uint64_t *result) { |
66 | #ifdef _MSC_VER |
67 | uint64_t high; |
68 | *result = _umul128(value1, value2, &high); |
69 | return high; |
70 | #else |
71 | return __builtin_umulll_overflow(value1, value2, |
72 | (unsigned long long *)result); |
73 | #endif |
74 | } |
75 | }// namespace simdjson::haswell |
76 | UNTARGET_REGION |
77 | #endif |
78 | #endif // SIMDJSON_HASWELL_BITMANIPULATION_H |
79 | |