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
20using namespace llvm;
21
22namespace {
23
24bool sortByName(const GlobalVariable &L, const GlobalVariable &R) {
25 return L.getName() < R.getName();
26}
27
28bool sortByNameReverse(const GlobalVariable &L, const GlobalVariable &R) {
29 return sortByName(L: R, R: L);
30}
31
32TEST(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
52TEST(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
76TEST(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
89const 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
108TEST(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
124TEST(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
160TEST(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"(
166declare 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
200TEST(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"(
206declare 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
240TEST(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
274TEST(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

source code of llvm/unittests/IR/ModuleTest.cpp