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
sortByName(const GlobalVariable & L,const GlobalVariable & R)24 bool sortByName(const GlobalVariable &L, const GlobalVariable &R) {
25 return L.getName() < R.getName();
26 }
27
sortByNameReverse(const GlobalVariable & L,const GlobalVariable & R)28 bool sortByNameReverse(const GlobalVariable &L, const GlobalVariable &R) {
29 return sortByName(R, L);
30 }
31
TEST(ModuleTest,sortGlobalsByName)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");
46
47 // Sort the globals by name.
48 EXPECT_FALSE(std::is_sorted(M.global_begin(), M.global_end(), compare));
49 M.getGlobalList().sort(compare);
50 EXPECT_TRUE(std::is_sorted(M.global_begin(), M.global_end(), compare));
51 }
52 }
53
TEST(ModuleTest,randomNumberGenerator)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
TEST(ModuleTest,setModuleFlag)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 const char *IRString = R"IR(
92 !llvm.module.flags = !{!0}
93
94 !0 = !{i32 1, !"ProfileSummary", !1}
95 !1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
96 !2 = !{!"ProfileFormat", !"SampleProfile"}
97 !3 = !{!"TotalCount", i64 10000}
98 !4 = !{!"MaxCount", i64 10}
99 !5 = !{!"MaxInternalCount", i64 1}
100 !6 = !{!"MaxFunctionCount", i64 1000}
101 !7 = !{!"NumCounts", i64 200}
102 !8 = !{!"NumFunctions", i64 3}
103 !9 = !{!"DetailedSummary", !10}
104 !10 = !{!11, !12, !13}
105 !11 = !{i32 10000, i64 1000, i32 1}
106 !12 = !{i32 990000, i64 300, i32 10}
107 !13 = !{i32 999999, i64 5, i32 100}
108 )IR";
109
TEST(ModuleTest,setProfileSummary)110 TEST(ModuleTest, setProfileSummary) {
111 SMDiagnostic Err;
112 LLVMContext Context;
113 std::unique_ptr<Module> M = parseAssemblyString(IRString, Err, Context);
114 auto *PS = ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false));
115 EXPECT_NE(nullptr, PS);
116 EXPECT_FALSE(PS->isPartialProfile());
117 PS->setPartialProfile(true);
118 M->setProfileSummary(PS->getMD(Context), ProfileSummary::PSK_Sample);
119 delete PS;
120 PS = ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false));
121 EXPECT_NE(nullptr, PS);
122 EXPECT_EQ(true, PS->isPartialProfile());
123 delete PS;
124 }
125
TEST(ModuleTest,setPartialSampleProfileRatio)126 TEST(ModuleTest, setPartialSampleProfileRatio) {
127 const char *IRString = R"IR(
128 !llvm.module.flags = !{!0}
129
130 !0 = !{i32 1, !"ProfileSummary", !1}
131 !1 = !{!2, !3, !4, !5, !6, !7, !8, !9, !10, !11}
132 !2 = !{!"ProfileFormat", !"SampleProfile"}
133 !3 = !{!"TotalCount", i64 10000}
134 !4 = !{!"MaxCount", i64 10}
135 !5 = !{!"MaxInternalCount", i64 1}
136 !6 = !{!"MaxFunctionCount", i64 1000}
137 !7 = !{!"NumCounts", i64 200}
138 !8 = !{!"NumFunctions", i64 3}
139 !9 = !{!"IsPartialProfile", i64 1}
140 !10 = !{!"PartialProfileRatio", double 0.0}
141 !11 = !{!"DetailedSummary", !12}
142 !12 = !{!13, !14, !15}
143 !13 = !{i32 10000, i64 1000, i32 1}
144 !14 = !{i32 990000, i64 300, i32 10}
145 !15 = !{i32 999999, i64 5, i32 100}
146 )IR";
147
148 SMDiagnostic Err;
149 LLVMContext Context;
150 std::unique_ptr<Module> M = parseAssemblyString(IRString, Err, Context);
151 ModuleSummaryIndex Index(/*HaveGVs*/ false);
152 const unsigned BlockCount = 100;
153 const unsigned NumCounts = 200;
154 Index.setBlockCount(BlockCount);
155 M->setPartialSampleProfileRatio(Index);
156 double Ratio = (double)BlockCount / NumCounts;
157 std::unique_ptr<ProfileSummary> ProfileSummary(
158 ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false)));
159 EXPECT_EQ(Ratio, ProfileSummary->getPartialProfileRatio());
160 }
161
162 } // end namespace
163