[orc-rt] Implement rotl / rotr, fix missing include in unit test. (#177305)
In e838f27e0f3 the EndianTest.cpp unittest was updated to avoid using `llvm::rotl` function, but the corresponding `orc_rt::rotl` function had not been implemented yet. This commit implements orc_rt::rotl, orc_rt::rotr, and orc_rt::has_single_bit by copying their definitions from the corresponding LLVM header (llvm-project/llvm/include/llvm/ADT/bit.h). Unit tests for these functions are also copied from their LLVM counterparts. Thanks to @jaredwy for spotting this!
This commit is contained in:
parent
2036bc524b
commit
2b22d76ba7
@ -128,6 +128,37 @@ template <typename T, typename _ = std::enable_if_t<std::is_unsigned_v<T>>>
|
||||
return std::numeric_limits<T>::digits - countl_zero(x);
|
||||
}
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
|
||||
[[nodiscard]] constexpr inline bool has_single_bit(T Value) noexcept {
|
||||
return (Value != 0) && ((Value & (Value - 1)) == 0);
|
||||
}
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
|
||||
[[nodiscard]] constexpr T rotl(T V, int R) {
|
||||
constexpr unsigned N = std::numeric_limits<T>::digits;
|
||||
|
||||
static_assert(has_single_bit(N), "& (N - 1) is only valid for powers of two");
|
||||
R = R & (N - 1);
|
||||
|
||||
if (R == 0)
|
||||
return V;
|
||||
|
||||
return (V << R) | (V >> (N - R));
|
||||
}
|
||||
|
||||
template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
|
||||
[[nodiscard]] constexpr T rotr(T V, int R) {
|
||||
constexpr unsigned N = std::numeric_limits<T>::digits;
|
||||
|
||||
static_assert(has_single_bit(N), "& (N - 1) is only valid for powers of two");
|
||||
R = R & (N - 1);
|
||||
|
||||
if (R == 0)
|
||||
return V;
|
||||
|
||||
return (V >> R) | (V << (N - R));
|
||||
}
|
||||
|
||||
} // namespace orc_rt
|
||||
|
||||
#endif // ORC_RT_BIT_H
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "orc-rt/Endian.h"
|
||||
#include "orc-rt/bit.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -151,3 +151,72 @@ TEST(BitTest, BitWidth) {
|
||||
EXPECT_EQ(32, orc_rt::bit_width(uint32_t(0xffffffffu)));
|
||||
EXPECT_EQ(64, orc_rt::bit_width(uint64_t(0xffffffffffffffffull)));
|
||||
}
|
||||
|
||||
TEST(BitTest, HasSingleBit) {
|
||||
EXPECT_FALSE(orc_rt::has_single_bit(0U));
|
||||
EXPECT_FALSE(orc_rt::has_single_bit(0ULL));
|
||||
|
||||
EXPECT_FALSE(orc_rt::has_single_bit(~0U));
|
||||
EXPECT_FALSE(orc_rt::has_single_bit(~0ULL));
|
||||
|
||||
EXPECT_TRUE(orc_rt::has_single_bit(1U));
|
||||
EXPECT_TRUE(orc_rt::has_single_bit(1ULL));
|
||||
|
||||
static const int8_t kValueS8 = -128;
|
||||
EXPECT_TRUE(orc_rt::has_single_bit(static_cast<uint8_t>(kValueS8)));
|
||||
|
||||
static const int16_t kValueS16 = -32768;
|
||||
EXPECT_TRUE(orc_rt::has_single_bit(static_cast<uint16_t>(kValueS16)));
|
||||
}
|
||||
|
||||
TEST(BitTest, Rotl) {
|
||||
EXPECT_EQ(0x53U, orc_rt::rotl<uint8_t>(0x53, 0));
|
||||
EXPECT_EQ(0x4dU, orc_rt::rotl<uint8_t>(0x53, 2));
|
||||
EXPECT_EQ(0xa6U, orc_rt::rotl<uint8_t>(0x53, 9));
|
||||
EXPECT_EQ(0x9aU, orc_rt::rotl<uint8_t>(0x53, -5));
|
||||
|
||||
EXPECT_EQ(0xabcdU, orc_rt::rotl<uint16_t>(0xabcd, 0));
|
||||
EXPECT_EQ(0xf36aU, orc_rt::rotl<uint16_t>(0xabcd, 6));
|
||||
EXPECT_EQ(0xaf36U, orc_rt::rotl<uint16_t>(0xabcd, 18));
|
||||
EXPECT_EQ(0xf36aU, orc_rt::rotl<uint16_t>(0xabcd, -10));
|
||||
|
||||
EXPECT_EQ(0xdeadbeefU, orc_rt::rotl<uint32_t>(0xdeadbeef, 0));
|
||||
EXPECT_EQ(0x7ddfbd5bU, orc_rt::rotl<uint32_t>(0xdeadbeef, 17));
|
||||
EXPECT_EQ(0x5b7ddfbdU, orc_rt::rotl<uint32_t>(0xdeadbeef, 41));
|
||||
EXPECT_EQ(0xb6fbbf7aU, orc_rt::rotl<uint32_t>(0xdeadbeef, -22));
|
||||
|
||||
EXPECT_EQ(0x12345678deadbeefULL,
|
||||
orc_rt::rotl<uint64_t>(0x12345678deadbeefULL, 0));
|
||||
EXPECT_EQ(0xf56df77891a2b3c6ULL,
|
||||
orc_rt::rotl<uint64_t>(0x12345678deadbeefULL, 35));
|
||||
EXPECT_EQ(0x8d159e37ab6fbbc4ULL,
|
||||
orc_rt::rotl<uint64_t>(0x12345678deadbeefULL, 70));
|
||||
EXPECT_EQ(0xb7dde2468acf1bd5ULL,
|
||||
orc_rt::rotl<uint64_t>(0x12345678deadbeefULL, -19));
|
||||
}
|
||||
|
||||
TEST(BitTest, Rotr) {
|
||||
EXPECT_EQ(0x53U, orc_rt::rotr<uint8_t>(0x53, 0));
|
||||
EXPECT_EQ(0xd4U, orc_rt::rotr<uint8_t>(0x53, 2));
|
||||
EXPECT_EQ(0xa9U, orc_rt::rotr<uint8_t>(0x53, 9));
|
||||
EXPECT_EQ(0x6aU, orc_rt::rotr<uint8_t>(0x53, -5));
|
||||
|
||||
EXPECT_EQ(0xabcdU, orc_rt::rotr<uint16_t>(0xabcd, 0));
|
||||
EXPECT_EQ(0x36afU, orc_rt::rotr<uint16_t>(0xabcd, 6));
|
||||
EXPECT_EQ(0x6af3U, orc_rt::rotr<uint16_t>(0xabcd, 18));
|
||||
EXPECT_EQ(0x36afU, orc_rt::rotr<uint16_t>(0xabcd, -10));
|
||||
|
||||
EXPECT_EQ(0xdeadbeefU, orc_rt::rotr<uint32_t>(0xdeadbeef, 0));
|
||||
EXPECT_EQ(0xdf77ef56U, orc_rt::rotr<uint32_t>(0xdeadbeef, 17));
|
||||
EXPECT_EQ(0x77ef56dfU, orc_rt::rotr<uint32_t>(0xdeadbeef, 41));
|
||||
EXPECT_EQ(0xbbf7ab6fU, orc_rt::rotr<uint32_t>(0xdeadbeef, -22));
|
||||
|
||||
EXPECT_EQ(0x12345678deadbeefULL,
|
||||
orc_rt::rotr<uint64_t>(0x12345678deadbeefULL, 0));
|
||||
EXPECT_EQ(0x1bd5b7dde2468acfULL,
|
||||
orc_rt::rotr<uint64_t>(0x12345678deadbeefULL, 35));
|
||||
EXPECT_EQ(0xbc48d159e37ab6fbULL,
|
||||
orc_rt::rotr<uint64_t>(0x12345678deadbeefULL, 70));
|
||||
EXPECT_EQ(0xb3c6f56df77891a2ULL,
|
||||
orc_rt::rotr<uint64_t>(0x12345678deadbeefULL, -19));
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user