summaryrefslogtreecommitdiff
path: root/runtime/base/bit_utils.h
diff options
context:
space:
mode:
author Andreas Gampe <agampe@google.com> 2015-08-13 20:55:31 -0700
committer Andreas Gampe <agampe@google.com> 2015-08-13 21:29:48 -0700
commit51db2c217052fd6881b81f3ac5162fe88c36dbf0 (patch)
tree14d724a828b5ba00889160c2b42095273b7d593c /runtime/base/bit_utils.h
parent060841a3966afc7a5251134d1f1ef100849b1468 (diff)
ART: DCHECK zero case for CLZ/CTZ
Add a DCHECK_CONSTEXPR. All current callers have an explicit zero check before hand and so we should not trip this at the moment. Remove the TODO. Add the check for T being unsigned for CLZ (trivial fix for leb128.h). We use CTZ with signed types. Change-Id: I7bbf0b1699eed21715c6cc20dbfe22b7da403b1a
Diffstat (limited to 'runtime/base/bit_utils.h')
-rw-r--r--runtime/base/bit_utils.h23
1 files changed, 15 insertions, 8 deletions
diff --git a/runtime/base/bit_utils.h b/runtime/base/bit_utils.h
index 6f45dc8209..332012bda9 100644
--- a/runtime/base/bit_utils.h
+++ b/runtime/base/bit_utils.h
@@ -29,21 +29,28 @@ namespace art {
template<typename T>
static constexpr int CLZ(T x) {
static_assert(std::is_integral<T>::value, "T must be integral");
- // TODO: assert unsigned. There is currently many uses with signed values.
+ static_assert(std::is_unsigned<T>::value, "T must be unsigned");
static_assert(sizeof(T) <= sizeof(long long), // NOLINT [runtime/int] [4]
"T too large, must be smaller than long long");
- return (sizeof(T) == sizeof(uint32_t))
- ? __builtin_clz(x) // TODO: __builtin_clz[ll] has undefined behavior for x=0
- : __builtin_clzll(x);
+ return
+ DCHECK_CONSTEXPR(x != 0, "x must not be zero", T(0))
+ (sizeof(T) == sizeof(uint32_t))
+ ? __builtin_clz(x)
+ : __builtin_clzll(x);
}
template<typename T>
static constexpr int CTZ(T x) {
static_assert(std::is_integral<T>::value, "T must be integral");
- // TODO: assert unsigned. There is currently many uses with signed values.
- return (sizeof(T) == sizeof(uint32_t))
- ? __builtin_ctz(x)
- : __builtin_ctzll(x);
+ // A similar check to the above does not make sense. It isn't as non-intuitive to ask for
+ // trailing zeros in a negative number, and the quick backends do this for immediate encodings.
+ static_assert(sizeof(T) <= sizeof(long long), // NOLINT [runtime/int] [4]
+ "T too large, must be smaller than long long");
+ return
+ DCHECK_CONSTEXPR(x != 0, "x must not be zero", T(0))
+ (sizeof(T) == sizeof(uint32_t))
+ ? __builtin_ctz(x)
+ : __builtin_ctzll(x);
}
template<typename T>