1 //===-- Unittests for memory_utils ----------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "src/__support/CPP/array.h"
10 #include "src/string/memory_utils/utils.h"
11 #include "test/UnitTest/Test.h"
13 namespace LIBC_NAMESPACE
{
15 TEST(LlvmLibcUtilsTest
, IsPowerOfTwoOrZero
) {
16 static const cpp::array
<bool, 65> kExpectedValues
{
17 1, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 0-15
18 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31
19 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47
20 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 48-63
23 for (size_t i
= 0; i
< kExpectedValues
.size(); ++i
)
24 EXPECT_EQ(is_power2_or_zero(i
), kExpectedValues
[i
]);
27 TEST(LlvmLibcUtilsTest
, IsPowerOfTwo
) {
28 static const cpp::array
<bool, 65> kExpectedValues
{
29 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, // 0-15
30 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 16-31
31 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 32-47
32 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 48-63
35 for (size_t i
= 0; i
< kExpectedValues
.size(); ++i
)
36 EXPECT_EQ(is_power2(i
), kExpectedValues
[i
]);
39 TEST(LlvmLibcUtilsTest
, Log2
) {
40 static const cpp::array
<size_t, 65> kExpectedValues
{
41 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, // 0-15
42 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, // 16-31
43 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 32-47
44 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, // 48-63
47 for (size_t i
= 0; i
< kExpectedValues
.size(); ++i
)
48 EXPECT_EQ(log2s(i
), kExpectedValues
[i
]);
51 TEST(LlvmLibcUtilsTest
, LEPowerOf2
) {
52 static const cpp::array
<size_t, 65> kExpectedValues
{
53 0, 1, 2, 2, 4, 4, 4, 4, 8, 8, 8, 8, 8, 8, 8, 8, // 0-15
54 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, // 16-31
55 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, // 32-47
56 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, // 48-63
59 for (size_t i
= 0; i
< kExpectedValues
.size(); ++i
)
60 EXPECT_EQ(le_power2(i
), kExpectedValues
[i
]);
63 TEST(LlvmLibcUtilsTest
, GEPowerOf2
) {
64 static const cpp::array
<size_t, 66> kExpectedValues
{
65 0, 1, 2, 4, 4, 8, 8, 8, 8, 16, 16, 16, 16, 16, 16, 16, // 0-15
66 16, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, // 16-31
67 32, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, // 32-47
68 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, // 48-63
71 for (size_t i
= 0; i
< kExpectedValues
.size(); ++i
)
72 EXPECT_EQ(ge_power2(i
), kExpectedValues
[i
]);
75 using UINT
= uintptr_t;
77 // Converts an offset into a pointer.
78 const void *forge(size_t offset
) {
79 return reinterpret_cast<const void *>(offset
);
82 TEST(LlvmLibcUtilsTest
, DistanceToNextAligned
) {
83 EXPECT_EQ(distance_to_next_aligned
<16>(forge(0)), UINT(16));
84 EXPECT_EQ(distance_to_next_aligned
<16>(forge(1)), UINT(15));
85 EXPECT_EQ(distance_to_next_aligned
<16>(forge(16)), UINT(16));
86 EXPECT_EQ(distance_to_next_aligned
<16>(forge(15)), UINT(1));
87 EXPECT_EQ(distance_to_next_aligned
<32>(forge(16)), UINT(16));
90 TEST(LlvmLibcUtilsTest
, DistanceToAlignUp
) {
91 EXPECT_EQ(distance_to_align_up
<16>(forge(0)), UINT(0));
92 EXPECT_EQ(distance_to_align_up
<16>(forge(1)), UINT(15));
93 EXPECT_EQ(distance_to_align_up
<16>(forge(16)), UINT(0));
94 EXPECT_EQ(distance_to_align_up
<16>(forge(15)), UINT(1));
95 EXPECT_EQ(distance_to_align_up
<32>(forge(16)), UINT(16));
98 TEST(LlvmLibcUtilsTest
, DistanceToAlignDown
) {
99 EXPECT_EQ(distance_to_align_down
<16>(forge(0)), UINT(0));
100 EXPECT_EQ(distance_to_align_down
<16>(forge(1)), UINT(1));
101 EXPECT_EQ(distance_to_align_down
<16>(forge(16)), UINT(0));
102 EXPECT_EQ(distance_to_align_down
<16>(forge(15)), UINT(15));
103 EXPECT_EQ(distance_to_align_down
<32>(forge(16)), UINT(16));
106 TEST(LlvmLibcUtilsTest
, Adjust2
) {
108 const size_t base_size
= 10;
109 for (ptrdiff_t I
= -2; I
< 2; ++I
) {
112 size_t size
= base_size
;
113 adjust(I
, p1
, p2
, size
);
114 EXPECT_EQ(intptr_t(p1
), intptr_t(&a
+ I
));
115 EXPECT_EQ(intptr_t(p2
), intptr_t(&b
+ I
));
116 EXPECT_EQ(size
, base_size
- I
);
120 TEST(LlvmLibcUtilsTest
, Align2
) {
122 const size_t base_size
= 10;
126 size_t size
= base_size
;
127 align_to_next_boundary
<128, Arg::P1
>(p1
, p2
, size
);
128 EXPECT_TRUE(uintptr_t(p1
) % 128 == 0);
131 EXPECT_EQ(size_t(p1
- &a
), base_size
- size
);
132 EXPECT_EQ(size_t(p2
- &b
), base_size
- size
);
137 size_t size
= base_size
;
138 align_to_next_boundary
<128, Arg::P2
>(p1
, p2
, size
);
139 EXPECT_TRUE(uintptr_t(p2
) % 128 == 0);
142 EXPECT_EQ(size_t(p1
- &a
), base_size
- size
);
143 EXPECT_EQ(size_t(p2
- &b
), base_size
- size
);
147 TEST(LlvmLibcUtilsTest
, DisjointBuffers
) {
149 const char *const a
= buf
+ 0;
150 const char *const b
= buf
+ 1;
151 EXPECT_TRUE(is_disjoint(a
, b
, 0));
152 EXPECT_TRUE(is_disjoint(a
, b
, 1));
153 EXPECT_FALSE(is_disjoint(a
, b
, 2));
155 EXPECT_TRUE(is_disjoint(b
, a
, 0));
156 EXPECT_TRUE(is_disjoint(b
, a
, 1));
157 EXPECT_FALSE(is_disjoint(b
, a
, 2));
160 TEST(LlvmLibcUtilsTest
, LoadStoreAligned
) {
161 const uint64_t init
= 0xDEAD'C0DE'BEEF'F00D;
162 CPtr
const src
= reinterpret_cast<CPtr
>(&init
);
164 Ptr
const dst
= reinterpret_cast<Ptr
>(&store
);
166 using LoadFun
= uint64_t (*)(CPtr
);
167 using StoreFun
= void (*)(uint64_t, Ptr
);
170 LoadFun ld
= load_aligned
<uint64_t, uint64_t>;
171 StoreFun st
= store_aligned
<uint64_t, uint64_t>;
172 const uint64_t loaded
= ld(src
);
173 EXPECT_EQ(init
, loaded
);
176 EXPECT_EQ(init
, store
);
180 LoadFun ld
= load_aligned
<uint64_t, uint32_t, uint32_t>;
181 StoreFun st
= store_aligned
<uint64_t, uint32_t, uint32_t>;
182 const uint64_t loaded
= ld(src
);
183 EXPECT_EQ(init
, loaded
);
186 EXPECT_EQ(init
, store
);
190 LoadFun ld
= load_aligned
<uint64_t, uint32_t, uint16_t, uint8_t, uint8_t>;
191 StoreFun st
= store_aligned
<uint64_t, uint32_t, uint16_t, uint8_t, uint8_t>;
192 const uint64_t loaded
= ld(src
);
193 EXPECT_EQ(init
, loaded
);
196 EXPECT_EQ(init
, store
);
200 } // namespace LIBC_NAMESPACE