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/Pass.h"
13 #include "llvm/Support/RandomNumberGenerator.h"
14 #include "gtest/gtest.h"
15 
16 #include <random>
17 
18 using namespace llvm;
19 
20 namespace {
21 
22 bool sortByName(const GlobalVariable &L, const GlobalVariable &R) {
23   return L.getName() < R.getName();
24 }
25 
26 bool sortByNameReverse(const GlobalVariable &L, const GlobalVariable &R) {
27   return sortByName(R, L);
28 }
29 
30 TEST(ModuleTest, sortGlobalsByName) {
31   LLVMContext Context;
32   for (auto compare : {&sortByName, &sortByNameReverse}) {
33     Module M("M", Context);
34     Type *T = Type::getInt8Ty(Context);
35     GlobalValue::LinkageTypes L = GlobalValue::ExternalLinkage;
36     (void)new GlobalVariable(M, T, false, L, nullptr, "A");
37     (void)new GlobalVariable(M, T, false, L, nullptr, "F");
38     (void)new GlobalVariable(M, T, false, L, nullptr, "G");
39     (void)new GlobalVariable(M, T, false, L, nullptr, "E");
40     (void)new GlobalVariable(M, T, false, L, nullptr, "B");
41     (void)new GlobalVariable(M, T, false, L, nullptr, "H");
42     (void)new GlobalVariable(M, T, false, L, nullptr, "C");
43     (void)new GlobalVariable(M, T, false, L, nullptr, "D");
44 
45     // Sort the globals by name.
46     EXPECT_FALSE(std::is_sorted(M.global_begin(), M.global_end(), compare));
47     M.getGlobalList().sort(compare);
48     EXPECT_TRUE(std::is_sorted(M.global_begin(), M.global_end(), compare));
49   }
50 }
51 
52 TEST(ModuleTest, randomNumberGenerator) {
53   LLVMContext Context;
54   static char ID;
55   struct DummyPass : ModulePass {
56     DummyPass() : ModulePass(ID) {}
57     bool runOnModule(Module &) { 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(DP.getPassName());
68     std::generate(RandomStream.begin(), RandomStream.end(),
69                   [&]() { return dist(*RNG); });
70   }
71 
72   EXPECT_TRUE(std::equal(RandomStreams[0].begin(), RandomStreams[0].end(),
73                          RandomStreams[1].begin()));
74 }
75 
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));
87 }
88 
89 const 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 
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_EQ(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;
122 }
123 
124 } // end namespace
125