blob: 87dac0261ee5ba2182d40b599daf57d2b00d8626 [file] [log] [blame]
Vladimir Marko80afd022015-05-19 18:08:00 +01001/*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef ART_RUNTIME_BASE_BIT_UTILS_H_
18#define ART_RUNTIME_BASE_BIT_UTILS_H_
19
Vladimir Marko80afd022015-05-19 18:08:00 +010020#include <limits>
21#include <type_traits>
22
Andreas Gampe58246a12016-09-26 12:51:53 -070023#include "base/logging.h"
Andreas Gampe5678db52017-06-08 14:11:18 -070024#include "base/stl_util_identity.h"
Vladimir Marko80afd022015-05-19 18:08:00 +010025
26namespace art {
27
buzbee31afbec2017-03-14 15:30:19 -070028// Like sizeof, but count how many bits a type takes. Pass type explicitly.
29template <typename T>
30constexpr size_t BitSizeOf() {
31 static_assert(std::is_integral<T>::value, "T must be integral");
32 using unsigned_type = typename std::make_unsigned<T>::type;
33 static_assert(sizeof(T) == sizeof(unsigned_type), "Unexpected type size mismatch!");
34 static_assert(std::numeric_limits<unsigned_type>::radix == 2, "Unexpected radix!");
35 return std::numeric_limits<unsigned_type>::digits;
36}
37
38// Like sizeof, but count how many bits a type takes. Infers type from parameter.
39template <typename T>
40constexpr size_t BitSizeOf(T /*x*/) {
41 return BitSizeOf<T>();
42}
43
Vladimir Marko80afd022015-05-19 18:08:00 +010044template<typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +010045constexpr int CLZ(T x) {
Vladimir Marko80afd022015-05-19 18:08:00 +010046 static_assert(std::is_integral<T>::value, "T must be integral");
Andreas Gampe151ab8d2015-08-14 23:01:49 +000047 static_assert(std::is_unsigned<T>::value, "T must be unsigned");
Vladimir Marko80afd022015-05-19 18:08:00 +010048 static_assert(sizeof(T) <= sizeof(long long), // NOLINT [runtime/int] [4]
49 "T too large, must be smaller than long long");
Vladimir Markof04cf542016-08-31 15:25:25 +010050 DCHECK_NE(x, 0u);
51 return (sizeof(T) == sizeof(uint32_t)) ? __builtin_clz(x) : __builtin_clzll(x);
Vladimir Marko80afd022015-05-19 18:08:00 +010052}
53
buzbee31afbec2017-03-14 15:30:19 -070054// Similar to CLZ except that on zero input it returns bitwidth and supports signed integers.
55template<typename T>
56constexpr int JAVASTYLE_CLZ(T x) {
57 static_assert(std::is_integral<T>::value, "T must be integral");
58 using unsigned_type = typename std::make_unsigned<T>::type;
59 return (x == 0) ? BitSizeOf<T>() : CLZ(static_cast<unsigned_type>(x));
60}
61
Vladimir Marko80afd022015-05-19 18:08:00 +010062template<typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +010063constexpr int CTZ(T x) {
Vladimir Marko80afd022015-05-19 18:08:00 +010064 static_assert(std::is_integral<T>::value, "T must be integral");
Andreas Gampe151ab8d2015-08-14 23:01:49 +000065 // It is not unreasonable to ask for trailing zeros in a negative number. As such, do not check
66 // that T is an unsigned type.
67 static_assert(sizeof(T) <= sizeof(long long), // NOLINT [runtime/int] [4]
68 "T too large, must be smaller than long long");
Vladimir Markof04cf542016-08-31 15:25:25 +010069 DCHECK_NE(x, static_cast<T>(0));
70 return (sizeof(T) == sizeof(uint32_t)) ? __builtin_ctz(x) : __builtin_ctzll(x);
Vladimir Marko80afd022015-05-19 18:08:00 +010071}
72
buzbee31afbec2017-03-14 15:30:19 -070073// Similar to CTZ except that on zero input it returns bitwidth and supports signed integers.
74template<typename T>
75constexpr int JAVASTYLE_CTZ(T x) {
76 static_assert(std::is_integral<T>::value, "T must be integral");
77 using unsigned_type = typename std::make_unsigned<T>::type;
78 return (x == 0) ? BitSizeOf<T>() : CTZ(static_cast<unsigned_type>(x));
79}
80
Roland Levillain0d5a2812015-11-13 10:07:31 +000081// Return the number of 1-bits in `x`.
Vladimir Marko80afd022015-05-19 18:08:00 +010082template<typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +010083constexpr int POPCOUNT(T x) {
84 return (sizeof(T) == sizeof(uint32_t)) ? __builtin_popcount(x) : __builtin_popcountll(x);
Vladimir Marko80afd022015-05-19 18:08:00 +010085}
86
buzbee31afbec2017-03-14 15:30:19 -070087// Swap bytes.
88template<typename T>
89constexpr T BSWAP(T x) {
90 if (sizeof(T) == sizeof(uint16_t)) {
91 return __builtin_bswap16(x);
92 } else if (sizeof(T) == sizeof(uint32_t)) {
93 return __builtin_bswap32(x);
94 } else {
95 return __builtin_bswap64(x);
96 }
97}
98
Vladimir Marko80afd022015-05-19 18:08:00 +010099// Find the bit position of the most significant bit (0-based), or -1 if there were no bits set.
100template <typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100101constexpr ssize_t MostSignificantBit(T value) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100102 static_assert(std::is_integral<T>::value, "T must be integral");
103 static_assert(std::is_unsigned<T>::value, "T must be unsigned");
104 static_assert(std::numeric_limits<T>::radix == 2, "Unexpected radix!");
105 return (value == 0) ? -1 : std::numeric_limits<T>::digits - 1 - CLZ(value);
106}
107
108// Find the bit position of the least significant bit (0-based), or -1 if there were no bits set.
109template <typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100110constexpr ssize_t LeastSignificantBit(T value) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100111 static_assert(std::is_integral<T>::value, "T must be integral");
112 static_assert(std::is_unsigned<T>::value, "T must be unsigned");
113 return (value == 0) ? -1 : CTZ(value);
114}
115
116// How many bits (minimally) does it take to store the constant 'value'? i.e. 1 for 1, 3 for 5, etc.
117template <typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100118constexpr size_t MinimumBitsToStore(T value) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100119 return static_cast<size_t>(MostSignificantBit(value) + 1);
120}
121
122template <typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100123constexpr T RoundUpToPowerOfTwo(T x) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100124 static_assert(std::is_integral<T>::value, "T must be integral");
125 static_assert(std::is_unsigned<T>::value, "T must be unsigned");
126 // NOTE: Undefined if x > (1 << (std::numeric_limits<T>::digits - 1)).
127 return (x < 2u) ? x : static_cast<T>(1u) << (std::numeric_limits<T>::digits - CLZ(x - 1u));
128}
129
Artem Serovf26bb6c2017-09-01 10:59:03 +0100130// Return highest possible N - a power of two - such that val >= N.
131template <typename T>
132constexpr T TruncToPowerOfTwo(T val) {
133 static_assert(std::is_integral<T>::value, "T must be integral");
134 static_assert(std::is_unsigned<T>::value, "T must be unsigned");
135 return (val != 0) ? static_cast<T>(1u) << (BitSizeOf<T>() - CLZ(val) - 1u) : 0;
136}
137
Vladimir Marko80afd022015-05-19 18:08:00 +0100138template<typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100139constexpr bool IsPowerOfTwo(T x) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100140 static_assert(std::is_integral<T>::value, "T must be integral");
141 // TODO: assert unsigned. There is currently many uses with signed values.
142 return (x & (x - 1)) == 0;
143}
144
145template<typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100146constexpr int WhichPowerOf2(T x) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100147 static_assert(std::is_integral<T>::value, "T must be integral");
148 // TODO: assert unsigned. There is currently many uses with signed values.
149 DCHECK((x != 0) && IsPowerOfTwo(x));
150 return CTZ(x);
151}
152
153// For rounding integers.
Vladimir Marko88b2b802015-12-04 14:19:04 +0000154// Note: Omit the `n` from T type deduction, deduce only from the `x` argument.
Vladimir Marko80afd022015-05-19 18:08:00 +0100155template<typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100156constexpr T RoundDown(T x, typename Identity<T>::type n) WARN_UNUSED;
Vladimir Marko80afd022015-05-19 18:08:00 +0100157
158template<typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100159constexpr T RoundDown(T x, typename Identity<T>::type n) {
160 DCHECK(IsPowerOfTwo(n));
161 return (x & -n);
Vladimir Marko80afd022015-05-19 18:08:00 +0100162}
163
164template<typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100165constexpr T RoundUp(T x, typename std::remove_reference<T>::type n) WARN_UNUSED;
Vladimir Marko80afd022015-05-19 18:08:00 +0100166
167template<typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100168constexpr T RoundUp(T x, typename std::remove_reference<T>::type n) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100169 return RoundDown(x + n - 1, n);
170}
171
172// For aligning pointers.
173template<typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100174inline T* AlignDown(T* x, uintptr_t n) WARN_UNUSED;
Vladimir Marko80afd022015-05-19 18:08:00 +0100175
176template<typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100177inline T* AlignDown(T* x, uintptr_t n) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100178 return reinterpret_cast<T*>(RoundDown(reinterpret_cast<uintptr_t>(x), n));
179}
180
181template<typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100182inline T* AlignUp(T* x, uintptr_t n) WARN_UNUSED;
Vladimir Marko80afd022015-05-19 18:08:00 +0100183
184template<typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100185inline T* AlignUp(T* x, uintptr_t n) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100186 return reinterpret_cast<T*>(RoundUp(reinterpret_cast<uintptr_t>(x), n));
187}
188
189template<int n, typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100190constexpr bool IsAligned(T x) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100191 static_assert((n & (n - 1)) == 0, "n is not a power of two");
192 return (x & (n - 1)) == 0;
193}
194
195template<int n, typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100196inline bool IsAligned(T* x) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100197 return IsAligned<n>(reinterpret_cast<const uintptr_t>(x));
198}
199
200template<typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100201inline bool IsAlignedParam(T x, int n) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100202 return (x & (n - 1)) == 0;
203}
204
Hiroshi Yamauchi3c3c4a12017-02-21 16:49:59 -0800205template<typename T>
206inline bool IsAlignedParam(T* x, int n) {
207 return IsAlignedParam(reinterpret_cast<const uintptr_t>(x), n);
208}
209
Vladimir Marko80afd022015-05-19 18:08:00 +0100210#define CHECK_ALIGNED(value, alignment) \
211 CHECK(::art::IsAligned<alignment>(value)) << reinterpret_cast<const void*>(value)
212
213#define DCHECK_ALIGNED(value, alignment) \
214 DCHECK(::art::IsAligned<alignment>(value)) << reinterpret_cast<const void*>(value)
215
Vladimir Markocf36d492015-08-12 19:27:26 +0100216#define CHECK_ALIGNED_PARAM(value, alignment) \
217 CHECK(::art::IsAlignedParam(value, alignment)) << reinterpret_cast<const void*>(value)
218
Vladimir Marko80afd022015-05-19 18:08:00 +0100219#define DCHECK_ALIGNED_PARAM(value, alignment) \
220 DCHECK(::art::IsAlignedParam(value, alignment)) << reinterpret_cast<const void*>(value)
221
Vladimir Markof04cf542016-08-31 15:25:25 +0100222inline uint16_t Low16Bits(uint32_t value) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100223 return static_cast<uint16_t>(value);
224}
225
Vladimir Markof04cf542016-08-31 15:25:25 +0100226inline uint16_t High16Bits(uint32_t value) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100227 return static_cast<uint16_t>(value >> 16);
228}
229
Vladimir Markof04cf542016-08-31 15:25:25 +0100230inline uint32_t Low32Bits(uint64_t value) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100231 return static_cast<uint32_t>(value);
232}
233
Vladimir Markof04cf542016-08-31 15:25:25 +0100234inline uint32_t High32Bits(uint64_t value) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100235 return static_cast<uint32_t>(value >> 32);
236}
237
238// Check whether an N-bit two's-complement representation can hold value.
239template <typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100240inline bool IsInt(size_t N, T value) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100241 if (N == BitSizeOf<T>()) {
242 return true;
243 } else {
244 CHECK_LT(0u, N);
245 CHECK_LT(N, BitSizeOf<T>());
246 T limit = static_cast<T>(1) << (N - 1u);
247 return (-limit <= value) && (value < limit);
248 }
249}
250
251template <typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100252constexpr T GetIntLimit(size_t bits) {
253 DCHECK_NE(bits, 0u);
254 DCHECK_LT(bits, BitSizeOf<T>());
255 return static_cast<T>(1) << (bits - 1);
Vladimir Marko80afd022015-05-19 18:08:00 +0100256}
257
258template <size_t kBits, typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100259constexpr bool IsInt(T value) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100260 static_assert(kBits > 0, "kBits cannot be zero.");
261 static_assert(kBits <= BitSizeOf<T>(), "kBits must be <= max.");
262 static_assert(std::is_signed<T>::value, "Needs a signed type.");
263 // Corner case for "use all bits." Can't use the limits, as they would overflow, but it is
264 // trivially true.
265 return (kBits == BitSizeOf<T>()) ?
266 true :
267 (-GetIntLimit<T>(kBits) <= value) && (value < GetIntLimit<T>(kBits));
268}
269
270template <size_t kBits, typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100271constexpr bool IsUint(T value) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100272 static_assert(kBits > 0, "kBits cannot be zero.");
273 static_assert(kBits <= BitSizeOf<T>(), "kBits must be <= max.");
274 static_assert(std::is_integral<T>::value, "Needs an integral type.");
275 // Corner case for "use all bits." Can't use the limits, as they would overflow, but it is
276 // trivially true.
277 // NOTE: To avoid triggering assertion in GetIntLimit(kBits+1) if kBits+1==BitSizeOf<T>(),
278 // use GetIntLimit(kBits)*2u. The unsigned arithmetic works well for us if it overflows.
Vladimir Markof04cf542016-08-31 15:25:25 +0100279 using unsigned_type = typename std::make_unsigned<T>::type;
Vladimir Marko80afd022015-05-19 18:08:00 +0100280 return (0 <= value) &&
281 (kBits == BitSizeOf<T>() ||
Vladimir Markof04cf542016-08-31 15:25:25 +0100282 (static_cast<unsigned_type>(value) <= GetIntLimit<unsigned_type>(kBits) * 2u - 1u));
Vladimir Marko80afd022015-05-19 18:08:00 +0100283}
284
285template <size_t kBits, typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100286constexpr bool IsAbsoluteUint(T value) {
Vladimir Marko80afd022015-05-19 18:08:00 +0100287 static_assert(kBits <= BitSizeOf<T>(), "kBits must be <= max.");
288 static_assert(std::is_integral<T>::value, "Needs an integral type.");
Vladimir Markof04cf542016-08-31 15:25:25 +0100289 using unsigned_type = typename std::make_unsigned<T>::type;
Vladimir Marko80afd022015-05-19 18:08:00 +0100290 return (kBits == BitSizeOf<T>())
291 ? true
292 : IsUint<kBits>(value < 0
293 ? static_cast<unsigned_type>(-1 - value) + 1u // Avoid overflow.
294 : static_cast<unsigned_type>(value));
295}
296
Chris Larsendbce0d72015-09-17 13:34:00 -0700297// Generate maximum/minimum values for signed/unsigned n-bit integers
298template <typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100299constexpr T MaxInt(size_t bits) {
300 DCHECK(std::is_unsigned<T>::value || bits > 0u) << "bits cannot be zero for signed.";
301 DCHECK_LE(bits, BitSizeOf<T>());
302 using unsigned_type = typename std::make_unsigned<T>::type;
303 return bits == BitSizeOf<T>()
304 ? std::numeric_limits<T>::max()
305 : std::is_signed<T>::value
306 ? ((bits == 1u) ? 0 : static_cast<T>(MaxInt<unsigned_type>(bits - 1)))
307 : static_cast<T>(UINT64_C(1) << bits) - static_cast<T>(1);
Chris Larsendbce0d72015-09-17 13:34:00 -0700308}
309
310template <typename T>
Vladimir Markof04cf542016-08-31 15:25:25 +0100311constexpr T MinInt(size_t bits) {
312 DCHECK(std::is_unsigned<T>::value || bits > 0) << "bits cannot be zero for signed.";
313 DCHECK_LE(bits, BitSizeOf<T>());
314 return bits == BitSizeOf<T>()
315 ? std::numeric_limits<T>::min()
316 : std::is_signed<T>::value
317 ? ((bits == 1u) ? -1 : static_cast<T>(-1) - MaxInt<T>(bits))
318 : static_cast<T>(0);
Chris Larsendbce0d72015-09-17 13:34:00 -0700319}
320
buzbee31afbec2017-03-14 15:30:19 -0700321// Returns value with bit set in lowest one-bit position or 0 if 0. (java.lang.X.lowestOneBit).
322template <typename kind>
323inline static kind LowestOneBitValue(kind opnd) {
324 // Hacker's Delight, Section 2-1
325 return opnd & -opnd;
326}
327
328// Returns value with bit set in hightest one-bit position or 0 if 0. (java.lang.X.highestOneBit).
329template <typename T>
330inline static T HighestOneBitValue(T opnd) {
331 using unsigned_type = typename std::make_unsigned<T>::type;
332 T res;
333 if (opnd == 0) {
334 res = 0;
335 } else {
336 int bit_position = BitSizeOf<T>() - (CLZ(static_cast<unsigned_type>(opnd)) + 1);
337 res = static_cast<T>(UINT64_C(1) << bit_position);
338 }
339 return res;
340}
341
342// Rotate bits.
343template <typename T, bool left>
344inline static T Rot(T opnd, int distance) {
345 int mask = BitSizeOf<T>() - 1;
346 int unsigned_right_shift = left ? (-distance & mask) : (distance & mask);
347 int signed_left_shift = left ? (distance & mask) : (-distance & mask);
348 using unsigned_type = typename std::make_unsigned<T>::type;
349 return (static_cast<unsigned_type>(opnd) >> unsigned_right_shift) | (opnd << signed_left_shift);
350}
351
352// TUNING: use rbit for arm/arm64
353inline static uint32_t ReverseBits32(uint32_t opnd) {
354 // Hacker's Delight 7-1
355 opnd = ((opnd >> 1) & 0x55555555) | ((opnd & 0x55555555) << 1);
356 opnd = ((opnd >> 2) & 0x33333333) | ((opnd & 0x33333333) << 2);
357 opnd = ((opnd >> 4) & 0x0F0F0F0F) | ((opnd & 0x0F0F0F0F) << 4);
358 opnd = ((opnd >> 8) & 0x00FF00FF) | ((opnd & 0x00FF00FF) << 8);
359 opnd = ((opnd >> 16)) | ((opnd) << 16);
360 return opnd;
361}
362
363// TUNING: use rbit for arm/arm64
364inline static uint64_t ReverseBits64(uint64_t opnd) {
365 // Hacker's Delight 7-1
366 opnd = (opnd & 0x5555555555555555L) << 1 | ((opnd >> 1) & 0x5555555555555555L);
367 opnd = (opnd & 0x3333333333333333L) << 2 | ((opnd >> 2) & 0x3333333333333333L);
368 opnd = (opnd & 0x0f0f0f0f0f0f0f0fL) << 4 | ((opnd >> 4) & 0x0f0f0f0f0f0f0f0fL);
369 opnd = (opnd & 0x00ff00ff00ff00ffL) << 8 | ((opnd >> 8) & 0x00ff00ff00ff00ffL);
370 opnd = (opnd << 48) | ((opnd & 0xffff0000L) << 16) | ((opnd >> 16) & 0xffff0000L) | (opnd >> 48);
371 return opnd;
372}
373
Vladimir Marko80afd022015-05-19 18:08:00 +0100374} // namespace art
375
376#endif // ART_RUNTIME_BASE_BIT_UTILS_H_