Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2b22d76

Browse files
authored
[orc-rt] Implement rotl / rotr, fix missing include in unit test. (#177305)
In e838f27 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!
1 parent 2036bc5 commit 2b22d76

3 files changed

Lines changed: 101 additions & 0 deletions

File tree

orc-rt/include/orc-rt/bit.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,37 @@ template <typename T, typename _ = std::enable_if_t<std::is_unsigned_v<T>>>
128128
return std::numeric_limits<T>::digits - countl_zero(x);
129129
}
130130

131+
template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
132+
[[nodiscard]] constexpr inline bool has_single_bit(T Value) noexcept {
133+
return (Value != 0) && ((Value & (Value - 1)) == 0);
134+
}
135+
136+
template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
137+
[[nodiscard]] constexpr T rotl(T V, int R) {
138+
constexpr unsigned N = std::numeric_limits<T>::digits;
139+
140+
static_assert(has_single_bit(N), "& (N - 1) is only valid for powers of two");
141+
R = R & (N - 1);
142+
143+
if (R == 0)
144+
return V;
145+
146+
return (V << R) | (V >> (N - R));
147+
}
148+
149+
template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
150+
[[nodiscard]] constexpr T rotr(T V, int R) {
151+
constexpr unsigned N = std::numeric_limits<T>::digits;
152+
153+
static_assert(has_single_bit(N), "& (N - 1) is only valid for powers of two");
154+
R = R & (N - 1);
155+
156+
if (R == 0)
157+
return V;
158+
159+
return (V >> R) | (V << (N - R));
160+
}
161+
131162
} // namespace orc_rt
132163

133164
#endif // ORC_RT_BIT_H

orc-rt/unittests/EndianTest.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#include "orc-rt/Endian.h"
14+
#include "orc-rt/bit.h"
1415
#include "gtest/gtest.h"
1516

1617
#include <algorithm>

orc-rt/unittests/bit-test.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,72 @@ TEST(BitTest, BitWidth) {
151151
EXPECT_EQ(32, orc_rt::bit_width(uint32_t(0xffffffffu)));
152152
EXPECT_EQ(64, orc_rt::bit_width(uint64_t(0xffffffffffffffffull)));
153153
}
154+
155+
TEST(BitTest, HasSingleBit) {
156+
EXPECT_FALSE(orc_rt::has_single_bit(0U));
157+
EXPECT_FALSE(orc_rt::has_single_bit(0ULL));
158+
159+
EXPECT_FALSE(orc_rt::has_single_bit(~0U));
160+
EXPECT_FALSE(orc_rt::has_single_bit(~0ULL));
161+
162+
EXPECT_TRUE(orc_rt::has_single_bit(1U));
163+
EXPECT_TRUE(orc_rt::has_single_bit(1ULL));
164+
165+
static const int8_t kValueS8 = -128;
166+
EXPECT_TRUE(orc_rt::has_single_bit(static_cast<uint8_t>(kValueS8)));
167+
168+
static const int16_t kValueS16 = -32768;
169+
EXPECT_TRUE(orc_rt::has_single_bit(static_cast<uint16_t>(kValueS16)));
170+
}
171+
172+
TEST(BitTest, Rotl) {
173+
EXPECT_EQ(0x53U, orc_rt::rotl<uint8_t>(0x53, 0));
174+
EXPECT_EQ(0x4dU, orc_rt::rotl<uint8_t>(0x53, 2));
175+
EXPECT_EQ(0xa6U, orc_rt::rotl<uint8_t>(0x53, 9));
176+
EXPECT_EQ(0x9aU, orc_rt::rotl<uint8_t>(0x53, -5));
177+
178+
EXPECT_EQ(0xabcdU, orc_rt::rotl<uint16_t>(0xabcd, 0));
179+
EXPECT_EQ(0xf36aU, orc_rt::rotl<uint16_t>(0xabcd, 6));
180+
EXPECT_EQ(0xaf36U, orc_rt::rotl<uint16_t>(0xabcd, 18));
181+
EXPECT_EQ(0xf36aU, orc_rt::rotl<uint16_t>(0xabcd, -10));
182+
183+
EXPECT_EQ(0xdeadbeefU, orc_rt::rotl<uint32_t>(0xdeadbeef, 0));
184+
EXPECT_EQ(0x7ddfbd5bU, orc_rt::rotl<uint32_t>(0xdeadbeef, 17));
185+
EXPECT_EQ(0x5b7ddfbdU, orc_rt::rotl<uint32_t>(0xdeadbeef, 41));
186+
EXPECT_EQ(0xb6fbbf7aU, orc_rt::rotl<uint32_t>(0xdeadbeef, -22));
187+
188+
EXPECT_EQ(0x12345678deadbeefULL,
189+
orc_rt::rotl<uint64_t>(0x12345678deadbeefULL, 0));
190+
EXPECT_EQ(0xf56df77891a2b3c6ULL,
191+
orc_rt::rotl<uint64_t>(0x12345678deadbeefULL, 35));
192+
EXPECT_EQ(0x8d159e37ab6fbbc4ULL,
193+
orc_rt::rotl<uint64_t>(0x12345678deadbeefULL, 70));
194+
EXPECT_EQ(0xb7dde2468acf1bd5ULL,
195+
orc_rt::rotl<uint64_t>(0x12345678deadbeefULL, -19));
196+
}
197+
198+
TEST(BitTest, Rotr) {
199+
EXPECT_EQ(0x53U, orc_rt::rotr<uint8_t>(0x53, 0));
200+
EXPECT_EQ(0xd4U, orc_rt::rotr<uint8_t>(0x53, 2));
201+
EXPECT_EQ(0xa9U, orc_rt::rotr<uint8_t>(0x53, 9));
202+
EXPECT_EQ(0x6aU, orc_rt::rotr<uint8_t>(0x53, -5));
203+
204+
EXPECT_EQ(0xabcdU, orc_rt::rotr<uint16_t>(0xabcd, 0));
205+
EXPECT_EQ(0x36afU, orc_rt::rotr<uint16_t>(0xabcd, 6));
206+
EXPECT_EQ(0x6af3U, orc_rt::rotr<uint16_t>(0xabcd, 18));
207+
EXPECT_EQ(0x36afU, orc_rt::rotr<uint16_t>(0xabcd, -10));
208+
209+
EXPECT_EQ(0xdeadbeefU, orc_rt::rotr<uint32_t>(0xdeadbeef, 0));
210+
EXPECT_EQ(0xdf77ef56U, orc_rt::rotr<uint32_t>(0xdeadbeef, 17));
211+
EXPECT_EQ(0x77ef56dfU, orc_rt::rotr<uint32_t>(0xdeadbeef, 41));
212+
EXPECT_EQ(0xbbf7ab6fU, orc_rt::rotr<uint32_t>(0xdeadbeef, -22));
213+
214+
EXPECT_EQ(0x12345678deadbeefULL,
215+
orc_rt::rotr<uint64_t>(0x12345678deadbeefULL, 0));
216+
EXPECT_EQ(0x1bd5b7dde2468acfULL,
217+
orc_rt::rotr<uint64_t>(0x12345678deadbeefULL, 35));
218+
EXPECT_EQ(0xbc48d159e37ab6fbULL,
219+
orc_rt::rotr<uint64_t>(0x12345678deadbeefULL, 70));
220+
EXPECT_EQ(0xb3c6f56df77891a2ULL,
221+
orc_rt::rotr<uint64_t>(0x12345678deadbeefULL, -19));
222+
}

0 commit comments

Comments
 (0)