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 //===----------------------------------------------------------------------===//
8 
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/FileSystem.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include "gtest/gtest.h"
23 #include <string>
24 #include <vector>
25 
26 using namespace llvm;
27 using namespace sampleprof;
28 
NoError(std::error_code EC)29 static ::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 
36 namespace {
37 
38 struct SampleProfTest : ::testing::Test {
39   LLVMContext Context;
40   std::unique_ptr<SampleProfileWriter> Writer;
41   std::unique_ptr<SampleProfileReader> Reader;
42 
SampleProfTest__anond00af0ed0111::SampleProfTest43   SampleProfTest() : Writer(), Reader() {}
44 
createWriter__anond00af0ed0111::SampleProfTest45   void createWriter(SampleProfileFormat Format, StringRef Profile) {
46     std::error_code EC;
47     std::unique_ptr<raw_ostream> OS(
48         new raw_fd_ostream(Profile, EC, sys::fs::OF_None));
49     auto WriterOrErr = SampleProfileWriter::create(OS, Format);
50     ASSERT_TRUE(NoError(WriterOrErr.getError()));
51     Writer = std::move(WriterOrErr.get());
52   }
53 
readProfile__anond00af0ed0111::SampleProfTest54   void readProfile(const Module &M, StringRef Profile,
55                    StringRef RemapFile = "") {
56     auto ReaderOrErr = SampleProfileReader::create(
57         std::string(Profile), Context, std::string(RemapFile));
58     ASSERT_TRUE(NoError(ReaderOrErr.getError()));
59     Reader = std::move(ReaderOrErr.get());
60     Reader->collectFuncsFrom(M);
61   }
62 
createRemapFile__anond00af0ed0111::SampleProfTest63   void createRemapFile(SmallVectorImpl<char> &RemapPath, StringRef &RemapFile) {
64     std::error_code EC =
65         llvm::sys::fs::createTemporaryFile("remapfile", "", RemapPath);
66     ASSERT_TRUE(NoError(EC));
67     RemapFile = StringRef(RemapPath.data(), RemapPath.size());
68 
69     std::unique_ptr<raw_fd_ostream> OS(
70         new raw_fd_ostream(RemapFile, EC, sys::fs::OF_None));
71     *OS << R"(
72       # Types 'int' and 'long' are equivalent
73       type i l
74       # Function names 'foo' and 'faux' are equivalent
75       name 3foo 4faux
76     )";
77     OS->close();
78   }
79 
80   // Verify profile summary is consistent in the roundtrip to and from
81   // Metadata. \p AddPartialField is to choose whether the Metadata
82   // contains the IsPartialProfile field which is optional.
verifyProfileSummary__anond00af0ed0111::SampleProfTest83   void verifyProfileSummary(ProfileSummary &Summary, Module &M,
84                             const bool AddPartialField,
85                             const bool AddPartialProfileRatioField) {
86     LLVMContext &Context = M.getContext();
87     const bool IsPartialProfile = Summary.isPartialProfile();
88     const double PartialProfileRatio = Summary.getPartialProfileRatio();
89     auto VerifySummary = [IsPartialProfile, PartialProfileRatio](
90                              ProfileSummary &Summary) mutable {
91       ASSERT_EQ(ProfileSummary::PSK_Sample, Summary.getKind());
92       ASSERT_EQ(137392u, Summary.getTotalCount());
93       ASSERT_EQ(8u, Summary.getNumCounts());
94       ASSERT_EQ(4u, Summary.getNumFunctions());
95       ASSERT_EQ(1437u, Summary.getMaxFunctionCount());
96       ASSERT_EQ(60351u, Summary.getMaxCount());
97       ASSERT_EQ(IsPartialProfile, Summary.isPartialProfile());
98       ASSERT_EQ(PartialProfileRatio, Summary.getPartialProfileRatio());
99 
100       uint32_t Cutoff = 800000;
101       auto Predicate = [&Cutoff](const ProfileSummaryEntry &PE) {
102         return PE.Cutoff == Cutoff;
103       };
104       std::vector<ProfileSummaryEntry> &Details = Summary.getDetailedSummary();
105       auto EightyPerc = find_if(Details, Predicate);
106       Cutoff = 900000;
107       auto NinetyPerc = find_if(Details, Predicate);
108       Cutoff = 950000;
109       auto NinetyFivePerc = find_if(Details, Predicate);
110       Cutoff = 990000;
111       auto NinetyNinePerc = find_if(Details, Predicate);
112       ASSERT_EQ(60000u, EightyPerc->MinCount);
113       ASSERT_EQ(12557u, NinetyPerc->MinCount);
114       ASSERT_EQ(12557u, NinetyFivePerc->MinCount);
115       ASSERT_EQ(610u, NinetyNinePerc->MinCount);
116     };
117     VerifySummary(Summary);
118 
119     // Test that conversion of summary to and from Metadata works.
120     Metadata *MD =
121         Summary.getMD(Context, AddPartialField, AddPartialProfileRatioField);
122     ASSERT_TRUE(MD);
123     ProfileSummary *PS = ProfileSummary::getFromMD(MD);
124     ASSERT_TRUE(PS);
125     VerifySummary(*PS);
126     delete PS;
127 
128     // Test that summary can be attached to and read back from module.
129     M.eraseNamedMetadata(M.getOrInsertModuleFlagsMetadata());
130     M.setProfileSummary(MD, ProfileSummary::PSK_Sample);
131     MD = M.getProfileSummary(/* IsCS */ false);
132     ASSERT_TRUE(MD);
133     PS = ProfileSummary::getFromMD(MD);
134     ASSERT_TRUE(PS);
135     VerifySummary(*PS);
136     delete PS;
137   }
138 
testRoundTrip__anond00af0ed0111::SampleProfTest139   void testRoundTrip(SampleProfileFormat Format, bool Remap, bool UseMD5) {
140     SmallVector<char, 128> ProfilePath;
141     ASSERT_TRUE(NoError(llvm::sys::fs::createTemporaryFile("profile", "", ProfilePath)));
142     StringRef Profile(ProfilePath.data(), ProfilePath.size());
143     createWriter(Format, Profile);
144     if (Format == SampleProfileFormat::SPF_Ext_Binary && UseMD5)
145       static_cast<SampleProfileWriterExtBinary *>(Writer.get())->setUseMD5();
146 
147     StringRef FooName("_Z3fooi");
148     FunctionSamples FooSamples;
149     FooSamples.setName(FooName);
150     FooSamples.addTotalSamples(7711);
151     FooSamples.addHeadSamples(610);
152     FooSamples.addBodySamples(1, 0, 610);
153     FooSamples.addBodySamples(2, 0, 600);
154     FooSamples.addBodySamples(4, 0, 60000);
155     FooSamples.addBodySamples(8, 0, 60351);
156     FooSamples.addBodySamples(10, 0, 605);
157 
158     StringRef BarName("_Z3bari");
159     FunctionSamples BarSamples;
160     BarSamples.setName(BarName);
161     BarSamples.addTotalSamples(20301);
162     BarSamples.addHeadSamples(1437);
163     BarSamples.addBodySamples(1, 0, 1437);
164     // Test how reader/writer handles unmangled names.
165     StringRef MconstructName("_M_construct<char *>");
166     StringRef StringviewName("string_view<std::allocator<char> >");
167     BarSamples.addCalledTargetSamples(1, 0, MconstructName, 1000);
168     BarSamples.addCalledTargetSamples(1, 0, StringviewName, 437);
169 
170     StringRef BazName("_Z3bazi");
171     FunctionSamples BazSamples;
172     BazSamples.setName(BazName);
173     BazSamples.addTotalSamples(12557);
174     BazSamples.addHeadSamples(1257);
175     BazSamples.addBodySamples(1, 0, 12557);
176 
177     StringRef BooName("_Z3booi");
178     FunctionSamples BooSamples;
179     BooSamples.setName(BooName);
180     BooSamples.addTotalSamples(1232);
181     BooSamples.addHeadSamples(1);
182     BooSamples.addBodySamples(1, 0, 1232);
183 
184     StringMap<FunctionSamples> Profiles;
185     Profiles[FooName] = std::move(FooSamples);
186     Profiles[BarName] = std::move(BarSamples);
187     Profiles[BazName] = std::move(BazSamples);
188     Profiles[BooName] = std::move(BooSamples);
189 
190     Module M("my_module", Context);
191     FunctionType *fn_type =
192         FunctionType::get(Type::getVoidTy(Context), {}, false);
193 
194     SmallVector<char, 128> RemapPath;
195     StringRef RemapFile;
196     if (Remap) {
197       createRemapFile(RemapPath, RemapFile);
198       FooName = "_Z4fauxi";
199       BarName = "_Z3barl";
200     }
201 
202     M.getOrInsertFunction(FooName, fn_type);
203     M.getOrInsertFunction(BarName, fn_type);
204     M.getOrInsertFunction(BooName, fn_type);
205 
206     ProfileSymbolList List;
207     if (Format == SampleProfileFormat::SPF_Ext_Binary) {
208       List.add("zoo", true);
209       List.add("moo", true);
210     }
211     Writer->setProfileSymbolList(&List);
212 
213     std::error_code EC;
214     EC = Writer->write(Profiles);
215     ASSERT_TRUE(NoError(EC));
216 
217     Writer->getOutputStream().flush();
218 
219     readProfile(M, Profile, RemapFile);
220     EC = Reader->read();
221     ASSERT_TRUE(NoError(EC));
222 
223     if (Format == SampleProfileFormat::SPF_Ext_Binary) {
224       std::unique_ptr<ProfileSymbolList> ReaderList =
225           Reader->getProfileSymbolList();
226       ReaderList->contains("zoo");
227       ReaderList->contains("moo");
228     }
229 
230     FunctionSamples *ReadFooSamples = Reader->getSamplesFor(FooName);
231     ASSERT_TRUE(ReadFooSamples != nullptr);
232     if (!UseMD5) {
233       ASSERT_EQ("_Z3fooi", ReadFooSamples->getName());
234     }
235     ASSERT_EQ(7711u, ReadFooSamples->getTotalSamples());
236     ASSERT_EQ(610u, ReadFooSamples->getHeadSamples());
237 
238     FunctionSamples *ReadBarSamples = Reader->getSamplesFor(BarName);
239     ASSERT_TRUE(ReadBarSamples != nullptr);
240     if (!UseMD5) {
241       ASSERT_EQ("_Z3bari", ReadBarSamples->getName());
242     }
243     ASSERT_EQ(20301u, ReadBarSamples->getTotalSamples());
244     ASSERT_EQ(1437u, ReadBarSamples->getHeadSamples());
245     ErrorOr<SampleRecord::CallTargetMap> CTMap =
246         ReadBarSamples->findCallTargetMapAt(1, 0);
247     ASSERT_FALSE(CTMap.getError());
248 
249     // Because _Z3bazi is not defined in module M, expect _Z3bazi's profile
250     // is not loaded when the profile is ExtBinary or Compact format because
251     // these formats support loading function profiles on demand.
252     FunctionSamples *ReadBazSamples = Reader->getSamplesFor(BazName);
253     if (Format == SampleProfileFormat::SPF_Ext_Binary ||
254         Format == SampleProfileFormat::SPF_Compact_Binary) {
255       ASSERT_TRUE(ReadBazSamples == nullptr);
256       ASSERT_EQ(3u, Reader->getProfiles().size());
257     } else {
258       ASSERT_TRUE(ReadBazSamples != nullptr);
259       ASSERT_EQ(12557u, ReadBazSamples->getTotalSamples());
260       ASSERT_EQ(4u, Reader->getProfiles().size());
261     }
262 
263     FunctionSamples *ReadBooSamples = Reader->getSamplesFor(BooName);
264     ASSERT_TRUE(ReadBooSamples != nullptr);
265     ASSERT_EQ(1232u, ReadBooSamples->getTotalSamples());
266 
267     std::string MconstructGUID;
268     StringRef MconstructRep =
269         getRepInFormat(MconstructName, UseMD5, MconstructGUID);
270     std::string StringviewGUID;
271     StringRef StringviewRep =
272         getRepInFormat(StringviewName, UseMD5, StringviewGUID);
273     ASSERT_EQ(1000u, CTMap.get()[MconstructRep]);
274     ASSERT_EQ(437u, CTMap.get()[StringviewRep]);
275 
276 
277     ProfileSummary &Summary = Reader->getSummary();
278     Summary.setPartialProfile(true);
279     verifyProfileSummary(Summary, M, true, false);
280 
281     Summary.setPartialProfile(false);
282     verifyProfileSummary(Summary, M, true, false);
283 
284     verifyProfileSummary(Summary, M, false, false);
285 
286     Summary.setPartialProfile(true);
287     Summary.setPartialProfileRatio(0.5);
288     verifyProfileSummary(Summary, M, true, true);
289   }
290 
addFunctionSamples__anond00af0ed0111::SampleProfTest291   void addFunctionSamples(StringMap<FunctionSamples> *Smap, const char *Fname,
292                           uint64_t TotalSamples, uint64_t HeadSamples) {
293     StringRef Name(Fname);
294     FunctionSamples FcnSamples;
295     FcnSamples.setName(Name);
296     FcnSamples.addTotalSamples(TotalSamples);
297     FcnSamples.addHeadSamples(HeadSamples);
298     FcnSamples.addBodySamples(1, 0, HeadSamples);
299     (*Smap)[Name] = FcnSamples;
300   }
301 
setupFcnSamplesForElisionTest__anond00af0ed0111::SampleProfTest302   StringMap<FunctionSamples> setupFcnSamplesForElisionTest(StringRef Policy) {
303     StringMap<FunctionSamples> Smap;
304     addFunctionSamples(&Smap, "foo", uint64_t(20301), uint64_t(1437));
305     if (Policy == "" || Policy == "all")
306       return Smap;
307     addFunctionSamples(&Smap, "foo.bar", uint64_t(20303), uint64_t(1439));
308     if (Policy == "selected")
309       return Smap;
310     addFunctionSamples(&Smap, "foo.llvm.2465", uint64_t(20305), uint64_t(1441));
311     return Smap;
312   }
313 
createFunctionWithSampleProfileElisionPolicy__anond00af0ed0111::SampleProfTest314   void createFunctionWithSampleProfileElisionPolicy(Module *M,
315                                                     const char *Fname,
316                                                     StringRef Policy) {
317     FunctionType *FnType =
318         FunctionType::get(Type::getVoidTy(Context), {}, false);
319     auto Inserted = M->getOrInsertFunction(Fname, FnType);
320     auto Fcn = cast<Function>(Inserted.getCallee());
321     if (Policy != "")
322       Fcn->addFnAttr("sample-profile-suffix-elision-policy", Policy);
323   }
324 
setupModuleForElisionTest__anond00af0ed0111::SampleProfTest325   void setupModuleForElisionTest(Module *M, StringRef Policy) {
326     createFunctionWithSampleProfileElisionPolicy(M, "foo", Policy);
327     createFunctionWithSampleProfileElisionPolicy(M, "foo.bar", Policy);
328     createFunctionWithSampleProfileElisionPolicy(M, "foo.llvm.2465", Policy);
329   }
330 
testSuffixElisionPolicy__anond00af0ed0111::SampleProfTest331   void testSuffixElisionPolicy(SampleProfileFormat Format, StringRef Policy,
332                                const StringMap<uint64_t> &Expected) {
333     SmallVector<char, 128> ProfilePath;
334     std::error_code EC;
335     EC = llvm::sys::fs::createTemporaryFile("profile", "", ProfilePath);
336     ASSERT_TRUE(NoError(EC));
337     StringRef ProfileFile(ProfilePath.data(), ProfilePath.size());
338 
339     Module M("my_module", Context);
340     setupModuleForElisionTest(&M, Policy);
341     StringMap<FunctionSamples> ProfMap = setupFcnSamplesForElisionTest(Policy);
342 
343     // write profile
344     createWriter(Format, ProfileFile);
345     EC = Writer->write(ProfMap);
346     ASSERT_TRUE(NoError(EC));
347     Writer->getOutputStream().flush();
348 
349     // read profile
350     readProfile(M, ProfileFile);
351     EC = Reader->read();
352     ASSERT_TRUE(NoError(EC));
353 
354     for (auto I = Expected.begin(); I != Expected.end(); ++I) {
355       uint64_t Esamples = uint64_t(-1);
356       FunctionSamples *Samples = Reader->getSamplesFor(I->getKey());
357       if (Samples != nullptr)
358         Esamples = Samples->getTotalSamples();
359       ASSERT_EQ(I->getValue(), Esamples);
360     }
361   }
362 };
363 
TEST_F(SampleProfTest,roundtrip_text_profile)364 TEST_F(SampleProfTest, roundtrip_text_profile) {
365   testRoundTrip(SampleProfileFormat::SPF_Text, false, false);
366 }
367 
TEST_F(SampleProfTest,roundtrip_raw_binary_profile)368 TEST_F(SampleProfTest, roundtrip_raw_binary_profile) {
369   testRoundTrip(SampleProfileFormat::SPF_Binary, false, false);
370 }
371 
TEST_F(SampleProfTest,roundtrip_compact_binary_profile)372 TEST_F(SampleProfTest, roundtrip_compact_binary_profile) {
373   testRoundTrip(SampleProfileFormat::SPF_Compact_Binary, false, true);
374 }
375 
TEST_F(SampleProfTest,roundtrip_ext_binary_profile)376 TEST_F(SampleProfTest, roundtrip_ext_binary_profile) {
377   testRoundTrip(SampleProfileFormat::SPF_Ext_Binary, false, false);
378 }
379 
TEST_F(SampleProfTest,roundtrip_md5_ext_binary_profile)380 TEST_F(SampleProfTest, roundtrip_md5_ext_binary_profile) {
381   testRoundTrip(SampleProfileFormat::SPF_Ext_Binary, false, true);
382 }
383 
TEST_F(SampleProfTest,remap_text_profile)384 TEST_F(SampleProfTest, remap_text_profile) {
385   testRoundTrip(SampleProfileFormat::SPF_Text, true, false);
386 }
387 
TEST_F(SampleProfTest,remap_raw_binary_profile)388 TEST_F(SampleProfTest, remap_raw_binary_profile) {
389   testRoundTrip(SampleProfileFormat::SPF_Binary, true, false);
390 }
391 
TEST_F(SampleProfTest,remap_ext_binary_profile)392 TEST_F(SampleProfTest, remap_ext_binary_profile) {
393   testRoundTrip(SampleProfileFormat::SPF_Ext_Binary, true, false);
394 }
395 
TEST_F(SampleProfTest,sample_overflow_saturation)396 TEST_F(SampleProfTest, sample_overflow_saturation) {
397   const uint64_t Max = std::numeric_limits<uint64_t>::max();
398   sampleprof_error Result;
399 
400   FunctionSamples FooSamples;
401   Result = FooSamples.addTotalSamples(1);
402   ASSERT_EQ(Result, sampleprof_error::success);
403 
404   Result = FooSamples.addHeadSamples(1);
405   ASSERT_EQ(Result, sampleprof_error::success);
406 
407   Result = FooSamples.addBodySamples(10, 0, 1);
408   ASSERT_EQ(Result, sampleprof_error::success);
409 
410   Result = FooSamples.addTotalSamples(Max);
411   ASSERT_EQ(Result, sampleprof_error::counter_overflow);
412   ASSERT_EQ(FooSamples.getTotalSamples(), Max);
413 
414   Result = FooSamples.addHeadSamples(Max);
415   ASSERT_EQ(Result, sampleprof_error::counter_overflow);
416   ASSERT_EQ(FooSamples.getHeadSamples(), Max);
417 
418   Result = FooSamples.addBodySamples(10, 0, Max);
419   ASSERT_EQ(Result, sampleprof_error::counter_overflow);
420   ErrorOr<uint64_t> BodySamples = FooSamples.findSamplesAt(10, 0);
421   ASSERT_FALSE(BodySamples.getError());
422   ASSERT_EQ(BodySamples.get(), Max);
423 }
424 
TEST_F(SampleProfTest,default_suffix_elision_text)425 TEST_F(SampleProfTest, default_suffix_elision_text) {
426   // Default suffix elision policy: strip everything after first dot.
427   // This implies that all suffix variants will map to "foo", so
428   // we don't expect to see any entries for them in the sample
429   // profile.
430   StringMap<uint64_t> Expected;
431   Expected["foo"] = uint64_t(20301);
432   Expected["foo.bar"] = uint64_t(-1);
433   Expected["foo.llvm.2465"] = uint64_t(-1);
434   testSuffixElisionPolicy(SampleProfileFormat::SPF_Text, "", Expected);
435 }
436 
TEST_F(SampleProfTest,default_suffix_elision_compact_binary)437 TEST_F(SampleProfTest, default_suffix_elision_compact_binary) {
438   // Default suffix elision policy: strip everything after first dot.
439   // This implies that all suffix variants will map to "foo", so
440   // we don't expect to see any entries for them in the sample
441   // profile.
442   StringMap<uint64_t> Expected;
443   Expected["foo"] = uint64_t(20301);
444   Expected["foo.bar"] = uint64_t(-1);
445   Expected["foo.llvm.2465"] = uint64_t(-1);
446   testSuffixElisionPolicy(SampleProfileFormat::SPF_Compact_Binary, "",
447                           Expected);
448 }
449 
TEST_F(SampleProfTest,selected_suffix_elision_text)450 TEST_F(SampleProfTest, selected_suffix_elision_text) {
451   // Profile is created and searched using the "selected"
452   // suffix elision policy: we only strip a .XXX suffix if
453   // it matches a pattern known to be generated by the compiler
454   // (e.g. ".llvm.<digits>").
455   StringMap<uint64_t> Expected;
456   Expected["foo"] = uint64_t(20301);
457   Expected["foo.bar"] = uint64_t(20303);
458   Expected["foo.llvm.2465"] = uint64_t(-1);
459   testSuffixElisionPolicy(SampleProfileFormat::SPF_Text, "selected", Expected);
460 }
461 
TEST_F(SampleProfTest,selected_suffix_elision_compact_binary)462 TEST_F(SampleProfTest, selected_suffix_elision_compact_binary) {
463   // Profile is created and searched using the "selected"
464   // suffix elision policy: we only strip a .XXX suffix if
465   // it matches a pattern known to be generated by the compiler
466   // (e.g. ".llvm.<digits>").
467   StringMap<uint64_t> Expected;
468   Expected["foo"] = uint64_t(20301);
469   Expected["foo.bar"] = uint64_t(20303);
470   Expected["foo.llvm.2465"] = uint64_t(-1);
471   testSuffixElisionPolicy(SampleProfileFormat::SPF_Compact_Binary, "selected",
472                           Expected);
473 }
474 
TEST_F(SampleProfTest,none_suffix_elision_text)475 TEST_F(SampleProfTest, none_suffix_elision_text) {
476   // Profile is created and searched using the "none"
477   // suffix elision policy: no stripping of suffixes at all.
478   // Here we expect to see all variants in the profile.
479   StringMap<uint64_t> Expected;
480   Expected["foo"] = uint64_t(20301);
481   Expected["foo.bar"] = uint64_t(20303);
482   Expected["foo.llvm.2465"] = uint64_t(20305);
483   testSuffixElisionPolicy(SampleProfileFormat::SPF_Text, "none", Expected);
484 }
485 
TEST_F(SampleProfTest,none_suffix_elision_compact_binary)486 TEST_F(SampleProfTest, none_suffix_elision_compact_binary) {
487   // Profile is created and searched using the "none"
488   // suffix elision policy: no stripping of suffixes at all.
489   // Here we expect to see all variants in the profile.
490   StringMap<uint64_t> Expected;
491   Expected["foo"] = uint64_t(20301);
492   Expected["foo.bar"] = uint64_t(20303);
493   Expected["foo.llvm.2465"] = uint64_t(20305);
494   testSuffixElisionPolicy(SampleProfileFormat::SPF_Compact_Binary, "none",
495                           Expected);
496 }
497 
498 } // end anonymous namespace
499