Revert r354244 "[DAGCombiner] Eliminate dead stores to stack."
[llvm-complete.git] / unittests / ProfileData / SampleProfTest.cpp
blobc25b3d2752b3cd8190269d76029e12ab2faf9593
1 //===- unittest/ProfileData/SampleProfTest.cpp ------------------*- C++ -*-===//
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/ProfileData/SampleProf.h"
10 #include "llvm/ADT/StringMap.h"
11 #include "llvm/ADT/StringRef.h"
12 #include "llvm/IR/LLVMContext.h"
13 #include "llvm/IR/Metadata.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/ProfileData/SampleProfReader.h"
16 #include "llvm/ProfileData/SampleProfWriter.h"
17 #include "llvm/Support/Casting.h"
18 #include "llvm/Support/ErrorOr.h"
19 #include "llvm/Support/MemoryBuffer.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include "gtest/gtest.h"
22 #include <string>
23 #include <vector>
25 using namespace llvm;
26 using namespace sampleprof;
28 static ::testing::AssertionResult NoError(std::error_code EC) {
29 if (!EC)
30 return ::testing::AssertionSuccess();
31 return ::testing::AssertionFailure() << "error " << EC.value() << ": "
32 << EC.message();
35 namespace {
37 struct SampleProfTest : ::testing::Test {
38 LLVMContext Context;
39 std::unique_ptr<SampleProfileWriter> Writer;
40 std::unique_ptr<SampleProfileReader> Reader;
42 SampleProfTest() : Writer(), Reader() {}
44 void createWriter(SampleProfileFormat Format, StringRef Profile) {
45 std::error_code EC;
46 std::unique_ptr<raw_ostream> OS(
47 new raw_fd_ostream(Profile, EC, sys::fs::F_None));
48 auto WriterOrErr = SampleProfileWriter::create(OS, Format);
49 ASSERT_TRUE(NoError(WriterOrErr.getError()));
50 Writer = std::move(WriterOrErr.get());
53 void readProfile(const Module &M, StringRef Profile) {
54 auto ReaderOrErr = SampleProfileReader::create(Profile, Context);
55 ASSERT_TRUE(NoError(ReaderOrErr.getError()));
56 Reader = std::move(ReaderOrErr.get());
57 Reader->collectFuncsToUse(M);
60 void testRoundTrip(SampleProfileFormat Format, bool Remap) {
61 SmallVector<char, 128> ProfilePath;
62 ASSERT_TRUE(NoError(llvm::sys::fs::createTemporaryFile("profile", "", ProfilePath)));
63 StringRef Profile(ProfilePath.data(), ProfilePath.size());
64 createWriter(Format, Profile);
66 StringRef FooName("_Z3fooi");
67 FunctionSamples FooSamples;
68 FooSamples.setName(FooName);
69 FooSamples.addTotalSamples(7711);
70 FooSamples.addHeadSamples(610);
71 FooSamples.addBodySamples(1, 0, 610);
72 FooSamples.addBodySamples(2, 0, 600);
73 FooSamples.addBodySamples(4, 0, 60000);
74 FooSamples.addBodySamples(8, 0, 60351);
75 FooSamples.addBodySamples(10, 0, 605);
77 StringRef BarName("_Z3bari");
78 FunctionSamples BarSamples;
79 BarSamples.setName(BarName);
80 BarSamples.addTotalSamples(20301);
81 BarSamples.addHeadSamples(1437);
82 BarSamples.addBodySamples(1, 0, 1437);
83 // Test how reader/writer handles unmangled names.
84 StringRef MconstructName("_M_construct<char *>");
85 StringRef StringviewName("string_view<std::allocator<char> >");
86 BarSamples.addCalledTargetSamples(1, 0, MconstructName, 1000);
87 BarSamples.addCalledTargetSamples(1, 0, StringviewName, 437);
89 Module M("my_module", Context);
90 FunctionType *fn_type =
91 FunctionType::get(Type::getVoidTy(Context), {}, false);
92 M.getOrInsertFunction(FooName, fn_type);
93 M.getOrInsertFunction(BarName, fn_type);
95 StringMap<FunctionSamples> Profiles;
96 Profiles[FooName] = std::move(FooSamples);
97 Profiles[BarName] = std::move(BarSamples);
99 std::error_code EC;
100 EC = Writer->write(Profiles);
101 ASSERT_TRUE(NoError(EC));
103 Writer->getOutputStream().flush();
105 readProfile(M, Profile);
107 EC = Reader->read();
108 ASSERT_TRUE(NoError(EC));
110 if (Remap) {
111 auto MemBuffer = llvm::MemoryBuffer::getMemBuffer(R"(
112 # Types 'int' and 'long' are equivalent
113 type i l
114 # Function names 'foo' and 'faux' are equivalent
115 name 3foo 4faux
116 )");
117 Reader.reset(new SampleProfileReaderItaniumRemapper(
118 std::move(MemBuffer), Context, std::move(Reader)));
119 FooName = "_Z4fauxi";
120 BarName = "_Z3barl";
122 EC = Reader->read();
123 ASSERT_TRUE(NoError(EC));
126 ASSERT_EQ(2u, Reader->getProfiles().size());
128 FunctionSamples *ReadFooSamples = Reader->getSamplesFor(FooName);
129 ASSERT_TRUE(ReadFooSamples != nullptr);
130 if (Format != SampleProfileFormat::SPF_Compact_Binary) {
131 ASSERT_EQ("_Z3fooi", ReadFooSamples->getName());
133 ASSERT_EQ(7711u, ReadFooSamples->getTotalSamples());
134 ASSERT_EQ(610u, ReadFooSamples->getHeadSamples());
136 FunctionSamples *ReadBarSamples = Reader->getSamplesFor(BarName);
137 ASSERT_TRUE(ReadBarSamples != nullptr);
138 if (Format != SampleProfileFormat::SPF_Compact_Binary) {
139 ASSERT_EQ("_Z3bari", ReadBarSamples->getName());
141 ASSERT_EQ(20301u, ReadBarSamples->getTotalSamples());
142 ASSERT_EQ(1437u, ReadBarSamples->getHeadSamples());
143 ErrorOr<SampleRecord::CallTargetMap> CTMap =
144 ReadBarSamples->findCallTargetMapAt(1, 0);
145 ASSERT_FALSE(CTMap.getError());
147 std::string MconstructGUID;
148 StringRef MconstructRep =
149 getRepInFormat(MconstructName, Format, MconstructGUID);
150 std::string StringviewGUID;
151 StringRef StringviewRep =
152 getRepInFormat(StringviewName, Format, StringviewGUID);
153 ASSERT_EQ(1000u, CTMap.get()[MconstructRep]);
154 ASSERT_EQ(437u, CTMap.get()[StringviewRep]);
156 auto VerifySummary = [](ProfileSummary &Summary) mutable {
157 ASSERT_EQ(ProfileSummary::PSK_Sample, Summary.getKind());
158 ASSERT_EQ(123603u, Summary.getTotalCount());
159 ASSERT_EQ(6u, Summary.getNumCounts());
160 ASSERT_EQ(2u, Summary.getNumFunctions());
161 ASSERT_EQ(1437u, Summary.getMaxFunctionCount());
162 ASSERT_EQ(60351u, Summary.getMaxCount());
164 uint32_t Cutoff = 800000;
165 auto Predicate = [&Cutoff](const ProfileSummaryEntry &PE) {
166 return PE.Cutoff == Cutoff;
168 std::vector<ProfileSummaryEntry> &Details = Summary.getDetailedSummary();
169 auto EightyPerc = find_if(Details, Predicate);
170 Cutoff = 900000;
171 auto NinetyPerc = find_if(Details, Predicate);
172 Cutoff = 950000;
173 auto NinetyFivePerc = find_if(Details, Predicate);
174 Cutoff = 990000;
175 auto NinetyNinePerc = find_if(Details, Predicate);
176 ASSERT_EQ(60000u, EightyPerc->MinCount);
177 ASSERT_EQ(60000u, NinetyPerc->MinCount);
178 ASSERT_EQ(60000u, NinetyFivePerc->MinCount);
179 ASSERT_EQ(610u, NinetyNinePerc->MinCount);
182 ProfileSummary &Summary = Reader->getSummary();
183 VerifySummary(Summary);
185 // Test that conversion of summary to and from Metadata works.
186 Metadata *MD = Summary.getMD(Context);
187 ASSERT_TRUE(MD);
188 ProfileSummary *PS = ProfileSummary::getFromMD(MD);
189 ASSERT_TRUE(PS);
190 VerifySummary(*PS);
191 delete PS;
193 // Test that summary can be attached to and read back from module.
194 M.setProfileSummary(MD);
195 MD = M.getProfileSummary();
196 ASSERT_TRUE(MD);
197 PS = ProfileSummary::getFromMD(MD);
198 ASSERT_TRUE(PS);
199 VerifySummary(*PS);
200 delete PS;
204 TEST_F(SampleProfTest, roundtrip_text_profile) {
205 testRoundTrip(SampleProfileFormat::SPF_Text, false);
208 TEST_F(SampleProfTest, roundtrip_raw_binary_profile) {
209 testRoundTrip(SampleProfileFormat::SPF_Binary, false);
212 TEST_F(SampleProfTest, roundtrip_compact_binary_profile) {
213 testRoundTrip(SampleProfileFormat::SPF_Compact_Binary, false);
216 TEST_F(SampleProfTest, remap_text_profile) {
217 testRoundTrip(SampleProfileFormat::SPF_Text, true);
220 TEST_F(SampleProfTest, remap_raw_binary_profile) {
221 testRoundTrip(SampleProfileFormat::SPF_Binary, true);
224 TEST_F(SampleProfTest, sample_overflow_saturation) {
225 const uint64_t Max = std::numeric_limits<uint64_t>::max();
226 sampleprof_error Result;
228 StringRef FooName("_Z3fooi");
229 FunctionSamples FooSamples;
230 Result = FooSamples.addTotalSamples(1);
231 ASSERT_EQ(Result, sampleprof_error::success);
233 Result = FooSamples.addHeadSamples(1);
234 ASSERT_EQ(Result, sampleprof_error::success);
236 Result = FooSamples.addBodySamples(10, 0, 1);
237 ASSERT_EQ(Result, sampleprof_error::success);
239 Result = FooSamples.addTotalSamples(Max);
240 ASSERT_EQ(Result, sampleprof_error::counter_overflow);
241 ASSERT_EQ(FooSamples.getTotalSamples(), Max);
243 Result = FooSamples.addHeadSamples(Max);
244 ASSERT_EQ(Result, sampleprof_error::counter_overflow);
245 ASSERT_EQ(FooSamples.getHeadSamples(), Max);
247 Result = FooSamples.addBodySamples(10, 0, Max);
248 ASSERT_EQ(Result, sampleprof_error::counter_overflow);
249 ErrorOr<uint64_t> BodySamples = FooSamples.findSamplesAt(10, 0);
250 ASSERT_FALSE(BodySamples.getError());
251 ASSERT_EQ(BodySamples.get(), Max);
254 } // end anonymous namespace