Skip to content

Commit b973e2e

Browse files
committed
[libc++] Introduce __bits
It has the low-level bit fiddling operations from bit. It eliminates a cyclic dependency between __bit_reference, bits, and vector. I want to exploit this in later patches. Reviewed By: #libc, ldionne Differential Revision: https://reviews.llvm.org/D94908
1 parent ea2cfda commit b973e2e

File tree

5 files changed

+150
-117
lines changed

5 files changed

+150
-117
lines changed

libcxx/include/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
set(files
22
__availability
33
__bit_reference
4+
__bits
45
__bsd_locale_defaults.h
56
__bsd_locale_fallbacks.h
67
__debug

libcxx/include/__bit_reference

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#define _LIBCPP___BIT_REFERENCE
1212

1313
#include <__config>
14-
#include <bit>
14+
#include <__bits>
1515
#include <algorithm>
1616

1717
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)

libcxx/include/__bits

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// -*- C++ -*-
2+
//===----------------------------------------------------------------------===//
3+
//
4+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef _LIBCPP___BITS
11+
#define _LIBCPP___BITS
12+
13+
#include <__config>
14+
15+
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
16+
#pragma GCC system_header
17+
#endif
18+
19+
_LIBCPP_PUSH_MACROS
20+
#include <__undef_macros>
21+
22+
23+
_LIBCPP_BEGIN_NAMESPACE_STD
24+
25+
#ifndef _LIBCPP_COMPILER_MSVC
26+
27+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
28+
int __libcpp_ctz(unsigned __x) _NOEXCEPT { return __builtin_ctz(__x); }
29+
30+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
31+
int __libcpp_ctz(unsigned long __x) _NOEXCEPT { return __builtin_ctzl(__x); }
32+
33+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
34+
int __libcpp_ctz(unsigned long long __x) _NOEXCEPT { return __builtin_ctzll(__x); }
35+
36+
37+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
38+
int __libcpp_clz(unsigned __x) _NOEXCEPT { return __builtin_clz(__x); }
39+
40+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
41+
int __libcpp_clz(unsigned long __x) _NOEXCEPT { return __builtin_clzl(__x); }
42+
43+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
44+
int __libcpp_clz(unsigned long long __x) _NOEXCEPT { return __builtin_clzll(__x); }
45+
46+
47+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
48+
int __libcpp_popcount(unsigned __x) _NOEXCEPT { return __builtin_popcount(__x); }
49+
50+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
51+
int __libcpp_popcount(unsigned long __x) _NOEXCEPT { return __builtin_popcountl(__x); }
52+
53+
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
54+
int __libcpp_popcount(unsigned long long __x) _NOEXCEPT { return __builtin_popcountll(__x); }
55+
56+
#else // _LIBCPP_COMPILER_MSVC
57+
58+
// Precondition: __x != 0
59+
inline _LIBCPP_INLINE_VISIBILITY
60+
int __libcpp_ctz(unsigned __x) {
61+
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
62+
static_assert(sizeof(unsigned long) == 4, "");
63+
unsigned long __where;
64+
if (_BitScanForward(&__where, __x))
65+
return static_cast<int>(__where);
66+
return 32;
67+
}
68+
69+
inline _LIBCPP_INLINE_VISIBILITY
70+
int __libcpp_ctz(unsigned long __x) {
71+
static_assert(sizeof(unsigned long) == sizeof(unsigned), "");
72+
return __ctz(static_cast<unsigned>(__x));
73+
}
74+
75+
inline _LIBCPP_INLINE_VISIBILITY
76+
int __libcpp_ctz(unsigned long long __x) {
77+
unsigned long __where;
78+
#if defined(_LIBCPP_HAS_BITSCAN64)
79+
(defined(_M_AMD64) || defined(__x86_64__))
80+
if (_BitScanForward64(&__where, __x))
81+
return static_cast<int>(__where);
82+
#else
83+
// Win32 doesn't have _BitScanForward64 so emulate it with two 32 bit calls.
84+
if (_BitScanForward(&__where, static_cast<unsigned long>(__x)))
85+
return static_cast<int>(__where);
86+
if (_BitScanForward(&__where, static_cast<unsigned long>(__x >> 32)))
87+
return static_cast<int>(__where + 32);
88+
#endif
89+
return 64;
90+
}
91+
92+
// Precondition: __x != 0
93+
inline _LIBCPP_INLINE_VISIBILITY
94+
int __libcpp_clz(unsigned __x) {
95+
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
96+
static_assert(sizeof(unsigned long) == 4, "");
97+
unsigned long __where;
98+
if (_BitScanReverse(&__where, __x))
99+
return static_cast<int>(31 - __where);
100+
return 32; // Undefined Behavior.
101+
}
102+
103+
inline _LIBCPP_INLINE_VISIBILITY
104+
int __libcpp_clz(unsigned long __x) {
105+
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
106+
return __libcpp_clz(static_cast<unsigned>(__x));
107+
}
108+
109+
inline _LIBCPP_INLINE_VISIBILITY
110+
int __libcpp_clz(unsigned long long __x) {
111+
unsigned long __where;
112+
#if defined(_LIBCPP_HAS_BITSCAN64)
113+
if (_BitScanReverse64(&__where, __x))
114+
return static_cast<int>(63 - __where);
115+
#else
116+
// Win32 doesn't have _BitScanReverse64 so emulate it with two 32 bit calls.
117+
if (_BitScanReverse(&__where, static_cast<unsigned long>(__x >> 32)))
118+
return static_cast<int>(63 - (__where + 32));
119+
if (_BitScanReverse(&__where, static_cast<unsigned long>(__x)))
120+
return static_cast<int>(63 - __where);
121+
#endif
122+
return 64; // Undefined Behavior.
123+
}
124+
125+
inline _LIBCPP_INLINE_VISIBILITY int __libcpp_popcount(unsigned __x) {
126+
static_assert(sizeof(unsigned) == 4, "");
127+
return __popcnt(__x);
128+
}
129+
130+
inline _LIBCPP_INLINE_VISIBILITY int __libcpp_popcount(unsigned long __x) {
131+
static_assert(sizeof(unsigned long) == 4, "");
132+
return __popcnt(__x);
133+
}
134+
135+
inline _LIBCPP_INLINE_VISIBILITY int __libcpp_popcount(unsigned long long __x) {
136+
static_assert(sizeof(unsigned long long) == 8, "");
137+
return __popcnt64(__x);
138+
}
139+
140+
#endif // _LIBCPP_COMPILER_MSVC
141+
142+
_LIBCPP_END_NAMESPACE_STD
143+
144+
_LIBCPP_POP_MACROS
145+
146+
#endif // _LIBCPP__BITS

libcxx/include/bit

+1-116
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ namespace std {
5555
*/
5656

5757
#include <__config>
58+
#include <__bits>
5859
#include <limits>
5960
#include <type_traits>
6061
#include <version>
@@ -76,122 +77,6 @@ _LIBCPP_PUSH_MACROS
7677

7778
_LIBCPP_BEGIN_NAMESPACE_STD
7879

79-
#ifndef _LIBCPP_COMPILER_MSVC
80-
81-
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
82-
int __libcpp_ctz(unsigned __x) _NOEXCEPT { return __builtin_ctz(__x); }
83-
84-
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
85-
int __libcpp_ctz(unsigned long __x) _NOEXCEPT { return __builtin_ctzl(__x); }
86-
87-
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
88-
int __libcpp_ctz(unsigned long long __x) _NOEXCEPT { return __builtin_ctzll(__x); }
89-
90-
91-
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
92-
int __libcpp_clz(unsigned __x) _NOEXCEPT { return __builtin_clz(__x); }
93-
94-
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
95-
int __libcpp_clz(unsigned long __x) _NOEXCEPT { return __builtin_clzl(__x); }
96-
97-
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
98-
int __libcpp_clz(unsigned long long __x) _NOEXCEPT { return __builtin_clzll(__x); }
99-
100-
101-
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
102-
int __libcpp_popcount(unsigned __x) _NOEXCEPT { return __builtin_popcount(__x); }
103-
104-
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
105-
int __libcpp_popcount(unsigned long __x) _NOEXCEPT { return __builtin_popcountl(__x); }
106-
107-
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR
108-
int __libcpp_popcount(unsigned long long __x) _NOEXCEPT { return __builtin_popcountll(__x); }
109-
110-
#else // _LIBCPP_COMPILER_MSVC
111-
112-
// Precondition: __x != 0
113-
inline _LIBCPP_INLINE_VISIBILITY
114-
int __libcpp_ctz(unsigned __x) {
115-
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
116-
static_assert(sizeof(unsigned long) == 4, "");
117-
unsigned long __where;
118-
if (_BitScanForward(&__where, __x))
119-
return static_cast<int>(__where);
120-
return 32;
121-
}
122-
123-
inline _LIBCPP_INLINE_VISIBILITY
124-
int __libcpp_ctz(unsigned long __x) {
125-
static_assert(sizeof(unsigned long) == sizeof(unsigned), "");
126-
return __ctz(static_cast<unsigned>(__x));
127-
}
128-
129-
inline _LIBCPP_INLINE_VISIBILITY
130-
int __libcpp_ctz(unsigned long long __x) {
131-
unsigned long __where;
132-
#if defined(_LIBCPP_HAS_BITSCAN64)
133-
(defined(_M_AMD64) || defined(__x86_64__))
134-
if (_BitScanForward64(&__where, __x))
135-
return static_cast<int>(__where);
136-
#else
137-
// Win32 doesn't have _BitScanForward64 so emulate it with two 32 bit calls.
138-
if (_BitScanForward(&__where, static_cast<unsigned long>(__x)))
139-
return static_cast<int>(__where);
140-
if (_BitScanForward(&__where, static_cast<unsigned long>(__x >> 32)))
141-
return static_cast<int>(__where + 32);
142-
#endif
143-
return 64;
144-
}
145-
146-
// Precondition: __x != 0
147-
inline _LIBCPP_INLINE_VISIBILITY
148-
int __libcpp_clz(unsigned __x) {
149-
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
150-
static_assert(sizeof(unsigned long) == 4, "");
151-
unsigned long __where;
152-
if (_BitScanReverse(&__where, __x))
153-
return static_cast<int>(31 - __where);
154-
return 32; // Undefined Behavior.
155-
}
156-
157-
inline _LIBCPP_INLINE_VISIBILITY
158-
int __libcpp_clz(unsigned long __x) {
159-
static_assert(sizeof(unsigned) == sizeof(unsigned long), "");
160-
return __libcpp_clz(static_cast<unsigned>(__x));
161-
}
162-
163-
inline _LIBCPP_INLINE_VISIBILITY
164-
int __libcpp_clz(unsigned long long __x) {
165-
unsigned long __where;
166-
#if defined(_LIBCPP_HAS_BITSCAN64)
167-
if (_BitScanReverse64(&__where, __x))
168-
return static_cast<int>(63 - __where);
169-
#else
170-
// Win32 doesn't have _BitScanReverse64 so emulate it with two 32 bit calls.
171-
if (_BitScanReverse(&__where, static_cast<unsigned long>(__x >> 32)))
172-
return static_cast<int>(63 - (__where + 32));
173-
if (_BitScanReverse(&__where, static_cast<unsigned long>(__x)))
174-
return static_cast<int>(63 - __where);
175-
#endif
176-
return 64; // Undefined Behavior.
177-
}
178-
179-
inline _LIBCPP_INLINE_VISIBILITY int __libcpp_popcount(unsigned __x) {
180-
static_assert(sizeof(unsigned) == 4, "");
181-
return __popcnt(__x);
182-
}
183-
184-
inline _LIBCPP_INLINE_VISIBILITY int __libcpp_popcount(unsigned long __x) {
185-
static_assert(sizeof(unsigned long) == 4, "");
186-
return __popcnt(__x);
187-
}
188-
189-
inline _LIBCPP_INLINE_VISIBILITY int __libcpp_popcount(unsigned long long __x) {
190-
static_assert(sizeof(unsigned long long) == 8, "");
191-
return __popcnt64(__x);
192-
}
193-
194-
#endif // _LIBCPP_COMPILER_MSVC
19580

19681
template <class _Tp>
19782
using __bitop_unsigned_integer _LIBCPP_NODEBUG_TYPE = integral_constant<bool,

libcxx/include/module.modulemap

+1
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,7 @@ module std [system] {
522522
}
523523

524524
// FIXME: These should be private.
525+
module __bits { header "__bits" export * }
525526
module __bit_reference { header "__bit_reference" export * }
526527
module __debug { header "__debug" export * }
527528
module __errc { header "__errc" export * }

0 commit comments

Comments
 (0)