Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / libc / test / src / string / memory_utils / utils_test.cpp
blob8e9052de56f1b088466b6e60a7d36e1a09581200
1 //===-- Unittests for memory_utils ----------------------------------------===//
2 //
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
6 //
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
21 1 // 64
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
33 1 // 64
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
45 6 // 64
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
57 64 // 64
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
69 64, 128 // 64-65
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) {
107 char a, b;
108 const size_t base_size = 10;
109 for (ptrdiff_t I = -2; I < 2; ++I) {
110 auto *p1 = &a;
111 auto *p2 = &b;
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) {
121 char a, b;
122 const size_t base_size = 10;
124 auto *p1 = &a;
125 auto *p2 = &b;
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);
129 EXPECT_GT(p1, &a);
130 EXPECT_GT(p2, &b);
131 EXPECT_EQ(size_t(p1 - &a), base_size - size);
132 EXPECT_EQ(size_t(p2 - &b), base_size - size);
135 auto *p1 = &a;
136 auto *p2 = &b;
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);
140 EXPECT_GT(p1, &a);
141 EXPECT_GT(p2, &b);
142 EXPECT_EQ(size_t(p1 - &a), base_size - size);
143 EXPECT_EQ(size_t(p2 - &b), base_size - size);
147 TEST(LlvmLibcUtilsTest, DisjointBuffers) {
148 char buf[3];
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);
163 uint64_t store;
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);
174 store = 0;
175 st(init, dst);
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);
184 store = 0;
185 st(init, dst);
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);
194 store = 0;
195 st(init, dst);
196 EXPECT_EQ(init, store);
200 } // namespace LIBC_NAMESPACE