Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / unittests / IR / ModuleTest.cpp
blobda684b85a4dfb52245130b4ec1da465c846ef208
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 //===----------------------------------------------------------------------===//
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"
18 #include <random>
20 using namespace llvm;
22 namespace {
24 bool sortByName(const GlobalVariable &L, const GlobalVariable &R) {
25 return L.getName() < R.getName();
28 bool sortByNameReverse(const GlobalVariable &L, const GlobalVariable &R) {
29 return sortByName(R, L);
32 TEST(ModuleTest, sortGlobalsByName) {
33 LLVMContext Context;
34 for (auto compare : {&sortByName, &sortByNameReverse}) {
35 Module M("M", Context);
36 Type *T = Type::getInt8Ty(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");
47 // Sort the globals by name.
48 EXPECT_FALSE(std::is_sorted(M.global_begin(), M.global_end(), compare));
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;
60 Module M("R", Context);
62 std::uniform_int_distribution<int> dist;
63 const size_t NBCheck = 10;
65 std::array<int, NBCheck> RandomStreams[2];
66 for (auto &RandomStream : RandomStreams) {
67 std::unique_ptr<RandomNumberGenerator> RNG = M.createRNG(DP.getPassName());
68 std::generate(RandomStream.begin(), RandomStream.end(),
69 [&]() { return dist(*RNG); });
72 EXPECT_TRUE(std::equal(RandomStreams[0].begin(), RandomStreams[0].end(),
73 RandomStreams[1].begin()));
76 TEST(ModuleTest, setModuleFlag) {
77 LLVMContext Context;
78 Module M("M", Context);
79 StringRef Key = "Key";
80 Metadata *Val1 = MDString::get(Context, "Val1");
81 Metadata *Val2 = MDString::get(Context, "Val2");
82 EXPECT_EQ(nullptr, M.getModuleFlag(Key));
83 M.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val1);
84 EXPECT_EQ(Val1, M.getModuleFlag(Key));
85 M.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val2);
86 EXPECT_EQ(Val2, M.getModuleFlag(Key));
89 const char *IRString = R"IR(
90 !llvm.module.flags = !{!0}
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";
108 TEST(ModuleTest, setProfileSummary) {
109 SMDiagnostic Err;
110 LLVMContext Context;
111 std::unique_ptr<Module> M = parseAssemblyString(IRString, Err, Context);
112 auto *PS = ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false));
113 EXPECT_NE(nullptr, PS);
114 EXPECT_FALSE(PS->isPartialProfile());
115 PS->setPartialProfile(true);
116 M->setProfileSummary(PS->getMD(Context), ProfileSummary::PSK_Sample);
117 delete PS;
118 PS = ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false));
119 EXPECT_NE(nullptr, PS);
120 EXPECT_EQ(true, PS->isPartialProfile());
121 delete PS;
124 TEST(ModuleTest, setPartialSampleProfileRatio) {
125 const char *IRString = R"IR(
126 !llvm.module.flags = !{!0}
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";
146 SMDiagnostic Err;
147 LLVMContext Context;
148 std::unique_ptr<Module> M = parseAssemblyString(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(M->getProfileSummary(/*IsCS*/ false)));
157 EXPECT_EQ(Ratio, ProfileSummary->getPartialProfileRatio());
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(R"(
166 declare void @Foo()
167 @GA = alias void (), ptr @Foo
169 Err, Context);
170 Function *Foo = M->getFunction("Foo");
171 auto *GA = M->getNamedAlias("GA");
172 EXPECT_EQ(M->alias_size(), 1u);
173 auto *NewGA =
174 GlobalAlias::create(Foo->getType(), 0, GlobalValue::ExternalLinkage,
175 "NewGA", Foo, /*Parent=*/nullptr);
176 EXPECT_EQ(M->alias_size(), 1u);
178 M->insertAlias(NewGA);
179 EXPECT_EQ(&*std::prev(M->aliases().end()), NewGA);
181 M->removeAlias(NewGA);
182 EXPECT_EQ(M->alias_size(), 1u);
183 M->insertAlias(NewGA);
184 EXPECT_EQ(M->alias_size(), 2u);
185 EXPECT_EQ(&*std::prev(M->aliases().end()), NewGA);
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());
192 M->removeAlias(NewGA);
193 EXPECT_EQ(M->alias_size(), 1u);
195 M->insertAlias(NewGA);
196 M->eraseAlias(NewGA);
197 EXPECT_EQ(M->alias_size(), 1u);
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(R"(
206 declare void @Foo()
207 @GIF = ifunc void (), ptr @Foo
209 Err, Context);
210 Function *Foo = M->getFunction("Foo");
211 auto *GIF = M->getNamedIFunc("GIF");
212 EXPECT_EQ(M->ifunc_size(), 1u);
213 auto *NewGIF =
214 GlobalIFunc::create(Foo->getType(), 0, GlobalValue::ExternalLinkage,
215 "NewGIF", Foo, /*Parent=*/nullptr);
216 EXPECT_EQ(M->ifunc_size(), 1u);
218 M->insertIFunc(NewGIF);
219 EXPECT_EQ(&*std::prev(M->ifuncs().end()), NewGIF);
221 M->removeIFunc(NewGIF);
222 EXPECT_EQ(M->ifunc_size(), 1u);
223 M->insertIFunc(NewGIF);
224 EXPECT_EQ(M->ifunc_size(), 2u);
225 EXPECT_EQ(&*std::prev(M->ifuncs().end()), NewGIF);
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());
232 M->removeIFunc(NewGIF);
233 EXPECT_EQ(M->ifunc_size(), 1u);
235 M->insertIFunc(NewGIF);
236 M->eraseIFunc(NewGIF);
237 EXPECT_EQ(M->ifunc_size(), 1u);
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>("M", C);
246 NamedMDNode *MDN1 = M->getOrInsertNamedMetadata("MDN1");
247 EXPECT_EQ(M->named_metadata_size(), 1u);
248 NamedMDNode *MDN2 = M->getOrInsertNamedMetadata("MDN2");
249 EXPECT_EQ(M->named_metadata_size(), 2u);
250 auto *NewMDN = M->getOrInsertNamedMetadata("NewMDN");
251 EXPECT_EQ(M->named_metadata_size(), 3u);
253 M->removeNamedMDNode(NewMDN);
254 EXPECT_EQ(M->named_metadata_size(), 2u);
256 M->insertNamedMDNode(NewMDN);
257 EXPECT_EQ(&*std::prev(M->named_metadata().end()), NewMDN);
259 M->removeNamedMDNode(NewMDN);
260 M->insertNamedMDNode(NewMDN);
261 EXPECT_EQ(M->named_metadata_size(), 3u);
262 EXPECT_EQ(&*std::prev(M->named_metadata().end()), NewMDN);
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());
270 M->eraseNamedMDNode(NewMDN);
271 EXPECT_EQ(M->named_metadata_size(), 2u);
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(R"(
280 @GV = external global i32
282 Err, Context);
283 auto *GV = cast<GlobalVariable>(M->getNamedValue("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(M->globals().begin(), NewGV);
291 EXPECT_EQ(M->global_size(), 2u);
292 EXPECT_EQ(&*M->globals().begin(), NewGV);
293 // Insert at end()
294 M->removeGlobalVariable(NewGV);
295 EXPECT_EQ(M->global_size(), 1u);
296 M->insertGlobalVariable(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(NewGV);
306 EXPECT_EQ(M->global_size(), 1u);
307 // Check erase
308 M->insertGlobalVariable(NewGV);
309 M->eraseGlobalVariable(NewGV);
310 EXPECT_EQ(M->global_size(), 1u);
313 } // end namespace