[LV] Add tests with dereferenceable assumptions.
[llvm-project.git] / llvm / unittests / ProfileData / PGOCtxProfReaderWriterTest.cpp
bloba7950e124908477159753e7cb5d819e63322d005
1 //===-------------- PGOCtxProfReadWriteTest.cpp ---------------------------===//
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/ADT/DenseSet.h"
10 #include "llvm/Bitcode/BitcodeAnalyzer.h"
11 #include "llvm/ProfileData/CtxInstrContextNode.h"
12 #include "llvm/ProfileData/PGOCtxProfReader.h"
13 #include "llvm/ProfileData/PGOCtxProfWriter.h"
14 #include "llvm/Support/Error.h"
15 #include "llvm/Support/MemoryBuffer.h"
16 #include "llvm/Support/raw_ostream.h"
17 #include "llvm/Testing/Support/SupportHelpers.h"
18 #include "gtest/gtest.h"
20 using namespace llvm;
21 using namespace llvm::ctx_profile;
23 class PGOCtxProfRWTest : public ::testing::Test {
24 std::vector<std::unique_ptr<char[]>> Nodes;
25 std::map<GUID, const ContextNode *> Roots;
27 public:
28 ContextNode *createNode(GUID Guid, uint32_t NumCounters,
29 uint32_t NumCallsites, ContextNode *Next = nullptr) {
30 auto AllocSize = ContextNode::getAllocSize(NumCounters, NumCallsites);
31 auto *Mem = Nodes.emplace_back(std::make_unique<char[]>(AllocSize)).get();
32 std::memset(Mem, 0, AllocSize);
33 auto *Ret = new (Mem) ContextNode(Guid, NumCounters, NumCallsites, Next);
34 return Ret;
37 void SetUp() override {
38 // Root (guid 1) has 2 callsites, one used for an indirect call to either
39 // guid 2 or 4.
40 // guid 2 calls guid 5
41 // guid 5 calls guid 2
42 // there's also a second root, guid3.
43 auto *Root1 = createNode(1, 2, 2);
44 Root1->counters()[0] = 10;
45 Root1->counters()[1] = 11;
46 Roots.insert({1, Root1});
47 auto *L1 = createNode(2, 1, 1);
48 L1->counters()[0] = 12;
49 Root1->subContexts()[1] = createNode(4, 3, 1, L1);
50 Root1->subContexts()[1]->counters()[0] = 13;
51 Root1->subContexts()[1]->counters()[1] = 14;
52 Root1->subContexts()[1]->counters()[2] = 15;
54 auto *L3 = createNode(5, 6, 3);
55 for (auto I = 0; I < 6; ++I)
56 L3->counters()[I] = 16 + I;
57 L1->subContexts()[0] = L3;
58 L3->subContexts()[2] = createNode(2, 1, 1);
59 L3->subContexts()[2]->counters()[0] = 30;
60 auto *Root2 = createNode(3, 1, 0);
61 Root2->counters()[0] = 40;
62 Roots.insert({3, Root2});
65 const std::map<GUID, const ContextNode *> &roots() const { return Roots; }
68 void checkSame(const ContextNode &Raw, const PGOCtxProfContext &Profile) {
69 EXPECT_EQ(Raw.guid(), Profile.guid());
70 ASSERT_EQ(Raw.counters_size(), Profile.counters().size());
71 for (auto I = 0U; I < Raw.counters_size(); ++I)
72 EXPECT_EQ(Raw.counters()[I], Profile.counters()[I]);
74 for (auto I = 0U; I < Raw.callsites_size(); ++I) {
75 if (Raw.subContexts()[I] == nullptr)
76 continue;
77 EXPECT_TRUE(Profile.hasCallsite(I));
78 const auto &ProfileTargets = Profile.callsite(I);
80 std::map<GUID, const ContextNode *> Targets;
81 for (const auto *N = Raw.subContexts()[I]; N; N = N->next())
82 EXPECT_TRUE(Targets.insert({N->guid(), N}).second);
84 EXPECT_EQ(Targets.size(), ProfileTargets.size());
85 for (auto It : Targets) {
86 auto PIt = ProfileTargets.find(It.second->guid());
87 EXPECT_NE(PIt, ProfileTargets.end());
88 checkSame(*It.second, PIt->second);
93 TEST_F(PGOCtxProfRWTest, RoundTrip) {
94 llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true);
96 std::error_code EC;
97 raw_fd_stream Out(ProfileFile.path(), EC);
98 ASSERT_FALSE(EC);
100 PGOCtxProfileWriter Writer(Out);
101 for (auto &[_, R] : roots())
102 Writer.write(*R);
106 ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
107 MemoryBuffer::getFile(ProfileFile.path());
108 ASSERT_TRUE(!!MB);
109 ASSERT_NE(*MB, nullptr);
111 // Check it's analyzable by the BCAnalyzer
112 BitcodeAnalyzer BA((*MB)->getBuffer());
113 std::string AnalyzerDump;
114 raw_string_ostream OS(AnalyzerDump);
115 BCDumpOptions Opts(OS);
117 // As in, expect no error.
118 EXPECT_FALSE(BA.analyze(Opts));
119 EXPECT_TRUE(AnalyzerDump.find("<Metadata BlockID") != std::string::npos);
120 EXPECT_TRUE(AnalyzerDump.find("<Context BlockID") != std::string::npos);
121 EXPECT_TRUE(AnalyzerDump.find("<CalleeIndex codeid") != std::string::npos);
123 PGOCtxProfileReader Reader((*MB)->getBuffer());
124 auto Expected = Reader.loadContexts();
125 ASSERT_TRUE(!!Expected);
126 auto &Ctxes = *Expected;
127 EXPECT_EQ(Ctxes.size(), roots().size());
128 EXPECT_EQ(Ctxes.size(), 2U);
129 for (auto &[G, R] : roots())
130 checkSame(*R, Ctxes.find(G)->second);
132 DenseSet<GlobalValue::GUID> Guids;
133 Ctxes.at(1U).getContainedGuids(Guids);
134 EXPECT_THAT(Guids,
135 testing::WhenSorted(testing::ElementsAre(1U, 2U, 4U, 5U)));
137 Guids.clear();
138 Ctxes.at(3U).getContainedGuids(Guids);
139 EXPECT_THAT(Guids, testing::ElementsAre(3U));
143 TEST_F(PGOCtxProfRWTest, InvalidCounters) {
144 auto *R = createNode(1, 0, 1);
145 llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true);
147 std::error_code EC;
148 raw_fd_stream Out(ProfileFile.path(), EC);
149 ASSERT_FALSE(EC);
151 PGOCtxProfileWriter Writer(Out);
152 Writer.write(*R);
156 auto MB = MemoryBuffer::getFile(ProfileFile.path());
157 ASSERT_TRUE(!!MB);
158 ASSERT_NE(*MB, nullptr);
159 PGOCtxProfileReader Reader((*MB)->getBuffer());
160 auto Expected = Reader.loadContexts();
161 EXPECT_FALSE(Expected);
162 consumeError(Expected.takeError());
166 TEST_F(PGOCtxProfRWTest, Empty) {
167 PGOCtxProfileReader Reader("");
168 auto Expected = Reader.loadContexts();
169 EXPECT_FALSE(Expected);
170 consumeError(Expected.takeError());
173 TEST_F(PGOCtxProfRWTest, Invalid) {
174 PGOCtxProfileReader Reader("Surely this is not valid");
175 auto Expected = Reader.loadContexts();
176 EXPECT_FALSE(Expected);
177 consumeError(Expected.takeError());
180 TEST_F(PGOCtxProfRWTest, ValidButEmpty) {
181 llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true);
183 std::error_code EC;
184 raw_fd_stream Out(ProfileFile.path(), EC);
185 ASSERT_FALSE(EC);
187 PGOCtxProfileWriter Writer(Out);
188 // don't write anything - this will just produce the metadata subblock.
192 auto MB = MemoryBuffer::getFile(ProfileFile.path());
193 ASSERT_TRUE(!!MB);
194 ASSERT_NE(*MB, nullptr);
196 PGOCtxProfileReader Reader((*MB)->getBuffer());
197 auto Expected = Reader.loadContexts();
198 EXPECT_TRUE(!!Expected);
199 EXPECT_TRUE(Expected->empty());
203 TEST_F(PGOCtxProfRWTest, WrongVersion) {
204 llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true);
206 std::error_code EC;
207 raw_fd_stream Out(ProfileFile.path(), EC);
208 ASSERT_FALSE(EC);
210 PGOCtxProfileWriter Writer(Out, PGOCtxProfileWriter::CurrentVersion + 1);
214 auto MB = MemoryBuffer::getFile(ProfileFile.path());
215 ASSERT_TRUE(!!MB);
216 ASSERT_NE(*MB, nullptr);
218 PGOCtxProfileReader Reader((*MB)->getBuffer());
219 auto Expected = Reader.loadContexts();
220 EXPECT_FALSE(Expected);
221 consumeError(Expected.takeError());
225 TEST_F(PGOCtxProfRWTest, DuplicateRoots) {
226 llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true);
228 std::error_code EC;
229 raw_fd_stream Out(ProfileFile.path(), EC);
230 ASSERT_FALSE(EC);
232 PGOCtxProfileWriter Writer(Out);
233 Writer.write(*createNode(1, 1, 1));
234 Writer.write(*createNode(1, 1, 1));
238 auto MB = MemoryBuffer::getFile(ProfileFile.path());
239 ASSERT_TRUE(!!MB);
240 ASSERT_NE(*MB, nullptr);
241 PGOCtxProfileReader Reader((*MB)->getBuffer());
242 auto Expected = Reader.loadContexts();
243 EXPECT_FALSE(Expected);
244 consumeError(Expected.takeError());
248 TEST_F(PGOCtxProfRWTest, DuplicateTargets) {
249 llvm::unittest::TempFile ProfileFile("ctx_profile", "", "", /*Unique*/ true);
251 std::error_code EC;
252 raw_fd_stream Out(ProfileFile.path(), EC);
253 ASSERT_FALSE(EC);
255 auto *R = createNode(1, 1, 1);
256 auto *L1 = createNode(2, 1, 0);
257 auto *L2 = createNode(2, 1, 0, L1);
258 R->subContexts()[0] = L2;
259 PGOCtxProfileWriter Writer(Out);
260 Writer.write(*R);
264 auto MB = MemoryBuffer::getFile(ProfileFile.path());
265 ASSERT_TRUE(!!MB);
266 ASSERT_NE(*MB, nullptr);
267 PGOCtxProfileReader Reader((*MB)->getBuffer());
268 auto Expected = Reader.loadContexts();
269 EXPECT_FALSE(Expected);
270 consumeError(Expected.takeError());