xref: /llvm-project/llvm/unittests/Support/AlignmentTest.cpp (revision c87581c4d46e5db3dfd5776d323fa7535e6669e7)
1 //=== - llvm/unittest/Support/Alignment.cpp - Alignment utility tests -----===//
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 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/Support/Alignment.h"
10 #include "gtest/gtest.h"
11 
12 #include <vector>
13 
14 using namespace llvm;
15 
16 namespace {
17 
18 std::vector<uint64_t> getValidAlignments() {
19   std::vector<uint64_t> Out;
20   for (size_t Shift = 0; Shift < 64; ++Shift)
21     Out.push_back(1ULL << Shift);
22   return Out;
23 }
24 
25 // We use a subset of valid alignments for DEATH_TESTs as they are particularly
26 // slow.
27 std::vector<uint64_t> getValidAlignmentsForDeathTest() {
28   return {1, 1ULL << 31, 1ULL << 63};
29 }
30 
31 std::vector<uint64_t> getNonPowerOfTwo() { return {3, 10, 15}; }
32 
33 TEST(Alignment, AlignDefaultCTor) { EXPECT_EQ(Align().value(), 1ULL); }
34 
35 TEST(Alignment, MaybeAlignDefaultCTor) {
36   EXPECT_FALSE(MaybeAlign().hasValue());
37 }
38 
39 TEST(Alignment, ValidCTors) {
40   for (size_t Value : getValidAlignments()) {
41     EXPECT_EQ(Align(Value).value(), Value);
42     EXPECT_EQ((*MaybeAlign(Value)).value(), Value);
43   }
44 }
45 
46 TEST(Alignment, InvalidCTors) {
47   EXPECT_DEATH((Align(0)), "Value must not be 0");
48   for (size_t Value : getNonPowerOfTwo()) {
49     EXPECT_DEATH((Align(Value)), "Alignment is not a power of 2");
50     EXPECT_DEATH((MaybeAlign(Value)), "Alignment is not 0 or a power of 2");
51   }
52 }
53 
54 TEST(Alignment, CheckMaybeAlignHasValue) {
55   EXPECT_TRUE(MaybeAlign(1));
56   EXPECT_TRUE(MaybeAlign(1).hasValue());
57   EXPECT_FALSE(MaybeAlign(0));
58   EXPECT_FALSE(MaybeAlign(0).hasValue());
59   EXPECT_FALSE(MaybeAlign());
60   EXPECT_FALSE(MaybeAlign().hasValue());
61 }
62 
63 TEST(Alignment, CantConvertUnsetMaybe) {
64   EXPECT_DEATH((MaybeAlign(0).getValue()), ".*");
65 }
66 
67 TEST(Alignment, Division) {
68   for (size_t Value : getValidAlignments()) {
69     if (Value == 1) {
70       EXPECT_DEATH(Align(Value) / 2, "Can't halve byte alignment");
71       EXPECT_DEATH(MaybeAlign(Value) / 2, "Can't halve byte alignment");
72     } else {
73       EXPECT_EQ(Align(Value) / 2, Value / 2);
74       EXPECT_EQ(MaybeAlign(Value) / 2, Value / 2);
75     }
76   }
77   EXPECT_EQ(MaybeAlign(0) / 2, MaybeAlign(0));
78 
79   EXPECT_DEATH(Align(8) / 0, "Divisor must be positive and a power of 2");
80   EXPECT_DEATH(Align(8) / 3, "Divisor must be positive and a power of 2");
81 }
82 
83 TEST(Alignment, AlignTo) {
84   struct {
85     uint64_t alignment;
86     uint64_t offset;
87     uint64_t rounded;
88   } kTests[] = {
89       // MaybeAlign
90       {0, 0, 0},
91       {0, 1, 1},
92       {0, 5, 5},
93       // MaybeAlign / Align
94       {1, 0, 0},
95       {1, 1, 1},
96       {1, 5, 5},
97       {2, 0, 0},
98       {2, 1, 2},
99       {2, 2, 2},
100       {2, 7, 8},
101       {2, 16, 16},
102       {4, 0, 0},
103       {4, 1, 4},
104       {4, 4, 4},
105       {4, 6, 8},
106   };
107   for (const auto &T : kTests) {
108     MaybeAlign A(T.alignment);
109     // Test MaybeAlign
110     EXPECT_EQ(alignTo(T.offset, A), T.rounded);
111     // Test Align
112     if (A)
113       EXPECT_EQ(alignTo(T.offset, A.getValue()), T.rounded);
114   }
115 }
116 
117 TEST(Alignment, Log2) {
118   for (size_t Value : getValidAlignments()) {
119     EXPECT_EQ(Log2(Align(Value)), Log2_64(Value));
120     EXPECT_EQ(Log2(MaybeAlign(Value)), Log2_64(Value));
121   }
122   EXPECT_DEATH(Log2(MaybeAlign(0)), ".* should be defined");
123 }
124 
125 TEST(Alignment, MinAlign) {
126   struct {
127     uint64_t A;
128     uint64_t B;
129     uint64_t MinAlign;
130   } kTests[] = {
131       // MaybeAlign
132       {0, 0, 0},
133       {0, 8, 8},
134       {2, 0, 2},
135       // MaybeAlign / Align
136       {1, 2, 1},
137       {8, 4, 4},
138   };
139   for (const auto &T : kTests) {
140     EXPECT_EQ(commonAlignment(MaybeAlign(T.A), MaybeAlign(T.B)), T.MinAlign);
141     EXPECT_EQ(MinAlign(T.A, T.B), T.MinAlign);
142     if (T.A)
143       EXPECT_EQ(commonAlignment(Align(T.A), MaybeAlign(T.B)), T.MinAlign);
144     if (T.B)
145       EXPECT_EQ(commonAlignment(MaybeAlign(T.A), Align(T.B)), T.MinAlign);
146     if (T.A && T.B)
147       EXPECT_EQ(commonAlignment(Align(T.A), Align(T.B)), T.MinAlign);
148   }
149 }
150 
151 TEST(Alignment, Encode_Decode) {
152   for (size_t Value : getValidAlignments()) {
153     {
154       Align Actual(Value);
155       Align Expected = decodeMaybeAlign(encode(Actual)).getValue();
156       EXPECT_EQ(Expected, Actual);
157     }
158     {
159       MaybeAlign Actual(Value);
160       MaybeAlign Expected = decodeMaybeAlign(encode(Actual));
161       EXPECT_EQ(Expected, Actual);
162     }
163   }
164   MaybeAlign Actual(0);
165   MaybeAlign Expected = decodeMaybeAlign(encode(Actual));
166   EXPECT_EQ(Expected, Actual);
167 }
168 
169 TEST(Alignment, isAligned) {
170   struct {
171     uint64_t alignment;
172     uint64_t offset;
173     bool isAligned;
174   } kTests[] = {
175       // MaybeAlign / Align
176       {1, 0, true},  {1, 1, true},  {1, 5, true},  {2, 0, true},
177       {2, 1, false}, {2, 2, true},  {2, 7, false}, {2, 16, true},
178       {4, 0, true},  {4, 1, false}, {4, 4, true},  {4, 6, false},
179   };
180   for (const auto &T : kTests) {
181     MaybeAlign A(T.alignment);
182     // Test MaybeAlign
183     EXPECT_EQ(isAligned(A, T.offset), T.isAligned);
184     // Test Align
185     if (A)
186       EXPECT_EQ(isAligned(A.getValue(), T.offset), T.isAligned);
187   }
188 }
189 
190 TEST(Alignment, AlignComparisons) {
191   std::vector<uint64_t> ValidAlignments = getValidAlignments();
192   std::sort(ValidAlignments.begin(), ValidAlignments.end());
193   for (size_t I = 1; I < ValidAlignments.size(); ++I) {
194     assert(I >= 1);
195     const Align A(ValidAlignments[I - 1]);
196     const Align B(ValidAlignments[I]);
197     EXPECT_EQ(A, A);
198     EXPECT_NE(A, B);
199     EXPECT_LT(A, B);
200     EXPECT_GT(B, A);
201     EXPECT_LE(A, B);
202     EXPECT_GE(B, A);
203     EXPECT_LE(A, A);
204     EXPECT_GE(A, A);
205 
206     EXPECT_EQ(A, A.value());
207     EXPECT_NE(A, B.value());
208     EXPECT_LT(A, B.value());
209     EXPECT_GT(B, A.value());
210     EXPECT_LE(A, B.value());
211     EXPECT_GE(B, A.value());
212     EXPECT_LE(A, A.value());
213     EXPECT_GE(A, A.value());
214 
215     EXPECT_EQ(std::max(A, B), B);
216     EXPECT_EQ(std::min(A, B), A);
217 
218     const MaybeAlign MA(ValidAlignments[I - 1]);
219     const MaybeAlign MB(ValidAlignments[I]);
220     EXPECT_EQ(MA, MA);
221     EXPECT_NE(MA, MB);
222     EXPECT_LT(MA, MB);
223     EXPECT_GT(MB, MA);
224     EXPECT_LE(MA, MB);
225     EXPECT_GE(MB, MA);
226     EXPECT_LE(MA, MA);
227     EXPECT_GE(MA, MA);
228 
229     EXPECT_EQ(MA, MA ? (*MA).value() : 0);
230     EXPECT_NE(MA, MB ? (*MB).value() : 0);
231     EXPECT_LT(MA, MB ? (*MB).value() : 0);
232     EXPECT_GT(MB, MA ? (*MA).value() : 0);
233     EXPECT_LE(MA, MB ? (*MB).value() : 0);
234     EXPECT_GE(MB, MA ? (*MA).value() : 0);
235     EXPECT_LE(MA, MA ? (*MA).value() : 0);
236     EXPECT_GE(MA, MA ? (*MA).value() : 0);
237 
238     EXPECT_EQ(std::max(A, B), B);
239     EXPECT_EQ(std::min(A, B), A);
240   }
241 }
242 
243 TEST(Alignment, AssumeAligned) {
244   EXPECT_EQ(assumeAligned(0), Align(1));
245   EXPECT_EQ(assumeAligned(0), Align());
246   EXPECT_EQ(assumeAligned(1), Align(1));
247   EXPECT_EQ(assumeAligned(1), Align());
248 }
249 
250 TEST(Alignment, ComparisonsWithZero) {
251   for (size_t Value : getValidAlignmentsForDeathTest()) {
252     EXPECT_DEATH((void)(Align(Value) == 0), ".* should be defined");
253     EXPECT_DEATH((void)(Align(Value) != 0), ".* should be defined");
254     EXPECT_DEATH((void)(Align(Value) >= 0), ".* should be defined");
255     EXPECT_DEATH((void)(Align(Value) <= 0), ".* should be defined");
256     EXPECT_DEATH((void)(Align(Value) > 0), ".* should be defined");
257     EXPECT_DEATH((void)(Align(Value) < 0), ".* should be defined");
258   }
259 }
260 
261 TEST(Alignment, CompareMaybeAlignToZero) {
262   for (size_t Value : getValidAlignmentsForDeathTest()) {
263     // MaybeAlign is allowed to be == or != 0
264     (void)(MaybeAlign(Value) == 0);
265     (void)(MaybeAlign(Value) != 0);
266     EXPECT_DEATH((void)(MaybeAlign(Value) >= 0), ".* should be defined");
267     EXPECT_DEATH((void)(MaybeAlign(Value) <= 0), ".* should be defined");
268     EXPECT_DEATH((void)(MaybeAlign(Value) > 0), ".* should be defined");
269     EXPECT_DEATH((void)(MaybeAlign(Value) < 0), ".* should be defined");
270   }
271 }
272 
273 TEST(Alignment, CompareAlignToUndefMaybeAlign) {
274   for (size_t Value : getValidAlignmentsForDeathTest()) {
275     EXPECT_DEATH((void)(Align(Value) == MaybeAlign(0)), ".* should be defined");
276     EXPECT_DEATH((void)(Align(Value) != MaybeAlign(0)), ".* should be defined");
277     EXPECT_DEATH((void)(Align(Value) >= MaybeAlign(0)), ".* should be defined");
278     EXPECT_DEATH((void)(Align(Value) <= MaybeAlign(0)), ".* should be defined");
279     EXPECT_DEATH((void)(Align(Value) > MaybeAlign(0)), ".* should be defined");
280     EXPECT_DEATH((void)(Align(Value) < MaybeAlign(0)), ".* should be defined");
281   }
282 }
283 
284 } // end anonymous namespace
285