xref: /llvm-project/llvm/unittests/IR/ModuleTest.cpp (revision a04b0d587a8d260063fe1d50f6fecdc585d75ff4)
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/Constants.h"
12 #include "llvm/IR/GlobalVariable.h"
13 #include "llvm/IR/ModuleSummaryIndex.h"
14 #include "llvm/Pass.h"
15 #include "llvm/Support/RandomNumberGenerator.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include "gtest/gtest.h"
19 
20 #include <random>
21 
22 using namespace llvm;
23 
24 namespace {
25 
26 bool sortByName(const GlobalVariable &L, const GlobalVariable &R) {
27   return L.getName() < R.getName();
28 }
29 
30 bool sortByNameReverse(const GlobalVariable &L, const GlobalVariable &R) {
31   return sortByName(R, L);
32 }
33 
34 TEST(ModuleTest, sortGlobalsByName) {
35   LLVMContext Context;
36   for (auto compare : {&sortByName, &sortByNameReverse}) {
37     Module M("M", Context);
38     Type *T = Type::getInt8Ty(Context);
39     GlobalValue::LinkageTypes L = GlobalValue::ExternalLinkage;
40     (void)new GlobalVariable(M, T, false, L, nullptr, "A");
41     (void)new GlobalVariable(M, T, false, L, nullptr, "F");
42     (void)new GlobalVariable(M, T, false, L, nullptr, "G");
43     (void)new GlobalVariable(M, T, false, L, nullptr, "E");
44     (void)new GlobalVariable(M, T, false, L, nullptr, "B");
45     (void)new GlobalVariable(M, T, false, L, nullptr, "H");
46     (void)new GlobalVariable(M, T, false, L, nullptr, "C");
47     (void)new GlobalVariable(M, T, false, L, nullptr, "D");
48 
49     // Sort the globals by name.
50     EXPECT_FALSE(std::is_sorted(M.global_begin(), M.global_end(), compare));
51   }
52 }
53 
54 TEST(ModuleTest, randomNumberGenerator) {
55   LLVMContext Context;
56   static char ID;
57   struct DummyPass : ModulePass {
58     DummyPass() : ModulePass(ID) {}
59     bool runOnModule(Module &) override { return true; }
60   } DP;
61 
62   Module M("R", Context);
63 
64   std::uniform_int_distribution<int> dist;
65   const size_t NBCheck = 10;
66 
67   std::array<int, NBCheck> RandomStreams[2];
68   for (auto &RandomStream : RandomStreams) {
69     std::unique_ptr<RandomNumberGenerator> RNG = M.createRNG(DP.getPassName());
70     std::generate(RandomStream.begin(), RandomStream.end(),
71                   [&]() { return dist(*RNG); });
72   }
73 
74   EXPECT_TRUE(std::equal(RandomStreams[0].begin(), RandomStreams[0].end(),
75                          RandomStreams[1].begin()));
76 }
77 
78 TEST(ModuleTest, setModuleFlag) {
79   LLVMContext Context;
80   Module M("M", Context);
81   StringRef Key = "Key";
82   Metadata *Val1 = MDString::get(Context, "Val1");
83   Metadata *Val2 = MDString::get(Context, "Val2");
84   EXPECT_EQ(nullptr, M.getModuleFlag(Key));
85   M.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val1);
86   EXPECT_EQ(Val1, M.getModuleFlag(Key));
87   M.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val2);
88   EXPECT_EQ(Val2, M.getModuleFlag(Key));
89 }
90 
91 TEST(ModuleTest, setModuleFlagInt) {
92   LLVMContext Context;
93   Module M("M", Context);
94   StringRef Key = "Key";
95   uint32_t Val1 = 1;
96   uint32_t Val2 = 2;
97   EXPECT_EQ(nullptr, M.getModuleFlag(Key));
98   M.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val1);
99   auto A1 = mdconst::extract_or_null<ConstantInt>(M.getModuleFlag(Key));
100   EXPECT_EQ(Val1, A1->getZExtValue());
101   M.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val2);
102   auto A2 = mdconst::extract_or_null<ConstantInt>(M.getModuleFlag(Key));
103   EXPECT_EQ(Val2, A2->getZExtValue());
104 }
105 
106 const char *IRString = R"IR(
107   !llvm.module.flags = !{!0}
108 
109   !0 = !{i32 1, !"ProfileSummary", !1}
110   !1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
111   !2 = !{!"ProfileFormat", !"SampleProfile"}
112   !3 = !{!"TotalCount", i64 10000}
113   !4 = !{!"MaxCount", i64 10}
114   !5 = !{!"MaxInternalCount", i64 1}
115   !6 = !{!"MaxFunctionCount", i64 1000}
116   !7 = !{!"NumCounts", i64 200}
117   !8 = !{!"NumFunctions", i64 3}
118   !9 = !{!"DetailedSummary", !10}
119   !10 = !{!11, !12, !13}
120   !11 = !{i32 10000, i64 1000, i32 1}
121   !12 = !{i32 990000, i64 300, i32 10}
122   !13 = !{i32 999999, i64 5, i32 100}
123 )IR";
124 
125 TEST(ModuleTest, setProfileSummary) {
126   SMDiagnostic Err;
127   LLVMContext Context;
128   std::unique_ptr<Module> M = parseAssemblyString(IRString, Err, Context);
129   auto *PS = ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false));
130   EXPECT_NE(nullptr, PS);
131   EXPECT_FALSE(PS->isPartialProfile());
132   PS->setPartialProfile(true);
133   M->setProfileSummary(PS->getMD(Context), ProfileSummary::PSK_Sample);
134   delete PS;
135   PS = ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false));
136   EXPECT_NE(nullptr, PS);
137   EXPECT_EQ(true, PS->isPartialProfile());
138   delete PS;
139 }
140 
141 TEST(ModuleTest, setPartialSampleProfileRatio) {
142   const char *IRString = R"IR(
143   !llvm.module.flags = !{!0}
144 
145   !0 = !{i32 1, !"ProfileSummary", !1}
146   !1 = !{!2, !3, !4, !5, !6, !7, !8, !9, !10, !11}
147   !2 = !{!"ProfileFormat", !"SampleProfile"}
148   !3 = !{!"TotalCount", i64 10000}
149   !4 = !{!"MaxCount", i64 10}
150   !5 = !{!"MaxInternalCount", i64 1}
151   !6 = !{!"MaxFunctionCount", i64 1000}
152   !7 = !{!"NumCounts", i64 200}
153   !8 = !{!"NumFunctions", i64 3}
154   !9 = !{!"IsPartialProfile", i64 1}
155   !10 = !{!"PartialProfileRatio", double 0.0}
156   !11 = !{!"DetailedSummary", !12}
157   !12 = !{!13, !14, !15}
158   !13 = !{i32 10000, i64 1000, i32 1}
159   !14 = !{i32 990000, i64 300, i32 10}
160   !15 = !{i32 999999, i64 5, i32 100}
161   )IR";
162 
163   SMDiagnostic Err;
164   LLVMContext Context;
165   std::unique_ptr<Module> M = parseAssemblyString(IRString, Err, Context);
166   ModuleSummaryIndex Index(/*HaveGVs*/ false);
167   const unsigned BlockCount = 100;
168   const unsigned NumCounts = 200;
169   Index.setBlockCount(BlockCount);
170   M->setPartialSampleProfileRatio(Index);
171   double Ratio = (double)BlockCount / NumCounts;
172   std::unique_ptr<ProfileSummary> ProfileSummary(
173       ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false)));
174   EXPECT_EQ(Ratio, ProfileSummary->getPartialProfileRatio());
175 }
176 
177 TEST(ModuleTest, AliasList) {
178   // This tests all Module's functions that interact with Module::AliasList.
179   LLVMContext C;
180   SMDiagnostic Err;
181   LLVMContext Context;
182   std::unique_ptr<Module> M = parseAssemblyString(R"(
183 declare void @Foo()
184 @GA = alias void (), ptr @Foo
185 )",
186                                                   Err, Context);
187   Function *Foo = M->getFunction("Foo");
188   auto *GA = M->getNamedAlias("GA");
189   EXPECT_EQ(M->alias_size(), 1u);
190   auto *NewGA =
191       GlobalAlias::create(Foo->getType(), 0, GlobalValue::ExternalLinkage,
192                           "NewGA", Foo, /*Parent=*/nullptr);
193   EXPECT_EQ(M->alias_size(), 1u);
194 
195   M->insertAlias(NewGA);
196   EXPECT_EQ(&*std::prev(M->aliases().end()), NewGA);
197 
198   M->removeAlias(NewGA);
199   EXPECT_EQ(M->alias_size(), 1u);
200   M->insertAlias(NewGA);
201   EXPECT_EQ(M->alias_size(), 2u);
202   EXPECT_EQ(&*std::prev(M->aliases().end()), NewGA);
203 
204   auto Range = M->aliases();
205   EXPECT_EQ(&*Range.begin(), GA);
206   EXPECT_EQ(&*std::next(Range.begin()), NewGA);
207   EXPECT_EQ(std::next(Range.begin(), 2), Range.end());
208 
209   M->removeAlias(NewGA);
210   EXPECT_EQ(M->alias_size(), 1u);
211 
212   M->insertAlias(NewGA);
213   M->eraseAlias(NewGA);
214   EXPECT_EQ(M->alias_size(), 1u);
215 }
216 
217 TEST(ModuleTest, IFuncList) {
218   // This tests all Module's functions that interact with Module::IFuncList.
219   LLVMContext C;
220   SMDiagnostic Err;
221   LLVMContext Context;
222   std::unique_ptr<Module> M = parseAssemblyString(R"(
223 declare void @Foo()
224 @GIF = ifunc void (), ptr @Foo
225 )",
226                                                   Err, Context);
227   Function *Foo = M->getFunction("Foo");
228   auto *GIF = M->getNamedIFunc("GIF");
229   EXPECT_EQ(M->ifunc_size(), 1u);
230   auto *NewGIF =
231       GlobalIFunc::create(Foo->getType(), 0, GlobalValue::ExternalLinkage,
232                           "NewGIF", Foo, /*Parent=*/nullptr);
233   EXPECT_EQ(M->ifunc_size(), 1u);
234 
235   M->insertIFunc(NewGIF);
236   EXPECT_EQ(&*std::prev(M->ifuncs().end()), NewGIF);
237 
238   M->removeIFunc(NewGIF);
239   EXPECT_EQ(M->ifunc_size(), 1u);
240   M->insertIFunc(NewGIF);
241   EXPECT_EQ(M->ifunc_size(), 2u);
242   EXPECT_EQ(&*std::prev(M->ifuncs().end()), NewGIF);
243 
244   auto Range = M->ifuncs();
245   EXPECT_EQ(&*Range.begin(), GIF);
246   EXPECT_EQ(&*std::next(Range.begin()), NewGIF);
247   EXPECT_EQ(std::next(Range.begin(), 2), Range.end());
248 
249   M->removeIFunc(NewGIF);
250   EXPECT_EQ(M->ifunc_size(), 1u);
251 
252   M->insertIFunc(NewGIF);
253   M->eraseIFunc(NewGIF);
254   EXPECT_EQ(M->ifunc_size(), 1u);
255 }
256 
257 TEST(ModuleTest, NamedMDList) {
258   // This tests all Module's functions that interact with Module::NamedMDList.
259   LLVMContext C;
260   SMDiagnostic Err;
261   LLVMContext Context;
262   auto M = std::make_unique<Module>("M", C);
263   NamedMDNode *MDN1 = M->getOrInsertNamedMetadata("MDN1");
264   EXPECT_EQ(M->named_metadata_size(), 1u);
265   NamedMDNode *MDN2 = M->getOrInsertNamedMetadata("MDN2");
266   EXPECT_EQ(M->named_metadata_size(), 2u);
267   auto *NewMDN = M->getOrInsertNamedMetadata("NewMDN");
268   EXPECT_EQ(M->named_metadata_size(), 3u);
269 
270   M->removeNamedMDNode(NewMDN);
271   EXPECT_EQ(M->named_metadata_size(), 2u);
272 
273   M->insertNamedMDNode(NewMDN);
274   EXPECT_EQ(&*std::prev(M->named_metadata().end()), NewMDN);
275 
276   M->removeNamedMDNode(NewMDN);
277   M->insertNamedMDNode(NewMDN);
278   EXPECT_EQ(M->named_metadata_size(), 3u);
279   EXPECT_EQ(&*std::prev(M->named_metadata().end()), NewMDN);
280 
281   auto Range = M->named_metadata();
282   EXPECT_EQ(&*Range.begin(), MDN1);
283   EXPECT_EQ(&*std::next(Range.begin(), 1), MDN2);
284   EXPECT_EQ(&*std::next(Range.begin(), 2), NewMDN);
285   EXPECT_EQ(std::next(Range.begin(), 3), Range.end());
286 
287   M->eraseNamedMDNode(NewMDN);
288   EXPECT_EQ(M->named_metadata_size(), 2u);
289 }
290 
291 TEST(ModuleTest, GlobalList) {
292   // This tests all Module's functions that interact with Module::GlobalList.
293   LLVMContext C;
294   SMDiagnostic Err;
295   LLVMContext Context;
296   std::unique_ptr<Module> M = parseAssemblyString(R"(
297 @GV = external global i32
298 )",
299                                                   Err, Context);
300   auto *GV = cast<GlobalVariable>(M->getNamedValue("GV"));
301   EXPECT_EQ(M->global_size(), 1u);
302   GlobalVariable *NewGV = new GlobalVariable(
303       Type::getInt32Ty(C), /*isConstant=*/true, GlobalValue::InternalLinkage,
304       /*Initializer=*/nullptr, "NewGV");
305   EXPECT_EQ(M->global_size(), 1u);
306   // Insert before
307   M->insertGlobalVariable(M->globals().begin(), NewGV);
308   EXPECT_EQ(M->global_size(), 2u);
309   EXPECT_EQ(&*M->globals().begin(), NewGV);
310   // Insert at end()
311   M->removeGlobalVariable(NewGV);
312   EXPECT_EQ(M->global_size(), 1u);
313   M->insertGlobalVariable(NewGV);
314   EXPECT_EQ(M->global_size(), 2u);
315   EXPECT_EQ(&*std::prev(M->globals().end()), NewGV);
316   // Check globals()
317   auto Range = M->globals();
318   EXPECT_EQ(&*Range.begin(), GV);
319   EXPECT_EQ(&*std::next(Range.begin()), NewGV);
320   EXPECT_EQ(std::next(Range.begin(), 2), Range.end());
321   // Check remove
322   M->removeGlobalVariable(NewGV);
323   EXPECT_EQ(M->global_size(), 1u);
324   // Check erase
325   M->insertGlobalVariable(NewGV);
326   M->eraseGlobalVariable(NewGV);
327   EXPECT_EQ(M->global_size(), 1u);
328 }
329 
330 TEST(ModuleTest, MoveAssign) {
331   // This tests that we can move-assign modules, we parse two modules and
332   // move assign the second one to the first one, and check that the print
333   // is equal to what we loaded.
334   LLVMContext C;
335   SMDiagnostic Err;
336   LLVMContext Context;
337   std::unique_ptr<Module> M1 = parseAssemblyString(R"(
338 ; ModuleID = '<string>'
339 source_filename = "<string1>"
340 
341 @GV1 = external global i32
342 
343 @GA1 = alias void (), ptr @Foo1
344 
345 define void @Foo1() {
346   ret void
347 }
348 
349 !llvm.module.flags = !{!0}
350 !llvm.dbg.cu = !{!1}
351 !foo1 = !{!3}
352 !bar1 = !{!4}
353 
354 !0 = !{i32 2, !"Debug Info Version", i32 3}
355 !1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang1", isOptimized: true, flags: "-O2", runtimeVersion: 0, splitDebugFilename: "abc.debug", emissionKind: LineTablesOnly)
356 !2 = !DIFile(filename: "path/to/file1", directory: "/path/to/dir1")
357 !3 = !DILocation(line: 12, column: 34, scope: !4)
358 !4 = distinct !DISubprogram(name: "foo1", scope: null, spFlags: DISPFlagDefinition, unit: !1)
359 )",
360                                                    Err, Context);
361   ASSERT_TRUE(M1.get());
362 
363   StringLiteral M2Str = R"(
364 ; ModuleID = '<string>'
365 source_filename = "<string2>"
366 
367 @GV2 = external global i32
368 
369 @GA2 = alias void (), ptr @Foo2
370 
371 define void @Foo2() {
372   ret void
373 }
374 
375 !llvm.module.flags = !{!0}
376 !llvm.dbg.cu = !{!1}
377 !foo2 = !{!3}
378 !bar2 = !{!4}
379 
380 !0 = !{i32 2, !"Debug Info Version", i32 3}
381 !1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !2, producer: "clang2", isOptimized: true, flags: "-O2", runtimeVersion: 0, splitDebugFilename: "abc.debug", emissionKind: LineTablesOnly)
382 !2 = !DIFile(filename: "path/to/file2", directory: "/path/to/dir2")
383 !3 = !DILocation(line: 1234, column: 56, scope: !4)
384 !4 = distinct !DISubprogram(name: "foo2", scope: null, spFlags: DISPFlagDefinition, unit: !1)
385 )";
386   {
387     std::unique_ptr<Module> M2 = parseAssemblyString(M2Str, Err, Context);
388     ASSERT_TRUE(M2.get());
389     auto *GV1 = M1->getNamedValue("GV1");
390     ASSERT_TRUE(GV1);
391     auto *GV2 = M2->getNamedValue("GV2");
392     ASSERT_TRUE(GV2);
393     ASSERT_EQ(GV2->getParent(), &*M2);
394     *M1 = std::move(*M2);
395     ASSERT_EQ(GV2->getParent(), &*M1);
396   }
397 
398   std::string M1Print;
399   {
400     llvm::raw_string_ostream Os(M1Print);
401     Os << "\n" << *M1;
402   }
403   ASSERT_EQ(M2Str, M1Print);
404 }
405 
406 } // end namespace
407