1 | //===- unittests/IR/ModuleTest.cpp - Module unit 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/IR/Module.h" |
10 | #include "llvm/AsmParser/Parser.h" |
11 | #include "llvm/IR/GlobalVariable.h" |
12 | #include "llvm/IR/ModuleSummaryIndex.h" |
13 | #include "llvm/Pass.h" |
14 | #include "llvm/Support/RandomNumberGenerator.h" |
15 | #include "llvm/Support/SourceMgr.h" |
16 | #include "gtest/gtest.h" |
17 | |
18 | #include <random> |
19 | |
20 | using namespace llvm; |
21 | |
22 | namespace { |
23 | |
24 | bool sortByName(const GlobalVariable &L, const GlobalVariable &R) { |
25 | return L.getName() < R.getName(); |
26 | } |
27 | |
28 | bool sortByNameReverse(const GlobalVariable &L, const GlobalVariable &R) { |
29 | return sortByName(L: R, R: L); |
30 | } |
31 | |
32 | TEST(ModuleTest, sortGlobalsByName) { |
33 | LLVMContext Context; |
34 | for (auto compare : {&sortByName, &sortByNameReverse}) { |
35 | Module M("M" , Context); |
36 | Type *T = Type::getInt8Ty(C&: Context); |
37 | GlobalValue::LinkageTypes L = GlobalValue::ExternalLinkage; |
38 | (void)new GlobalVariable(M, T, false, L, nullptr, "A" ); |
39 | (void)new GlobalVariable(M, T, false, L, nullptr, "F" ); |
40 | (void)new GlobalVariable(M, T, false, L, nullptr, "G" ); |
41 | (void)new GlobalVariable(M, T, false, L, nullptr, "E" ); |
42 | (void)new GlobalVariable(M, T, false, L, nullptr, "B" ); |
43 | (void)new GlobalVariable(M, T, false, L, nullptr, "H" ); |
44 | (void)new GlobalVariable(M, T, false, L, nullptr, "C" ); |
45 | (void)new GlobalVariable(M, T, false, L, nullptr, "D" ); |
46 | |
47 | // Sort the globals by name. |
48 | EXPECT_FALSE(std::is_sorted(M.global_begin(), M.global_end(), compare)); |
49 | } |
50 | } |
51 | |
52 | TEST(ModuleTest, randomNumberGenerator) { |
53 | LLVMContext Context; |
54 | static char ID; |
55 | struct DummyPass : ModulePass { |
56 | DummyPass() : ModulePass(ID) {} |
57 | bool runOnModule(Module &) override { return true; } |
58 | } DP; |
59 | |
60 | Module M("R" , Context); |
61 | |
62 | std::uniform_int_distribution<int> dist; |
63 | const size_t NBCheck = 10; |
64 | |
65 | std::array<int, NBCheck> RandomStreams[2]; |
66 | for (auto &RandomStream : RandomStreams) { |
67 | std::unique_ptr<RandomNumberGenerator> RNG = M.createRNG(Name: DP.getPassName()); |
68 | std::generate(first: RandomStream.begin(), last: RandomStream.end(), |
69 | gen: [&]() { return dist(*RNG); }); |
70 | } |
71 | |
72 | EXPECT_TRUE(std::equal(RandomStreams[0].begin(), RandomStreams[0].end(), |
73 | RandomStreams[1].begin())); |
74 | } |
75 | |
76 | TEST(ModuleTest, setModuleFlag) { |
77 | LLVMContext Context; |
78 | Module M("M" , Context); |
79 | StringRef Key = "Key" ; |
80 | Metadata *Val1 = MDString::get(Context, Str: "Val1" ); |
81 | Metadata *Val2 = MDString::get(Context, Str: "Val2" ); |
82 | EXPECT_EQ(nullptr, M.getModuleFlag(Key)); |
83 | M.setModuleFlag(Behavior: Module::ModFlagBehavior::Error, Key, Val: Val1); |
84 | EXPECT_EQ(Val1, M.getModuleFlag(Key)); |
85 | M.setModuleFlag(Behavior: Module::ModFlagBehavior::Error, Key, Val: Val2); |
86 | EXPECT_EQ(Val2, M.getModuleFlag(Key)); |
87 | } |
88 | |
89 | const char *IRString = R"IR( |
90 | !llvm.module.flags = !{!0} |
91 | |
92 | !0 = !{i32 1, !"ProfileSummary", !1} |
93 | !1 = !{!2, !3, !4, !5, !6, !7, !8, !9} |
94 | !2 = !{!"ProfileFormat", !"SampleProfile"} |
95 | !3 = !{!"TotalCount", i64 10000} |
96 | !4 = !{!"MaxCount", i64 10} |
97 | !5 = !{!"MaxInternalCount", i64 1} |
98 | !6 = !{!"MaxFunctionCount", i64 1000} |
99 | !7 = !{!"NumCounts", i64 200} |
100 | !8 = !{!"NumFunctions", i64 3} |
101 | !9 = !{!"DetailedSummary", !10} |
102 | !10 = !{!11, !12, !13} |
103 | !11 = !{i32 10000, i64 1000, i32 1} |
104 | !12 = !{i32 990000, i64 300, i32 10} |
105 | !13 = !{i32 999999, i64 5, i32 100} |
106 | )IR" ; |
107 | |
108 | TEST(ModuleTest, setProfileSummary) { |
109 | SMDiagnostic Err; |
110 | LLVMContext Context; |
111 | std::unique_ptr<Module> M = parseAssemblyString(AsmString: IRString, Err, Context); |
112 | auto *PS = ProfileSummary::getFromMD(MD: M->getProfileSummary(/*IsCS*/ false)); |
113 | EXPECT_NE(nullptr, PS); |
114 | EXPECT_FALSE(PS->isPartialProfile()); |
115 | PS->setPartialProfile(true); |
116 | M->setProfileSummary(M: PS->getMD(Context), Kind: ProfileSummary::PSK_Sample); |
117 | delete PS; |
118 | PS = ProfileSummary::getFromMD(MD: M->getProfileSummary(/*IsCS*/ false)); |
119 | EXPECT_NE(nullptr, PS); |
120 | EXPECT_EQ(true, PS->isPartialProfile()); |
121 | delete PS; |
122 | } |
123 | |
124 | TEST(ModuleTest, setPartialSampleProfileRatio) { |
125 | const char *IRString = R"IR( |
126 | !llvm.module.flags = !{!0} |
127 | |
128 | !0 = !{i32 1, !"ProfileSummary", !1} |
129 | !1 = !{!2, !3, !4, !5, !6, !7, !8, !9, !10, !11} |
130 | !2 = !{!"ProfileFormat", !"SampleProfile"} |
131 | !3 = !{!"TotalCount", i64 10000} |
132 | !4 = !{!"MaxCount", i64 10} |
133 | !5 = !{!"MaxInternalCount", i64 1} |
134 | !6 = !{!"MaxFunctionCount", i64 1000} |
135 | !7 = !{!"NumCounts", i64 200} |
136 | !8 = !{!"NumFunctions", i64 3} |
137 | !9 = !{!"IsPartialProfile", i64 1} |
138 | !10 = !{!"PartialProfileRatio", double 0.0} |
139 | !11 = !{!"DetailedSummary", !12} |
140 | !12 = !{!13, !14, !15} |
141 | !13 = !{i32 10000, i64 1000, i32 1} |
142 | !14 = !{i32 990000, i64 300, i32 10} |
143 | !15 = !{i32 999999, i64 5, i32 100} |
144 | )IR" ; |
145 | |
146 | SMDiagnostic Err; |
147 | LLVMContext Context; |
148 | std::unique_ptr<Module> M = parseAssemblyString(AsmString: IRString, Err, Context); |
149 | ModuleSummaryIndex Index(/*HaveGVs*/ false); |
150 | const unsigned BlockCount = 100; |
151 | const unsigned NumCounts = 200; |
152 | Index.setBlockCount(BlockCount); |
153 | M->setPartialSampleProfileRatio(Index); |
154 | double Ratio = (double)BlockCount / NumCounts; |
155 | std::unique_ptr<ProfileSummary> ProfileSummary( |
156 | ProfileSummary::getFromMD(MD: M->getProfileSummary(/*IsCS*/ false))); |
157 | EXPECT_EQ(Ratio, ProfileSummary->getPartialProfileRatio()); |
158 | } |
159 | |
160 | TEST(ModuleTest, AliasList) { |
161 | // This tests all Module's functions that interact with Module::AliasList. |
162 | LLVMContext C; |
163 | SMDiagnostic Err; |
164 | LLVMContext Context; |
165 | std::unique_ptr<Module> M = parseAssemblyString(AsmString: R"( |
166 | declare void @Foo() |
167 | @GA = alias void (), ptr @Foo |
168 | )" , |
169 | Err, Context); |
170 | Function *Foo = M->getFunction(Name: "Foo" ); |
171 | auto *GA = M->getNamedAlias(Name: "GA" ); |
172 | EXPECT_EQ(M->alias_size(), 1u); |
173 | auto *NewGA = |
174 | GlobalAlias::create(Ty: Foo->getType(), AddressSpace: 0, Linkage: GlobalValue::ExternalLinkage, |
175 | Name: "NewGA" , Aliasee: Foo, /*Parent=*/nullptr); |
176 | EXPECT_EQ(M->alias_size(), 1u); |
177 | |
178 | M->insertAlias(Alias: NewGA); |
179 | EXPECT_EQ(&*std::prev(M->aliases().end()), NewGA); |
180 | |
181 | M->removeAlias(Alias: NewGA); |
182 | EXPECT_EQ(M->alias_size(), 1u); |
183 | M->insertAlias(Alias: NewGA); |
184 | EXPECT_EQ(M->alias_size(), 2u); |
185 | EXPECT_EQ(&*std::prev(M->aliases().end()), NewGA); |
186 | |
187 | auto Range = M->aliases(); |
188 | EXPECT_EQ(&*Range.begin(), GA); |
189 | EXPECT_EQ(&*std::next(Range.begin()), NewGA); |
190 | EXPECT_EQ(std::next(Range.begin(), 2), Range.end()); |
191 | |
192 | M->removeAlias(Alias: NewGA); |
193 | EXPECT_EQ(M->alias_size(), 1u); |
194 | |
195 | M->insertAlias(Alias: NewGA); |
196 | M->eraseAlias(Alias: NewGA); |
197 | EXPECT_EQ(M->alias_size(), 1u); |
198 | } |
199 | |
200 | TEST(ModuleTest, IFuncList) { |
201 | // This tests all Module's functions that interact with Module::IFuncList. |
202 | LLVMContext C; |
203 | SMDiagnostic Err; |
204 | LLVMContext Context; |
205 | std::unique_ptr<Module> M = parseAssemblyString(AsmString: R"( |
206 | declare void @Foo() |
207 | @GIF = ifunc void (), ptr @Foo |
208 | )" , |
209 | Err, Context); |
210 | Function *Foo = M->getFunction(Name: "Foo" ); |
211 | auto *GIF = M->getNamedIFunc(Name: "GIF" ); |
212 | EXPECT_EQ(M->ifunc_size(), 1u); |
213 | auto *NewGIF = |
214 | GlobalIFunc::create(Ty: Foo->getType(), AddressSpace: 0, Linkage: GlobalValue::ExternalLinkage, |
215 | Name: "NewGIF" , Resolver: Foo, /*Parent=*/nullptr); |
216 | EXPECT_EQ(M->ifunc_size(), 1u); |
217 | |
218 | M->insertIFunc(IFunc: NewGIF); |
219 | EXPECT_EQ(&*std::prev(M->ifuncs().end()), NewGIF); |
220 | |
221 | M->removeIFunc(IFunc: NewGIF); |
222 | EXPECT_EQ(M->ifunc_size(), 1u); |
223 | M->insertIFunc(IFunc: NewGIF); |
224 | EXPECT_EQ(M->ifunc_size(), 2u); |
225 | EXPECT_EQ(&*std::prev(M->ifuncs().end()), NewGIF); |
226 | |
227 | auto Range = M->ifuncs(); |
228 | EXPECT_EQ(&*Range.begin(), GIF); |
229 | EXPECT_EQ(&*std::next(Range.begin()), NewGIF); |
230 | EXPECT_EQ(std::next(Range.begin(), 2), Range.end()); |
231 | |
232 | M->removeIFunc(IFunc: NewGIF); |
233 | EXPECT_EQ(M->ifunc_size(), 1u); |
234 | |
235 | M->insertIFunc(IFunc: NewGIF); |
236 | M->eraseIFunc(IFunc: NewGIF); |
237 | EXPECT_EQ(M->ifunc_size(), 1u); |
238 | } |
239 | |
240 | TEST(ModuleTest, NamedMDList) { |
241 | // This tests all Module's functions that interact with Module::NamedMDList. |
242 | LLVMContext C; |
243 | SMDiagnostic Err; |
244 | LLVMContext Context; |
245 | auto M = std::make_unique<Module>(args: "M" , args&: C); |
246 | NamedMDNode *MDN1 = M->getOrInsertNamedMetadata(Name: "MDN1" ); |
247 | EXPECT_EQ(M->named_metadata_size(), 1u); |
248 | NamedMDNode *MDN2 = M->getOrInsertNamedMetadata(Name: "MDN2" ); |
249 | EXPECT_EQ(M->named_metadata_size(), 2u); |
250 | auto *NewMDN = M->getOrInsertNamedMetadata(Name: "NewMDN" ); |
251 | EXPECT_EQ(M->named_metadata_size(), 3u); |
252 | |
253 | M->removeNamedMDNode(MDNode: NewMDN); |
254 | EXPECT_EQ(M->named_metadata_size(), 2u); |
255 | |
256 | M->insertNamedMDNode(MDNode: NewMDN); |
257 | EXPECT_EQ(&*std::prev(M->named_metadata().end()), NewMDN); |
258 | |
259 | M->removeNamedMDNode(MDNode: NewMDN); |
260 | M->insertNamedMDNode(MDNode: NewMDN); |
261 | EXPECT_EQ(M->named_metadata_size(), 3u); |
262 | EXPECT_EQ(&*std::prev(M->named_metadata().end()), NewMDN); |
263 | |
264 | auto Range = M->named_metadata(); |
265 | EXPECT_EQ(&*Range.begin(), MDN1); |
266 | EXPECT_EQ(&*std::next(Range.begin(), 1), MDN2); |
267 | EXPECT_EQ(&*std::next(Range.begin(), 2), NewMDN); |
268 | EXPECT_EQ(std::next(Range.begin(), 3), Range.end()); |
269 | |
270 | M->eraseNamedMDNode(MDNode: NewMDN); |
271 | EXPECT_EQ(M->named_metadata_size(), 2u); |
272 | } |
273 | |
274 | TEST(ModuleTest, GlobalList) { |
275 | // This tests all Module's functions that interact with Module::GlobalList. |
276 | LLVMContext C; |
277 | SMDiagnostic Err; |
278 | LLVMContext Context; |
279 | std::unique_ptr<Module> M = parseAssemblyString(AsmString: R"( |
280 | @GV = external global i32 |
281 | )" , |
282 | Err, Context); |
283 | auto *GV = cast<GlobalVariable>(Val: M->getNamedValue(Name: "GV" )); |
284 | EXPECT_EQ(M->global_size(), 1u); |
285 | GlobalVariable *NewGV = new GlobalVariable( |
286 | Type::getInt32Ty(C), /*isConstant=*/true, GlobalValue::InternalLinkage, |
287 | /*Initializer=*/nullptr, "NewGV" ); |
288 | EXPECT_EQ(M->global_size(), 1u); |
289 | // Insert before |
290 | M->insertGlobalVariable(Where: M->globals().begin(), GV: NewGV); |
291 | EXPECT_EQ(M->global_size(), 2u); |
292 | EXPECT_EQ(&*M->globals().begin(), NewGV); |
293 | // Insert at end() |
294 | M->removeGlobalVariable(GV: NewGV); |
295 | EXPECT_EQ(M->global_size(), 1u); |
296 | M->insertGlobalVariable(GV: NewGV); |
297 | EXPECT_EQ(M->global_size(), 2u); |
298 | EXPECT_EQ(&*std::prev(M->globals().end()), NewGV); |
299 | // Check globals() |
300 | auto Range = M->globals(); |
301 | EXPECT_EQ(&*Range.begin(), GV); |
302 | EXPECT_EQ(&*std::next(Range.begin()), NewGV); |
303 | EXPECT_EQ(std::next(Range.begin(), 2), Range.end()); |
304 | // Check remove |
305 | M->removeGlobalVariable(GV: NewGV); |
306 | EXPECT_EQ(M->global_size(), 1u); |
307 | // Check erase |
308 | M->insertGlobalVariable(GV: NewGV); |
309 | M->eraseGlobalVariable(GV: NewGV); |
310 | EXPECT_EQ(M->global_size(), 1u); |
311 | } |
312 | |
313 | } // end namespace |
314 | |