blob: f75f10bae9006f231a2c384c7d14e72e9b46c6fc [file] [log] [blame]
Eugene Zelenkoaaf3f042016-04-28 18:04:41 +00001//===- unittest/ProfileData/SampleProfTest.cpp ------------------*- C++ -*-===//
Nathan Slingerland46cf0f02015-12-10 17:21:42 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Chandler Carruth3c0d6072017-06-06 11:06:56 +000010#include "llvm/ProfileData/SampleProf.h"
Eugene Zelenkoaaf3f042016-04-28 18:04:41 +000011#include "llvm/ADT/StringMap.h"
12#include "llvm/ADT/StringRef.h"
13#include "llvm/IR/LLVMContext.h"
Easwaran Raman1283c1d2016-03-01 18:30:58 +000014#include "llvm/IR/Metadata.h"
Eugene Zelenkoaaf3f042016-04-28 18:04:41 +000015#include "llvm/IR/Module.h"
Nathan Slingerland46cf0f02015-12-10 17:21:42 +000016#include "llvm/ProfileData/SampleProfReader.h"
17#include "llvm/ProfileData/SampleProfWriter.h"
Eugene Zelenkoaaf3f042016-04-28 18:04:41 +000018#include "llvm/Support/Casting.h"
19#include "llvm/Support/ErrorOr.h"
20#include "llvm/Support/MemoryBuffer.h"
21#include "llvm/Support/raw_ostream.h"
Nathan Slingerland46cf0f02015-12-10 17:21:42 +000022#include "gtest/gtest.h"
Eugene Zelenkoaaf3f042016-04-28 18:04:41 +000023#include <string>
Eugene Zelenkoaaf3f042016-04-28 18:04:41 +000024#include <vector>
Nathan Slingerland46cf0f02015-12-10 17:21:42 +000025
26using namespace llvm;
27using namespace sampleprof;
28
29static ::testing::AssertionResult NoError(std::error_code EC) {
30 if (!EC)
31 return ::testing::AssertionSuccess();
32 return ::testing::AssertionFailure() << "error " << EC.value() << ": "
33 << EC.message();
34}
35
36namespace {
37
38struct SampleProfTest : ::testing::Test {
Mehdi Amini8be77072016-04-14 21:59:01 +000039 LLVMContext Context;
Nathan Slingerland46cf0f02015-12-10 17:21:42 +000040 std::unique_ptr<SampleProfileWriter> Writer;
41 std::unique_ptr<SampleProfileReader> Reader;
42
Wei Mi5455b4c2018-09-15 00:04:15 +000043 SampleProfTest() : Writer(), Reader() {}
Nathan Slingerland46cf0f02015-12-10 17:21:42 +000044
Alexander Kornienkobb05e422018-09-17 12:11:01 +000045 void createWriter(SampleProfileFormat Format, StringRef Profile) {
Wei Mi5455b4c2018-09-15 00:04:15 +000046 std::error_code EC;
47 std::unique_ptr<raw_ostream> OS(
48 new raw_fd_ostream(Profile, EC, sys::fs::F_None));
Nathan Slingerland46cf0f02015-12-10 17:21:42 +000049 auto WriterOrErr = SampleProfileWriter::create(OS, Format);
50 ASSERT_TRUE(NoError(WriterOrErr.getError()));
51 Writer = std::move(WriterOrErr.get());
52 }
53
Alexander Kornienkobb05e422018-09-17 12:11:01 +000054 void readProfile(const Module &M, StringRef Profile) {
Mehdi Amini8be77072016-04-14 21:59:01 +000055 auto ReaderOrErr = SampleProfileReader::create(Profile, Context);
Nathan Slingerland46cf0f02015-12-10 17:21:42 +000056 ASSERT_TRUE(NoError(ReaderOrErr.getError()));
57 Reader = std::move(ReaderOrErr.get());
Wei Miec13dea2018-09-14 20:52:59 +000058 Reader->collectFuncsToUse(M);
Nathan Slingerland46cf0f02015-12-10 17:21:42 +000059 }
60
Richard Smith04af5ff2018-10-10 21:31:01 +000061 void testRoundTrip(SampleProfileFormat Format, bool Remap) {
Alexander Kornienkobb05e422018-09-17 12:11:01 +000062 SmallVector<char, 128> ProfilePath;
63 ASSERT_TRUE(NoError(llvm::sys::fs::createTemporaryFile("profile", "", ProfilePath)));
64 StringRef Profile(ProfilePath.data(), ProfilePath.size());
Wei Mi5455b4c2018-09-15 00:04:15 +000065 createWriter(Format, Profile);
Nathan Slingerland46cf0f02015-12-10 17:21:42 +000066
67 StringRef FooName("_Z3fooi");
68 FunctionSamples FooSamples;
Dehao Chen5c299ca2016-03-03 18:09:32 +000069 FooSamples.setName(FooName);
Nathan Slingerland46cf0f02015-12-10 17:21:42 +000070 FooSamples.addTotalSamples(7711);
71 FooSamples.addHeadSamples(610);
72 FooSamples.addBodySamples(1, 0, 610);
Easwaran Raman44878402016-02-19 03:15:33 +000073 FooSamples.addBodySamples(2, 0, 600);
74 FooSamples.addBodySamples(4, 0, 60000);
75 FooSamples.addBodySamples(8, 0, 60351);
76 FooSamples.addBodySamples(10, 0, 605);
Nathan Slingerland46cf0f02015-12-10 17:21:42 +000077
78 StringRef BarName("_Z3bari");
79 FunctionSamples BarSamples;
Dehao Chen5c299ca2016-03-03 18:09:32 +000080 BarSamples.setName(BarName);
Nathan Slingerland46cf0f02015-12-10 17:21:42 +000081 BarSamples.addTotalSamples(20301);
82 BarSamples.addHeadSamples(1437);
83 BarSamples.addBodySamples(1, 0, 1437);
Wei Mi93bc7462018-06-11 22:40:43 +000084 // Test how reader/writer handles unmangled names.
85 StringRef MconstructName("_M_construct<char *>");
86 StringRef StringviewName("string_view<std::allocator<char> >");
87 BarSamples.addCalledTargetSamples(1, 0, MconstructName, 1000);
88 BarSamples.addCalledTargetSamples(1, 0, StringviewName, 437);
Nathan Slingerland46cf0f02015-12-10 17:21:42 +000089
Wei Miec13dea2018-09-14 20:52:59 +000090 Module M("my_module", Context);
91 FunctionType *fn_type =
92 FunctionType::get(Type::getVoidTy(Context), {}, false);
93 M.getOrInsertFunction(FooName, fn_type);
94 M.getOrInsertFunction(BarName, fn_type);
95
Nathan Slingerland46cf0f02015-12-10 17:21:42 +000096 StringMap<FunctionSamples> Profiles;
97 Profiles[FooName] = std::move(FooSamples);
98 Profiles[BarName] = std::move(BarSamples);
99
100 std::error_code EC;
101 EC = Writer->write(Profiles);
102 ASSERT_TRUE(NoError(EC));
103
104 Writer->getOutputStream().flush();
105
Wei Mi5455b4c2018-09-15 00:04:15 +0000106 readProfile(M, Profile);
Nathan Slingerland46cf0f02015-12-10 17:21:42 +0000107
108 EC = Reader->read();
109 ASSERT_TRUE(NoError(EC));
110
Richard Smith04af5ff2018-10-10 21:31:01 +0000111 if (Remap) {
112 auto MemBuffer = llvm::MemoryBuffer::getMemBuffer(R"(
113 # Types 'int' and 'long' are equivalent
114 type i l
115 # Function names 'foo' and 'faux' are equivalent
116 name 3foo 4faux
117 )");
118 Reader.reset(new SampleProfileReaderItaniumRemapper(
119 std::move(MemBuffer), Context, std::move(Reader)));
120 FooName = "_Z4fauxi";
121 BarName = "_Z3barl";
Nathan Slingerland46cf0f02015-12-10 17:21:42 +0000122
Richard Smith04af5ff2018-10-10 21:31:01 +0000123 EC = Reader->read();
124 ASSERT_TRUE(NoError(EC));
125 }
Nathan Slingerland46cf0f02015-12-10 17:21:42 +0000126
Richard Smith04af5ff2018-10-10 21:31:01 +0000127 ASSERT_EQ(2u, Reader->getProfiles().size());
128
129 FunctionSamples *ReadFooSamples = Reader->getSamplesFor(FooName);
130 ASSERT_TRUE(ReadFooSamples != nullptr);
Simon Pilgrim45e56bf2018-12-20 14:09:15 +0000131 if (Format != SampleProfileFormat::SPF_Compact_Binary) {
Richard Smith11acfd42018-12-19 03:24:03 +0000132 ASSERT_EQ("_Z3fooi", ReadFooSamples->getName());
Simon Pilgrim45e56bf2018-12-20 14:09:15 +0000133 }
Richard Smith04af5ff2018-10-10 21:31:01 +0000134 ASSERT_EQ(7711u, ReadFooSamples->getTotalSamples());
135 ASSERT_EQ(610u, ReadFooSamples->getHeadSamples());
136
137 FunctionSamples *ReadBarSamples = Reader->getSamplesFor(BarName);
138 ASSERT_TRUE(ReadBarSamples != nullptr);
Simon Pilgrim45e56bf2018-12-20 14:09:15 +0000139 if (Format != SampleProfileFormat::SPF_Compact_Binary) {
Richard Smith11acfd42018-12-19 03:24:03 +0000140 ASSERT_EQ("_Z3bari", ReadBarSamples->getName());
Simon Pilgrim45e56bf2018-12-20 14:09:15 +0000141 }
Richard Smith04af5ff2018-10-10 21:31:01 +0000142 ASSERT_EQ(20301u, ReadBarSamples->getTotalSamples());
143 ASSERT_EQ(1437u, ReadBarSamples->getHeadSamples());
Wei Mif53ccf32018-03-07 16:45:33 +0000144 ErrorOr<SampleRecord::CallTargetMap> CTMap =
Richard Smith04af5ff2018-10-10 21:31:01 +0000145 ReadBarSamples->findCallTargetMapAt(1, 0);
Wei Mif53ccf32018-03-07 16:45:33 +0000146 ASSERT_FALSE(CTMap.getError());
Wei Mi93bc7462018-06-11 22:40:43 +0000147
148 std::string MconstructGUID;
149 StringRef MconstructRep =
150 getRepInFormat(MconstructName, Format, MconstructGUID);
151 std::string StringviewGUID;
152 StringRef StringviewRep =
153 getRepInFormat(StringviewName, Format, StringviewGUID);
154 ASSERT_EQ(1000u, CTMap.get()[MconstructRep]);
155 ASSERT_EQ(437u, CTMap.get()[StringviewRep]);
Easwaran Raman44878402016-02-19 03:15:33 +0000156
Easwaran Raman30c760d2016-05-19 21:53:28 +0000157 auto VerifySummary = [](ProfileSummary &Summary) mutable {
158 ASSERT_EQ(ProfileSummary::PSK_Sample, Summary.getKind());
159 ASSERT_EQ(123603u, Summary.getTotalCount());
160 ASSERT_EQ(6u, Summary.getNumCounts());
Easwaran Raman1283c1d2016-03-01 18:30:58 +0000161 ASSERT_EQ(2u, Summary.getNumFunctions());
Easwaran Raman418032a2016-03-28 23:14:29 +0000162 ASSERT_EQ(1437u, Summary.getMaxFunctionCount());
Easwaran Raman30c760d2016-05-19 21:53:28 +0000163 ASSERT_EQ(60351u, Summary.getMaxCount());
Easwaran Raman44878402016-02-19 03:15:33 +0000164
Easwaran Raman1283c1d2016-03-01 18:30:58 +0000165 uint32_t Cutoff = 800000;
166 auto Predicate = [&Cutoff](const ProfileSummaryEntry &PE) {
167 return PE.Cutoff == Cutoff;
168 };
169 std::vector<ProfileSummaryEntry> &Details = Summary.getDetailedSummary();
David Majnemerb0353c62016-08-12 00:18:03 +0000170 auto EightyPerc = find_if(Details, Predicate);
Easwaran Raman1283c1d2016-03-01 18:30:58 +0000171 Cutoff = 900000;
David Majnemerb0353c62016-08-12 00:18:03 +0000172 auto NinetyPerc = find_if(Details, Predicate);
Easwaran Raman1283c1d2016-03-01 18:30:58 +0000173 Cutoff = 950000;
David Majnemerb0353c62016-08-12 00:18:03 +0000174 auto NinetyFivePerc = find_if(Details, Predicate);
Easwaran Raman1283c1d2016-03-01 18:30:58 +0000175 Cutoff = 990000;
David Majnemerb0353c62016-08-12 00:18:03 +0000176 auto NinetyNinePerc = find_if(Details, Predicate);
Easwaran Raman1283c1d2016-03-01 18:30:58 +0000177 ASSERT_EQ(60000u, EightyPerc->MinCount);
178 ASSERT_EQ(60000u, NinetyPerc->MinCount);
179 ASSERT_EQ(60000u, NinetyFivePerc->MinCount);
180 ASSERT_EQ(610u, NinetyNinePerc->MinCount);
Easwaran Raman44878402016-02-19 03:15:33 +0000181 };
Easwaran Raman1283c1d2016-03-01 18:30:58 +0000182
Easwaran Raman30c760d2016-05-19 21:53:28 +0000183 ProfileSummary &Summary = Reader->getSummary();
Easwaran Raman1283c1d2016-03-01 18:30:58 +0000184 VerifySummary(Summary);
185
Easwaran Ramanaf640bf2016-03-18 21:29:30 +0000186 // Test that conversion of summary to and from Metadata works.
Mehdi Amini8be77072016-04-14 21:59:01 +0000187 Metadata *MD = Summary.getMD(Context);
Easwaran Raman1283c1d2016-03-01 18:30:58 +0000188 ASSERT_TRUE(MD);
189 ProfileSummary *PS = ProfileSummary::getFromMD(MD);
190 ASSERT_TRUE(PS);
Easwaran Raman30c760d2016-05-19 21:53:28 +0000191 VerifySummary(*PS);
192 delete PS;
Easwaran Ramanaf640bf2016-03-18 21:29:30 +0000193
194 // Test that summary can be attached to and read back from module.
Easwaran Ramanaf640bf2016-03-18 21:29:30 +0000195 M.setProfileSummary(MD);
196 MD = M.getProfileSummary();
197 ASSERT_TRUE(MD);
198 PS = ProfileSummary::getFromMD(MD);
199 ASSERT_TRUE(PS);
Easwaran Raman30c760d2016-05-19 21:53:28 +0000200 VerifySummary(*PS);
201 delete PS;
Nathan Slingerland46cf0f02015-12-10 17:21:42 +0000202 }
203};
204
205TEST_F(SampleProfTest, roundtrip_text_profile) {
Richard Smith04af5ff2018-10-10 21:31:01 +0000206 testRoundTrip(SampleProfileFormat::SPF_Text, false);
Nathan Slingerland46cf0f02015-12-10 17:21:42 +0000207}
208
Wei Mi93bc7462018-06-11 22:40:43 +0000209TEST_F(SampleProfTest, roundtrip_raw_binary_profile) {
Richard Smith04af5ff2018-10-10 21:31:01 +0000210 testRoundTrip(SampleProfileFormat::SPF_Binary, false);
Wei Mi93bc7462018-06-11 22:40:43 +0000211}
212
213TEST_F(SampleProfTest, roundtrip_compact_binary_profile) {
Richard Smith04af5ff2018-10-10 21:31:01 +0000214 testRoundTrip(SampleProfileFormat::SPF_Compact_Binary, false);
215}
216
217TEST_F(SampleProfTest, remap_text_profile) {
218 testRoundTrip(SampleProfileFormat::SPF_Text, true);
219}
220
221TEST_F(SampleProfTest, remap_raw_binary_profile) {
222 testRoundTrip(SampleProfileFormat::SPF_Binary, true);
Nathan Slingerland46cf0f02015-12-10 17:21:42 +0000223}
224
Nathan Slingerlandfd568242015-12-16 21:45:43 +0000225TEST_F(SampleProfTest, sample_overflow_saturation) {
226 const uint64_t Max = std::numeric_limits<uint64_t>::max();
227 sampleprof_error Result;
228
229 StringRef FooName("_Z3fooi");
230 FunctionSamples FooSamples;
231 Result = FooSamples.addTotalSamples(1);
232 ASSERT_EQ(Result, sampleprof_error::success);
233
234 Result = FooSamples.addHeadSamples(1);
235 ASSERT_EQ(Result, sampleprof_error::success);
236
237 Result = FooSamples.addBodySamples(10, 0, 1);
238 ASSERT_EQ(Result, sampleprof_error::success);
239
240 Result = FooSamples.addTotalSamples(Max);
241 ASSERT_EQ(Result, sampleprof_error::counter_overflow);
242 ASSERT_EQ(FooSamples.getTotalSamples(), Max);
243
244 Result = FooSamples.addHeadSamples(Max);
245 ASSERT_EQ(Result, sampleprof_error::counter_overflow);
246 ASSERT_EQ(FooSamples.getHeadSamples(), Max);
247
248 Result = FooSamples.addBodySamples(10, 0, Max);
249 ASSERT_EQ(Result, sampleprof_error::counter_overflow);
250 ErrorOr<uint64_t> BodySamples = FooSamples.findSamplesAt(10, 0);
251 ASSERT_FALSE(BodySamples.getError());
252 ASSERT_EQ(BodySamples.get(), Max);
253}
254
Nathan Slingerland46cf0f02015-12-10 17:21:42 +0000255} // end anonymous namespace