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 "gtest/gtest.h"
16 
17 #include <random>
18 
19 using namespace llvm;
20 
21 namespace {
22 
23 bool sortByName(const GlobalVariable &L, const GlobalVariable &R) {
24   return L.getName() < R.getName();
25 }
26 
27 bool sortByNameReverse(const GlobalVariable &L, const GlobalVariable &R) {
28   return sortByName(R, L);
29 }
30 
31 TEST(ModuleTest, sortGlobalsByName) {
32   LLVMContext Context;
33   for (auto compare : {&sortByName, &sortByNameReverse}) {
34     Module M("M", Context);
35     Type *T = Type::getInt8Ty(Context);
36     GlobalValue::LinkageTypes L = GlobalValue::ExternalLinkage;
37     (void)new GlobalVariable(M, T, false, L, nullptr, "A");
38     (void)new GlobalVariable(M, T, false, L, nullptr, "F");
39     (void)new GlobalVariable(M, T, false, L, nullptr, "G");
40     (void)new GlobalVariable(M, T, false, L, nullptr, "E");
41     (void)new GlobalVariable(M, T, false, L, nullptr, "B");
42     (void)new GlobalVariable(M, T, false, L, nullptr, "H");
43     (void)new GlobalVariable(M, T, false, L, nullptr, "C");
44     (void)new GlobalVariable(M, T, false, L, nullptr, "D");
45 
46     // Sort the globals by name.
47     EXPECT_FALSE(std::is_sorted(M.global_begin(), M.global_end(), compare));
48     M.getGlobalList().sort(compare);
49     EXPECT_TRUE(std::is_sorted(M.global_begin(), M.global_end(), compare));
50   }
51 }
52 
53 TEST(ModuleTest, randomNumberGenerator) {
54   LLVMContext Context;
55   static char ID;
56   struct DummyPass : ModulePass {
57     DummyPass() : ModulePass(ID) {}
58     bool runOnModule(Module &) { return true; }
59   } DP;
60 
61   Module M("R", Context);
62 
63   std::uniform_int_distribution<int> dist;
64   const size_t NBCheck = 10;
65 
66   std::array<int, NBCheck> RandomStreams[2];
67   for (auto &RandomStream : RandomStreams) {
68     std::unique_ptr<RandomNumberGenerator> RNG = M.createRNG(DP.getPassName());
69     std::generate(RandomStream.begin(), RandomStream.end(),
70                   [&]() { return dist(*RNG); });
71   }
72 
73   EXPECT_TRUE(std::equal(RandomStreams[0].begin(), RandomStreams[0].end(),
74                          RandomStreams[1].begin()));
75 }
76 
77 TEST(ModuleTest, setModuleFlag) {
78   LLVMContext Context;
79   Module M("M", Context);
80   StringRef Key = "Key";
81   Metadata *Val1 = MDString::get(Context, "Val1");
82   Metadata *Val2 = MDString::get(Context, "Val2");
83   EXPECT_EQ(nullptr, M.getModuleFlag(Key));
84   M.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val1);
85   EXPECT_EQ(Val1, M.getModuleFlag(Key));
86   M.setModuleFlag(Module::ModFlagBehavior::Error, Key, Val2);
87   EXPECT_EQ(Val2, M.getModuleFlag(Key));
88 }
89 
90 const char *IRString = R"IR(
91   !llvm.module.flags = !{!0}
92 
93   !0 = !{i32 1, !"ProfileSummary", !1}
94   !1 = !{!2, !3, !4, !5, !6, !7, !8, !9}
95   !2 = !{!"ProfileFormat", !"SampleProfile"}
96   !3 = !{!"TotalCount", i64 10000}
97   !4 = !{!"MaxCount", i64 10}
98   !5 = !{!"MaxInternalCount", i64 1}
99   !6 = !{!"MaxFunctionCount", i64 1000}
100   !7 = !{!"NumCounts", i64 200}
101   !8 = !{!"NumFunctions", i64 3}
102   !9 = !{!"DetailedSummary", !10}
103   !10 = !{!11, !12, !13}
104   !11 = !{i32 10000, i64 1000, i32 1}
105   !12 = !{i32 990000, i64 300, i32 10}
106   !13 = !{i32 999999, i64 5, i32 100}
107 )IR";
108 
109 TEST(ModuleTest, setProfileSummary) {
110   SMDiagnostic Err;
111   LLVMContext Context;
112   std::unique_ptr<Module> M = parseAssemblyString(IRString, Err, Context);
113   auto *PS = ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false));
114   EXPECT_NE(nullptr, PS);
115   EXPECT_EQ(false, PS->isPartialProfile());
116   PS->setPartialProfile(true);
117   M->setProfileSummary(PS->getMD(Context), ProfileSummary::PSK_Sample);
118   delete PS;
119   PS = ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false));
120   EXPECT_NE(nullptr, PS);
121   EXPECT_EQ(true, PS->isPartialProfile());
122   delete PS;
123 }
124 
125 TEST(ModuleTest, setPartialSampleProfileRatio) {
126   const char *IRString = R"IR(
127   !llvm.module.flags = !{!0}
128 
129   !0 = !{i32 1, !"ProfileSummary", !1}
130   !1 = !{!2, !3, !4, !5, !6, !7, !8, !9, !10, !11}
131   !2 = !{!"ProfileFormat", !"SampleProfile"}
132   !3 = !{!"TotalCount", i64 10000}
133   !4 = !{!"MaxCount", i64 10}
134   !5 = !{!"MaxInternalCount", i64 1}
135   !6 = !{!"MaxFunctionCount", i64 1000}
136   !7 = !{!"NumCounts", i64 200}
137   !8 = !{!"NumFunctions", i64 3}
138   !9 = !{!"IsPartialProfile", i64 1}
139   !10 = !{!"PartialProfileRatio", double 0.0}
140   !11 = !{!"DetailedSummary", !12}
141   !12 = !{!13, !14, !15}
142   !13 = !{i32 10000, i64 1000, i32 1}
143   !14 = !{i32 990000, i64 300, i32 10}
144   !15 = !{i32 999999, i64 5, i32 100}
145   )IR";
146 
147   SMDiagnostic Err;
148   LLVMContext Context;
149   std::unique_ptr<Module> M = parseAssemblyString(IRString, Err, Context);
150   ModuleSummaryIndex Index(/*HaveGVs*/ false);
151   const unsigned BlockCount = 100;
152   const unsigned NumCounts = 200;
153   Index.setBlockCount(BlockCount);
154   M->setPartialSampleProfileRatio(Index);
155   double Ratio = (double)BlockCount / NumCounts;
156   std::unique_ptr<ProfileSummary> ProfileSummary(
157       ProfileSummary::getFromMD(M->getProfileSummary(/*IsCS*/ false)));
158   EXPECT_EQ(Ratio, ProfileSummary->getPartialProfileRatio());
159 }
160 
161 } // end namespace
162